summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp256
1 files changed, 133 insertions, 123 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 4a084c714..b9aa3c027 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -3,6 +3,7 @@
#include "ast-legalize.h"
#include "ir-insts.h"
+#include "legalize-types.h"
#include "lower-to-ir.h"
#include "mangle.h"
#include "name.h"
@@ -1236,13 +1237,6 @@ struct EmitVisitor
emitTypeImpl(type->valueType, arg.declarator);
}
- void visitFilteredTupleType(FilteredTupleType* type, TypeEmitArg const& arg)
- {
- auto declarator = arg.declarator;
- emit(getMangledTypeName(type));
- EmitDeclarator(declarator);
- }
-
void EmitType(
RefPtr<Type> type,
SourceLoc const& typeLoc,
@@ -2952,7 +2946,7 @@ struct EmitVisitor
Decl* decl = declRef.getDecl();
if(irDeclSet->Contains(decl))
{
- emit(getMangledName(declRef));
+ emit(getIRName(declRef));
return;
}
}
@@ -3605,10 +3599,6 @@ struct EmitVisitor
// The data type that describes where stuff in the constant buffer should go
RefPtr<Type> dataType = parameterGroupType->elementType;
- // We expect/require the data type to be a user-defined `struct` type
- auto declRefType = dataType->As<DeclRefType>();
- SLANG_RELEASE_ASSERT(declRefType);
-
// We expect to always have layout information
layout = maybeFetchLayout(varDecl, layout);
SLANG_RELEASE_ASSERT(layout);
@@ -3642,27 +3632,48 @@ struct EmitVisitor
emitHLSLRegisterSemantic(*info);
Emit("\n{\n");
- if (auto structRef = declRefType->declRef.As<StructDecl>())
- {
- int fieldCounter = 0;
- for (auto field : getMembersOfType<StructField>(structRef))
+ // We expect the data type to be a user-defined `struct` type,
+ // but it might also be a "filtered" type that represents the
+ // case where only some fields of the original type are valid
+ // to appear inside of a `struct`.
+ if (auto declRefType = dataType->As<DeclRefType>())
+ {
+ if (auto structRef = declRefType->declRef.As<StructDecl>())
{
- int fieldIndex = fieldCounter++;
+ int fieldCounter = 0;
- emitVarDeclHead(field);
+ for (auto field : getMembersOfType<StructField>(structRef))
+ {
+ int fieldIndex = fieldCounter++;
+
+ // Skip fields that have `void` type, since these represent
+ // declarations that got legalized out of existence.
+ if(GetType(field)->Equals(getSession()->getVoidType()))
+ continue;
- RefPtr<VarLayout> fieldLayout = structTypeLayout->fields[fieldIndex];
- SLANG_RELEASE_ASSERT(fieldLayout->varDecl.GetName() == field.GetName());
+ emitVarDeclHead(field);
- // Emit explicit layout annotations for every field
- emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
+ RefPtr<VarLayout> fieldLayout = structTypeLayout->fields[fieldIndex];
+ SLANG_RELEASE_ASSERT(fieldLayout->varDecl.GetName() == field.GetName());
- emitVarDeclInit(field);
+ // Emit explicit layout annotations for every field
+ emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
- Emit(";\n");
+ emitVarDeclInit(field);
+
+ Emit(";\n");
+ }
+ }
+ else
+ {
+ SLANG_UNEXPECTED("unexpected element type for parameter group");
}
}
+ else
+ {
+ SLANG_UNEXPECTED("unexpected element type for parameter group");
+ }
Emit("}\n");
}
@@ -3773,10 +3784,6 @@ struct EmitVisitor
// The data type that describes where stuff in the constant buffer should go
RefPtr<Type> dataType = parameterGroupType->elementType;
- // We expect/require the data type to be a user-defined `struct` type
- auto declRefType = dataType->As<DeclRefType>();
- SLANG_RELEASE_ASSERT(declRefType);
-
// We expect the layout, if present, to be for a structured type...
RefPtr<StructTypeLayout> structTypeLayout;
if (layout)
@@ -3827,26 +3834,54 @@ struct EmitVisitor
}
Emit("\n{\n");
- if (auto structRef = declRefType->declRef.As<StructDecl>())
+
+ // We expect the data type to be a user-defined `struct` type,
+ // but it might also be a "filtered" type that represents the
+ // case where only some fields of the original type are valid
+ // to appear inside of a `struct`.
+ if (auto declRefType = dataType->As<DeclRefType>())
{
- for (auto field : getMembersOfType<StructField>(structRef))
+
+ if (auto structRef = declRefType->declRef.As<StructDecl>())
{
- if (structTypeLayout)
+ int fieldCounter = 0;
+ for (auto field : getMembersOfType<StructField>(structRef))
{
- RefPtr<VarLayout> fieldLayout;
- structTypeLayout->mapVarToLayout.TryGetValue(field.getDecl(), fieldLayout);
- // assert(fieldLayout);
+ int fieldIndex = fieldCounter++;
+
+ // Skip fields that have `void` type, since these represent
+ // declarations that got legalized out of existence.
+ if(GetType(field)->Equals(getSession()->getVoidType()))
+ continue;
+
+ if (structTypeLayout)
+ {
+ RefPtr<VarLayout> fieldLayout = structTypeLayout->fields[fieldIndex];
+ // assert(fieldLayout);
+
+ // TODO(tfoley): We may want to emit *some* of these,
+ // some of the time...
+ // emitGLSLLayoutQualifiers(fieldLayout);
+ }
- // TODO(tfoley): We may want to emit *some* of these,
- // some of the time...
- // emitGLSLLayoutQualifiers(fieldLayout);
- }
- EmitVarDeclCommon(field);
+ EmitVarDeclCommon(field);
- Emit(";\n");
+ Emit(";\n");
+ }
+ }
+ else
+ {
+ SLANG_UNEXPECTED("unexpected element type for parameter group");
}
}
+ else
+ {
+ SLANG_UNEXPECTED("unexpected element type for parameter group");
+ }
+
+
+
Emit("}");
if( varDecl->getNameLoc().isValid() )
@@ -3890,13 +3925,10 @@ struct EmitVisitor
}
}
- // Skip fields that have been tuple-ified and don't contribute
- // any fields of "ordinary" type.
- if (auto tupleFieldMod = decl->FindModifier<TupleFieldModifier>())
- {
- if (!tupleFieldMod->hasAnyNonTupleFields)
- return;
- }
+ // Skip fields that have `void` type, since these may be introduced
+ // as part of type leglaization.
+ if(decl->getType()->Equals(getSession()->getVoidType()))
+ return;
RefPtr<VarLayout> layout = arg.layout;
layout = maybeFetchLayout(decl, layout);
@@ -4129,16 +4161,6 @@ emitDeclImpl(decl, nullptr);
String getIRName(Decl* decl)
{
- // It is a bit ugly, but we need a deterministic way
- // to get a name for things when emitting from the IR
- // that won't conflict with any keywords, builtins, etc.
- // in the target language.
- //
- // Eventually we should accomplish this by using
- // mangled names everywhere, but that complicates things
- // when we are also using direct comparison to fxc/glslang
- // output for some of our tests.
- //
// TODO: need a flag to get rid of the step that adds
// a prefix here, so that we can get "clean" output
// when needed.
@@ -4155,7 +4177,27 @@ emitDeclImpl(decl, nullptr);
String getIRName(DeclRefBase const& declRef)
{
- return getIRName(declRef.decl);
+ // It is a bit ugly, but we need a deterministic way
+ // to get a name for things when emitting from the IR
+ // that won't conflict with any keywords, builtins, etc.
+ // in the target language.
+ //
+ // Eventually we should accomplish this by using
+ // mangled names everywhere, but that complicates things
+ // when we are also using direct comparison to fxc/glslang
+ // output for some of our tests.
+ //
+
+ String name;
+ if (context->shared->entryPoint->compileRequest->compileFlags & SLANG_COMPILE_FLAG_NO_MANGLING)
+ {
+ name.append(getText(declRef.GetName()));
+ }
+ else
+ {
+ name.append(getMangledName(declRef));
+ }
+ return name;
}
String getGLSLSystemValueName(
@@ -6279,9 +6321,12 @@ emitDeclImpl(decl, nullptr);
auto fieldLayout = structTypeLayout->fields[fieldIndex++];
+ auto fieldType = GetType(ff);
+ if(fieldType->Equals(getSession()->getVoidType()))
+ continue;
+
emitIRVarModifiers(ctx, fieldLayout);
- auto fieldType = GetType(ff);
emitIRType(ctx, fieldType, getIRName(ff));
emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
@@ -6290,26 +6335,6 @@ emitDeclImpl(decl, nullptr);
}
}
}
- else if (auto filteredTupleType = elementType->As<FilteredTupleType>())
- {
- auto structTypeLayout = typeLayout.As<StructTypeLayout>();
- assert(structTypeLayout);
-
- for (auto ee : filteredTupleType->elements)
- {
- RefPtr<VarLayout> fieldLayout;
- structTypeLayout->mapVarToLayout.TryGetValue(ee.fieldDeclRef, fieldLayout);
-
- emitIRVarModifiers(ctx, fieldLayout);
-
- auto fieldType = ee.type;
- emitIRType(ctx, fieldType, getIRName(ee.fieldDeclRef));
-
- emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
-
- emit(";\n");
- }
- }
else
{
emit("/* unexpected */");
@@ -6376,9 +6401,12 @@ emitDeclImpl(decl, nullptr);
auto fieldLayout = structTypeLayout->fields[fieldIndex++];
+ auto fieldType = GetType(ff);
+ if(fieldType->Equals(getSession()->getVoidType()))
+ continue;
+
emitIRVarModifiers(ctx, fieldLayout);
- auto fieldType = GetType(ff);
emitIRType(ctx, fieldType, getIRName(ff));
// emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
@@ -6589,7 +6617,7 @@ emitDeclImpl(decl, nullptr);
}
Emit("struct ");
- emit(declRef.GetName());
+ EmitDeclRef(declRef);
Emit("\n{\n");
for( auto ff : GetFields(declRef) )
{
@@ -6597,6 +6625,11 @@ emitDeclImpl(decl, nullptr);
continue;
auto fieldType = GetType(ff);
+
+ // Skip `void` fields that might have been created by legalization.
+ if(fieldType->Equals(getSession()->getVoidType()))
+ continue;
+
emitIRType(ctx, fieldType, getIRName(ff));
EmitSemantics(ff.getDecl());
@@ -6655,43 +6688,6 @@ emitDeclImpl(decl, nullptr);
ensureStructDecl(ctx, structDeclRef);
}
}
- else if (auto filteredTupleType = type->As<FilteredTupleType>())
- {
- // First, ensure that the element types are ready:
- for (auto ee : filteredTupleType->elements)
- {
- if (ee.type)
- {
- emitIRUsedType(ctx, ee.type);
- }
- }
-
- // Now, we want to ensure we've emitted a
- // matching `struct` type declaration.
-
- String mangledName = getMangledTypeName(filteredTupleType);
- if (!ctx->shared->irTupleTypes.Contains(mangledName))
- {
- ctx->shared->irTupleTypes.Add(mangledName);
-
- // Emit the damn `struct` decl...
-
- Emit("struct ");
- emit(mangledName);
- Emit("\n{\n");
- for( auto ee : filteredTupleType->elements )
- {
- if (!ee.type)
- continue;
-
- emitIRType(ctx, ee.type, getIRName(ee.fieldDeclRef));
-
- emit(";\n");
- }
- Emit("};\n");
-
- }
- }
else
{}
}
@@ -6846,7 +6842,8 @@ StructTypeLayout* getGlobalStructLayout(
}
void legalizeTypes(
- IRModule* module);
+ TypeLegalizationContext* context,
+ IRModule* module);
String emitEntryPoint(
EntryPointRequest* entryPoint,
@@ -6937,6 +6934,9 @@ String emitEntryPoint(
// Next we will check for case (2a):
else if (!(translationUnit->compileRequest->compileFlags & SLANG_COMPILE_FLAG_USE_IR))
{
+ TypeLegalizationContext typeLegalizationContext;
+ typeLegalizationContext.session = entryPoint->compileRequest->mSession;
+
// This case means the user has opted out of using the IR (so we can't use the
// cases below), but they either turned on semantic checking *or* imported some
// Slang code, so they can't use the case above.
@@ -6958,7 +6958,8 @@ String emitEntryPoint(
programLayout,
target,
&sharedContext.extensionUsageTracker,
- nullptr);
+ nullptr,
+ &typeLegalizationContext);
sharedContext.program = lowered.program;
// Note that we emit the main body code of the program *before*
@@ -6976,6 +6977,9 @@ String emitEntryPoint(
// are certain steps that need to be shared.
else
{
+ TypeLegalizationContext typeLegalizationContext;
+ typeLegalizationContext.session = entryPoint->compileRequest->mSession;
+
// We are going to create a fresh IR module that we will use to
// clone any code needed by the user's entry point.
IRSpecializationState* irSpecializationState = createIRSpecializationState(
@@ -6985,6 +6989,8 @@ String emitEntryPoint(
targetRequest);
IRModule* irModule = getIRModule(irSpecializationState);
+ typeLegalizationContext.irModule = irModule;
+
LoweredEntryPoint lowered;
if(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING)
{
@@ -7002,7 +7008,8 @@ String emitEntryPoint(
programLayout,
target,
&sharedContext.extensionUsageTracker,
- irSpecializationState);
+ irSpecializationState,
+ &typeLegalizationContext);
}
else
{
@@ -7044,7 +7051,9 @@ String emitEntryPoint(
// we need to ensure that the code only uses types
// that are legal on the chosen target.
//
- legalizeTypes(irModule);
+ legalizeTypes(
+ &typeLegalizationContext,
+ irModule);
// Debugging output of legalization
#if 0
@@ -7053,6 +7062,8 @@ String emitEntryPoint(
fprintf(stderr, "###\n");
#endif
+ sharedContext.irDeclSetForAST = &lowered.irDecls;
+
// After all of the required optimization and legalization
// passes have been performed, we can emit target code from
// the IR module.
@@ -7065,7 +7076,6 @@ String emitEntryPoint(
// that we need to output, we'll do it now.
if (translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING)
{
- sharedContext.irDeclSetForAST = &lowered.irDecls;
visitor.EmitDeclsInContainer(lowered.program);
}