summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-04-11 16:18:29 -0700
committerGitHub <noreply@github.com>2018-04-11 16:18:29 -0700
commitbaf194e7456ba4568dcf11249896af35b3ce18cc (patch)
treef75e20db450100d41bfa9c384a8bab0fdc28a749 /source/slang/emit.cpp
parent6322983fa4dc84ef1e9dd8fad54d4c1580436e67 (diff)
Introduce an IR-level type system (#481)
* Introduce an IR-level type system Up to this point, the Slang IR has used the front-end type system to represent types in the IR. As a result (but ultimately more importantly) the IR representation of generics and specialization has used AST-level concepts embedded in the IR. For example, to express the specialization of `vector<T,N>` to a concrete type `float` for `T`, we needed an IR operation that could represent the specialization, with operands that somehow represented the type argument `float`. The whole thing was very complicated. The big idea of this change is to introduce a new representation in which types in the IR are just ordinary instructions, so that using them as operands makes sense. The hierarchy of IR types closely mirrors the AST-side hierarchy for now, and that will probably be something we should maintain going forward. In order to make these changes work, though, I also had to do major overhauls of things like the way substitutions are performed, how we check interface conformances, the way lookup through interface types is done, etc. etc. This is a big change, and unfortunately any attempt to summarize it in the commit message wouldn't do it justice. * Fix 64-bit build warning * Fix up some clang warnings/errors
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp1538
1 files changed, 704 insertions, 834 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 15f295740..28fb0b551 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -282,7 +282,6 @@ static EOpInfo const* const kInfixOpInfos[] =
&kEOp_Mod,
};
-
//
// represents a declarator for use in emitting types
@@ -302,16 +301,10 @@ struct EDeclarator
SourceLoc loc;
// Used for `Flavor::Array`
- IntVal* elementCount;
-};
-
-struct TypeEmitArg
-{
- EDeclarator* declarator;
+ IRInst* elementCount;
};
struct EmitVisitor
- : TypeVisitorWithArg<EmitVisitor, TypeEmitArg>
{
EmitContext* context;
EmitVisitor(EmitContext* context)
@@ -466,23 +459,6 @@ struct EmitVisitor
emitName(name, SourceLoc());
}
- void emitName(
- Decl* decl,
- SourceLoc const& loc)
- {
- if(auto name = decl->getName())
- emitName(name, loc);
-
- Emit("_S");
- Emit(getID(decl));
- }
-
- void emitName(
- Decl* decl)
- {
- emitName(decl, SourceLoc());
- }
-
void Emit(IntegerLiteralValue value)
{
char buffer[32];
@@ -752,22 +728,6 @@ struct EmitVisitor
// Types
//
- void Emit(RefPtr<IntVal> val)
- {
- if(auto constantIntVal = val.As<ConstantIntVal>())
- {
- Emit(constantIntVal->value);
- }
- else if(auto varRefVal = val.As<GenericParamIntVal>())
- {
- EmitDeclRef(varRefVal->declRef);
- }
- else
- {
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unknown type of integer constant value");
- }
- }
-
void EmitDeclarator(EDeclarator* declarator)
{
if (!declarator) return;
@@ -785,7 +745,7 @@ struct EmitVisitor
Emit("[");
if(auto elementCount = declarator->elementCount)
{
- Emit(elementCount);
+ EmitVal(elementCount);
}
Emit("]");
break;
@@ -802,41 +762,35 @@ struct EmitVisitor
}
void emitGLSLTypePrefix(
- RefPtr<Type> type)
+ IRType* type)
{
- if(auto basicElementType = type->As<BasicExpressionType>())
+ switch (type->op)
{
- switch (basicElementType->baseType)
- {
- case BaseType::Float:
- // no prefix
- break;
+ case kIROp_FloatType:
+ // no prefix
+ break;
- case BaseType::Int: Emit("i"); break;
- case BaseType::UInt: Emit("u"); break;
- case BaseType::Bool: Emit("b"); break;
- case BaseType::Double: Emit("d"); break;
- default:
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled GLSL type prefix");
- break;
- }
- }
- else if(auto vectorType = type->As<VectorExpressionType>())
- {
- emitGLSLTypePrefix(vectorType->elementType);
- }
- else if(auto matrixType = type->As<MatrixExpressionType>())
- {
- emitGLSLTypePrefix(matrixType->getElementType());
- }
- else
- {
+ case kIROp_IntType: Emit("i"); break;
+ case kIROp_UIntType: Emit("u"); break;
+ case kIROp_BoolType: Emit("b"); break;
+ case kIROp_DoubleType: Emit("d"); break;
+
+ case kIROp_VectorType:
+ emitGLSLTypePrefix(cast<IRVectorType>(type)->getElementType());
+ break;
+
+ case kIROp_MatrixType:
+ emitGLSLTypePrefix(cast<IRMatrixType>(type)->getElementType());
+ break;
+
+ default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled GLSL type prefix");
+ break;
}
}
void emitHLSLTextureType(
- RefPtr<TextureTypeBase> texType)
+ IRTextureTypeBase* texType)
{
switch(texType->getAccess())
{
@@ -885,15 +839,15 @@ struct EmitVisitor
Emit("Array");
}
Emit("<");
- EmitType(texType->elementType);
+ EmitType(texType->getElementType());
Emit(" >");
}
void emitGLSLTextureOrTextureSamplerType(
- RefPtr<TextureTypeBase> type,
- char const* baseName)
+ IRTextureTypeBase* type,
+ char const* baseName)
{
- emitGLSLTypePrefix(type->elementType);
+ emitGLSLTypePrefix(type->getElementType());
Emit(baseName);
switch (type->GetBaseShape())
@@ -919,7 +873,7 @@ struct EmitVisitor
}
void emitGLSLTextureType(
- RefPtr<TextureType> texType)
+ IRTextureType* texType)
{
switch(texType->getAccess())
{
@@ -935,19 +889,19 @@ struct EmitVisitor
}
void emitGLSLTextureSamplerType(
- RefPtr<TextureSamplerType> type)
+ IRTextureSamplerType* type)
{
emitGLSLTextureOrTextureSamplerType(type, "sampler");
}
void emitGLSLImageType(
- RefPtr<GLSLImageType> type)
+ IRGLSLImageType* type)
{
emitGLSLTextureOrTextureSamplerType(type, "image");
}
void emitTextureType(
- RefPtr<TextureType> texType)
+ IRTextureType* texType)
{
switch(context->shared->target)
{
@@ -966,7 +920,7 @@ struct EmitVisitor
}
void emitTextureSamplerType(
- RefPtr<TextureSamplerType> type)
+ IRTextureSamplerType* type)
{
switch(context->shared->target)
{
@@ -981,7 +935,7 @@ struct EmitVisitor
}
void emitImageType(
- RefPtr<GLSLImageType> type)
+ IRGLSLImageType* type)
{
switch(context->shared->target)
{
@@ -999,79 +953,27 @@ struct EmitVisitor
}
}
- void emitTypeImpl(RefPtr<Type> type, EDeclarator* declarator)
- {
- TypeEmitArg arg;
- arg.declarator = declarator;
-
- TypeVisitorWithArg::dispatch(type, arg);
- }
-
-#define UNEXPECTED(NAME) \
- void visit##NAME(NAME*, TypeEmitArg const& arg) \
- { Emit(#NAME); EmitDeclarator(arg.declarator); }
-
- UNEXPECTED(ErrorType);
- UNEXPECTED(OverloadGroupType);
- UNEXPECTED(FuncType);
- UNEXPECTED(TypeType);
- UNEXPECTED(GenericDeclRefType);
- UNEXPECTED(InitializerListType);
-
- UNEXPECTED(IRBasicBlockType);
- UNEXPECTED(PtrType);
-
-#undef UNEXPECTED
-
- void visitNamedExpressionType(NamedExpressionType* type, TypeEmitArg const& arg)
- {
- // We will always emit the actual type referenced by
- // a named type declaration, rather than try to produce
- // equivalent `typedef` declarations in the output.
-
- emitTypeImpl(GetType(type->declRef), arg.declarator);
- }
-
- void visitBasicExpressionType(BasicExpressionType* basicType, TypeEmitArg const& arg)
- {
- auto declarator = arg.declarator;
- switch (basicType->baseType)
- {
- case BaseType::Void: Emit("void"); break;
- case BaseType::Int: Emit("int"); break;
- case BaseType::Float: Emit("float"); break;
- case BaseType::UInt: Emit("uint"); break;
- case BaseType::Bool: Emit("bool"); break;
- case BaseType::Double: Emit("double"); break;
- default:
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled scalar type");
- break;
- }
-
- EmitDeclarator(declarator);
- }
- void visitVectorExpressionType(VectorExpressionType* vecType, TypeEmitArg const& arg)
+ void emitVectorTypeImpl(IRVectorType* vecType)
{
- auto declarator = arg.declarator;
switch(context->shared->target)
{
case CodeGenTarget::GLSL:
case CodeGenTarget::GLSL_Vulkan:
case CodeGenTarget::GLSL_Vulkan_OneDesc:
{
- emitGLSLTypePrefix(vecType->elementType);
+ emitGLSLTypePrefix(vecType->getElementType());
Emit("vec");
- Emit(vecType->elementCount);
+ EmitVal(vecType->getElementCount());
}
break;
case CodeGenTarget::HLSL:
// TODO(tfoley): should really emit these with sugar
Emit("vector<");
- EmitType(vecType->elementType);
+ EmitType(vecType->getElementType());
Emit(",");
- Emit(vecType->elementCount);
+ EmitVal(vecType->getElementCount());
Emit(">");
break;
@@ -1079,13 +981,10 @@ struct EmitVisitor
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled code generation target");
break;
}
-
- EmitDeclarator(declarator);
}
- void visitMatrixExpressionType(MatrixExpressionType* matType, TypeEmitArg const& arg)
+ void emitMatrixTypeImpl(IRMatrixType* matType)
{
- auto declarator = arg.declarator;
switch(context->shared->target)
{
case CodeGenTarget::GLSL:
@@ -1094,11 +993,11 @@ struct EmitVisitor
{
emitGLSLTypePrefix(matType->getElementType());
Emit("mat");
- Emit(matType->getRowCount());
+ EmitVal(matType->getRowCount());
// TODO(tfoley): only emit the next bit
// for non-square matrix
Emit("x");
- Emit(matType->getColumnCount());
+ EmitVal(matType->getColumnCount());
}
break;
@@ -1107,9 +1006,9 @@ struct EmitVisitor
Emit("matrix<");
EmitType(matType->getElementType());
Emit(",");
- Emit(matType->getRowCount());
+ EmitVal(matType->getRowCount());
Emit(",");
- Emit(matType->getColumnCount());
+ EmitVal(matType->getColumnCount());
Emit("> ");
break;
@@ -1117,42 +1016,18 @@ struct EmitVisitor
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled code generation target");
break;
}
-
- EmitDeclarator(declarator);
}
- void visitTextureType(TextureType* texType, TypeEmitArg const& arg)
+ void emitSamplerStateType(IRSamplerStateTypeBase* samplerStateType)
{
- auto declarator = arg.declarator;
- emitTextureType(texType);
- EmitDeclarator(declarator);
- }
-
- void visitTextureSamplerType(TextureSamplerType* textureSamplerType, TypeEmitArg const& arg)
- {
- auto declarator = arg.declarator;
- emitTextureSamplerType(textureSamplerType);
- EmitDeclarator(declarator);
- }
-
- void visitGLSLImageType(GLSLImageType* imageType, TypeEmitArg const& arg)
- {
- auto declarator = arg.declarator;
- emitImageType(imageType);
- EmitDeclarator(declarator);
- }
-
- void visitSamplerStateType(SamplerStateType* samplerStateType, TypeEmitArg const& arg)
- {
- auto declarator = arg.declarator;
switch(context->shared->target)
{
case CodeGenTarget::HLSL:
default:
- switch (samplerStateType->flavor)
+ switch (samplerStateType->op)
{
- case SamplerStateFlavor::SamplerState: Emit("SamplerState"); break;
- case SamplerStateFlavor::SamplerComparisonState: Emit("SamplerComparisonState"); break;
+ case kIROp_SamplerStateType: Emit("SamplerState"); break;
+ case kIROp_SamplerComparisonStateType: Emit("SamplerComparisonState"); break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled sampler state flavor");
break;
@@ -1160,10 +1035,10 @@ struct EmitVisitor
break;
case CodeGenTarget::GLSL:
- switch (samplerStateType->flavor)
+ switch (samplerStateType->op)
{
- case SamplerStateFlavor::SamplerState: Emit("sampler"); break;
- case SamplerStateFlavor::SamplerComparisonState: Emit("samplerShadow"); break;
+ case kIROp_SamplerStateType: Emit("sampler"); break;
+ case kIROp_SamplerComparisonStateType: Emit("samplerShadow"); break;
default:
SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled sampler state flavor");
break;
@@ -1171,69 +1046,217 @@ struct EmitVisitor
break;
break;
}
+ }
+
+ void emitStructuredBufferType(IRHLSLStructuredBufferTypeBase* type)
+ {
+ switch(context->shared->target)
+ {
+ case CodeGenTarget::HLSL:
+ default:
+ {
+ switch (type->op)
+ {
+ case kIROp_HLSLStructuredBufferType: Emit("StructuredBuffer"); break;
+ case kIROp_HLSLRWStructuredBufferType: Emit("RWStructuredBuffer"); break;
+ case kIROp_HLSLAppendStructuredBufferType: Emit("AppendStructuredBuffer"); break;
+ case kIROp_HLSLConsumeStructuredBufferType: Emit("ConsumeStructuredBuffer"); break;
+
+ default:
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled structured buffer type");
+ break;
+ }
- EmitDeclarator(declarator);
+ Emit("<");
+ EmitType(type->getElementType());
+ Emit(" >");
+ }
+ break;
+
+ case CodeGenTarget::GLSL:
+ // TODO: We desugar global variables with structured-buffer type into GLSL
+ // `buffer` declarations, but we don't currently handle structured-buffer types
+ // in other contexts (e.g., as function parameters). The simplest thing to do
+ // would be to emit a `StructuredBuffer<Foo>` as `Foo[]` and `RWStructuredBuffer<Foo>`
+ // as `in out Foo[]`, but that is starting to get into the realm of transformations
+ // that should really be handled during legalization, rather than during emission.
+ //
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "structured buffer type used unexpectedly");
+ break;
+ }
}
- void visitDeclRefType(DeclRefType* declRefType, TypeEmitArg const& arg)
+ void emitUntypedBufferType(IRUntypedBufferResourceType* type)
{
- auto declarator = arg.declarator;
- EmitDeclRef(declRefType->declRef);
- EmitDeclarator(declarator);
+ switch(context->shared->target)
+ {
+ case CodeGenTarget::HLSL:
+ default:
+ {
+ switch (type->op)
+ {
+ case kIROp_HLSLByteAddressBufferType: Emit("ByteAddressBuffer"); break;
+ case kIROp_HLSLRWByteAddressBufferType: Emit("RWByteAddressBuffer"); break;
+ case kIROp_RaytracingAccelerationStructureType: Emit("RaytracingAccelerationStructureType"); break;
+
+ default:
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled buffer type");
+ break;
+ }
+ }
+ break;
+
+ case CodeGenTarget::GLSL:
+ {
+ switch (type->op)
+ {
+ case kIROp_HLSLByteAddressBufferType: Emit("ByteAddressBuffer"); break;
+ case kIROp_HLSLRWByteAddressBufferType: Emit("RWByteAddressBuffer"); break;
+ case kIROp_RaytracingAccelerationStructureType: Emit("RaytracingAccelerationStructureType"); break;
+
+ default:
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled buffer type");
+ break;
+ }
+ }
+ break;
+ }
}
- void visitArrayExpressionType(ArrayExpressionType* arrayType, TypeEmitArg const& arg)
+ void emitSimpleTypeImpl(IRType* type)
{
- auto declarator = arg.declarator;
+ switch (type->op)
+ {
+ default:
+ break;
- EDeclarator arrayDeclarator;
- arrayDeclarator.next = declarator;
+ case kIROp_VoidType: Emit("void"); return;
+ case kIROp_IntType: Emit("int"); return;
+ case kIROp_UIntType: Emit("uint"); return;
+ case kIROp_BoolType: Emit("bool"); return;
+ case kIROp_HalfType: Emit("half"); return;
+ case kIROp_FloatType: Emit("float"); return;
+ case kIROp_DoubleType: Emit("double"); return;
+
+ case kIROp_VectorType:
+ emitVectorTypeImpl((IRVectorType*)type);
+ return;
+
+ case kIROp_MatrixType:
+ emitMatrixTypeImpl((IRMatrixType*)type);
+ return;
+
+ case kIROp_SamplerStateType:
+ case kIROp_SamplerComparisonStateType:
+ emitSamplerStateType(cast<IRSamplerStateTypeBase>(type));
+ return;
+
+ case kIROp_StructType:
+ emit(getIRName(type));
+ return;
+ }
+
+ // TODO: Ideally the following should be data-driven,
+ // based on meta-data attached to the definitions of
+ // each of these IR opcodes.
- if(arrayType->ArrayLength)
+ if (auto texType = as<IRTextureType>(type))
{
- arrayDeclarator.flavor = EDeclarator::Flavor::Array;
- arrayDeclarator.elementCount = arrayType->ArrayLength.Ptr();
+ emitTextureType(texType);
+ return;
}
- else
+ else if (auto textureSamplerType = as<IRTextureSamplerType>(type))
+ {
+ emitTextureSamplerType(textureSamplerType);
+ return;
+ }
+ else if (auto imageType = as<IRGLSLImageType>(type))
{
- arrayDeclarator.flavor = EDeclarator::Flavor::UnsizedArray;
+ emitImageType(imageType);
+ return;
+ }
+ else if (auto structuredBufferType = as<IRHLSLStructuredBufferTypeBase>(type))
+ {
+ emitStructuredBufferType(structuredBufferType);
+ return;
+ }
+ else if(auto untypedBufferType = as<IRUntypedBufferResourceType>(type))
+ {
+ emitUntypedBufferType(untypedBufferType);
+ return;
}
+ // HACK: As a fallback for HLSL targets, assume that the name of the
+ // instruction being used is the same as the name of the HLSL type.
+ if(context->shared->target == CodeGenTarget::HLSL)
+ {
+ auto opInfo = getIROpInfo(type->op);
+ emit(opInfo.name);
+ UInt operandCount = type->getOperandCount();
+ if(operandCount)
+ {
+ emit("<");
+ for(UInt ii = 0; ii < operandCount; ++ii)
+ {
+ if(ii != 0) emit(", ");
+ EmitVal(type->getOperand(ii));
+ }
+ emit(" >");
+ }
- emitTypeImpl(arrayType->baseType, &arrayDeclarator);
+ return;
+ }
+
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), SourceLoc(), "unhandled type");
}
- void visitRateQualifiedType(RateQualifiedType* type, TypeEmitArg const& arg)
+ void emitArrayTypeImpl(IRArrayType* arrayType, EDeclarator* declarator)
{
- emitTypeImpl(type->valueType, arg.declarator);
+ EDeclarator arrayDeclarator;
+ arrayDeclarator.flavor = EDeclarator::Flavor::Array;
+ arrayDeclarator.next = declarator;
+ arrayDeclarator.elementCount = arrayType->getElementCount();
+
+ emitTypeImpl(arrayType->getElementType(), &arrayDeclarator);
}
- void visitConstExprRate(ConstExprRate* /*rate*/, TypeEmitArg const& /*arg*/)
+ void emitUnsizedArrayTypeImpl(IRUnsizedArrayType* arrayType, EDeclarator* declarator)
{
- // This should never appear as a data type
- SLANG_UNEXPECTED("Rates not expected during emit");
+ EDeclarator arrayDeclarator;
+ arrayDeclarator.flavor = EDeclarator::Flavor::UnsizedArray;
+ arrayDeclarator.next = declarator;
+
+ emitTypeImpl(arrayType->getElementType(), &arrayDeclarator);
}
- void visitGroupSharedType(GroupSharedType* type, TypeEmitArg const& arg)
+ void emitTypeImpl(IRType* type, EDeclarator* declarator)
{
- switch(getTarget(context))
+ switch (type->op)
{
- case CodeGenTarget::HLSL:
- Emit("groupshared ");
+ default:
+ emitSimpleTypeImpl(type);
+ EmitDeclarator(declarator);
break;
- case CodeGenTarget::GLSL:
- Emit("shared ");
+ case kIROp_RateQualifiedType:
+ {
+ auto rateQualifiedType = cast<IRRateQualifiedType>(type);
+ emitTypeImpl(rateQualifiedType->getValueType(), declarator);
+ }
+
+ case kIROp_ArrayType:
+ emitArrayTypeImpl(cast<IRArrayType>(type), declarator);
break;
- default:
+ case kIROp_UnsizedArrayType:
+ emitUnsizedArrayTypeImpl(cast<IRUnsizedArrayType>(type), declarator);
break;
}
- emitTypeImpl(type->valueType, arg.declarator);
+
}
void EmitType(
- RefPtr<Type> type,
+ IRType* type,
SourceLoc const& typeLoc,
Name* name,
SourceLoc const& nameLoc)
@@ -1247,12 +1270,12 @@ struct EmitVisitor
emitTypeImpl(type, &nameDeclarator);
}
- void EmitType(RefPtr<Type> type, Name* name)
+ void EmitType(IRType* type, Name* name)
{
EmitType(type, SourceLoc(), name, SourceLoc());
}
- void EmitType(RefPtr<Type> type, String const& name)
+ void EmitType(IRType* type, String const& name)
{
// HACK: the rest of the code wants a `Name`,
// so we'll create one for a bit...
@@ -1263,7 +1286,7 @@ struct EmitVisitor
}
- void EmitType(RefPtr<Type> type)
+ void EmitType(IRType* type)
{
emitTypeImpl(type, nullptr);
}
@@ -1300,6 +1323,20 @@ struct EmitVisitor
}
}
+ void EmitType(IRType* type, Name* name, SourceLoc const& nameLoc)
+ {
+ EmitType(
+ type,
+ SourceLoc(),
+ name,
+ nameLoc);
+ }
+
+ void EmitType(IRType* type, NameLoc const& nameAndLoc)
+ {
+ EmitType(type, nameAndLoc.name, nameAndLoc.loc);
+ }
+
bool isTargetIntrinsicModifierApplicable(
IRTargetIntrinsicDecoration* decoration)
{
@@ -1407,78 +1444,16 @@ struct EmitVisitor
}
}
- //
- // Declaration References
- //
-
- void EmitVal(RefPtr<Val> val)
+ void EmitVal(IRInst* val)
{
- if (auto type = val.As<Type>())
+ if(auto type = as<IRType>(val))
{
EmitType(type);
}
- else if (auto intVal = val.As<IntVal>())
- {
- Emit(intVal);
- }
else
{
- // Note(tfoley): ignore unhandled cases for semantics for now...
- // assert(!"unimplemented");
- }
- }
-
- bool isBuiltinDecl(Decl* decl)
- {
- for (auto dd = decl; dd; dd = dd->ParentDecl)
- {
- if (dd->FindModifier<FromStdLibModifier>())
- return true;
- }
- return false;
- }
-
- void EmitDeclRef(DeclRef<Decl> declRef)
- {
- // When refering to anything other than a builtin, use its IR-facing name
- if (!isBuiltinDecl(declRef.getDecl()))
- {
- emit(getIRName(declRef));
- return;
- }
-
-
- // TODO: need to qualify a declaration name based on parent scopes/declarations
-
- // Emit the name for the declaration itself
- emitName(declRef.GetName());
-
- // If the declaration is nested directly in a generic, then
- // we need to output the generic arguments here
- auto parentDeclRef = declRef.GetParent();
- if (auto genericDeclRef = parentDeclRef.As<GenericDecl>())
- {
- // Only do this for declarations of appropriate flavors
- if(auto funcDeclRef = declRef.As<FunctionDeclBase>())
- {
- // Don't emit generic arguments for functions, because HLSL doesn't allow them
- return;
- }
-
- GenericSubstitution* subst = declRef.substitutions.genericSubstitutions;
- if (!subst)
- return;
-
- Emit("<");
- UInt argCount = subst->args.Count();
- for (UInt aa = 0; aa < argCount; ++aa)
- {
- if (aa != 0) Emit(",");
- EmitVal(subst->args[aa]);
- }
- Emit(" >");
+ emitIRInstExpr(context, val, IREmitMode::Default);
}
-
}
typedef unsigned int ESemanticMask;
@@ -1491,50 +1466,6 @@ struct EmitVisitor
kESemanticMask_Default = kESemanticMask_NoPackOffset,
};
- void EmitSemantic(RefPtr<HLSLSemantic> semantic, ESemanticMask /*mask*/)
- {
- if (auto simple = semantic.As<HLSLSimpleSemantic>())
- {
- Emit(" : ");
- emit(simple->name.Content);
- }
- else if(auto registerSemantic = semantic.As<HLSLRegisterSemantic>())
- {
- // Don't print out semantic from the user, since we are going to print the same thing our own way...
- }
- else if(auto packOffsetSemantic = semantic.As<HLSLPackOffsetSemantic>())
- {
- // Don't print out semantic from the user, since we are going to print the same thing our own way...
- }
- else
- {
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), semantic->loc, "unhandled kind of semantic");
- }
- }
-
-
- void EmitSemantics(RefPtr<Decl> decl, ESemanticMask mask = kESemanticMask_Default )
- {
- // Don't emit semantics if we aren't translating down to HLSL
- switch (context->shared->target)
- {
- case CodeGenTarget::HLSL:
- break;
-
- default:
- return;
- }
-
- for (auto mod = decl->modifiers.first; mod; mod = mod->next)
- {
- auto semantic = mod.As<HLSLSemantic>();
- if (!semantic)
- continue;
-
- EmitSemantic(semantic, mask);
- }
- }
-
// A chain of variables to use for emitting semantic/layout info
struct EmitVarChain
{
@@ -1851,7 +1782,6 @@ struct EmitVisitor
}
}
-
void emitGLSLVersionDirective(
ModuleDecl* /*program*/)
{
@@ -1949,19 +1879,6 @@ struct EmitVisitor
return context->shared->uniqueIDCounter++;
}
- UInt getID(Decl* decl)
- {
- auto& mapDeclToID = context->shared->mapDeclToID;
-
- UInt id = 0;
- if(mapDeclToID.TryGetValue(decl, id))
- return id;
-
- id = allocateUniqueID();
- mapDeclToID.Add(decl, id);
- return id;
- }
-
// IR-level emit logc
UInt getID(IRInst* value)
@@ -1977,105 +1894,25 @@ struct EmitVisitor
return id;
}
- String getIRName(Decl* decl)
- {
- // TODO: need a flag to get rid of the step that adds
- // a prefix here, so that we can get "clean" output
- // when needed.
- //
-
- String name;
- if (!(context->shared->entryPoint->compileRequest->compileFlags & SLANG_COMPILE_FLAG_NO_MANGLING))
- {
- name.append("_s");
- }
- name.append(getText(decl->getName()));
- return name;
- }
-
- String getIRName(DeclRefBase const& declRef)
- {
- // In general, when referring to a declaration that has been lowered
- // via the IR, we want to use its mangled name.
- //
- // There are two main exceptions to this:
- //
- // 1. For debugging, we accept the `-no-mangle` flag which basically
- // instructs us to try to use the original name of all declarations,
- // to make the output more like what is expected to come out of
- // fxc pass-through. This case should get deprecated some day.
- //
- // 2. It is really annoying to have the fields of a `struct` type
- // get ridiculously lengthy mangled names, and this also messes
- // up stuff like specialization (since the mangled name of a field
- // would then include the mangled name of the outer type).
- //
-
- String name;
- if (context->shared->entryPoint->compileRequest->compileFlags & SLANG_COMPILE_FLAG_NO_MANGLING)
- {
- // Special case (1):
- name.append(getText(declRef.GetName()));
- return name;
- }
-
- // Special case (2)
- if (declRef.GetParent().decl->As<AggTypeDecl>())
- {
- name.append(declRef.decl->nameAndLoc.name->text);
- return name;
- }
- // General case:
- name.append(getMangledName(declRef));
- return name;
- }
-
String getIRName(
IRInst* inst)
{
- switch(inst->op)
- {
- case kIROp_decl_ref:
- {
- auto irDeclRef = (IRDeclRef*) inst;
- return getIRName(irDeclRef->declRef);
- }
- break;
-
- default:
- break;
- }
-
- if(auto decoration = inst->findDecoration<IRHighLevelDeclDecoration>())
- {
- auto decl = decoration->decl;
- if (auto reflectionNameMod = decl->FindModifier<ParameterGroupReflectionName>())
- {
- return getText(reflectionNameMod->nameAndLoc.name);
- }
-
- if ((context->shared->entryPoint->compileRequest->compileFlags & SLANG_COMPILE_FLAG_NO_MANGLING))
- {
- return getIRName(decl);
- }
- }
-
- switch (inst->op)
+ // If the instruction has a mangled name, then emit using that.
+ if (auto globalValue = as<IRGlobalValue>(inst))
{
- case kIROp_global_var:
- case kIROp_global_constant:
- case kIROp_Func:
+ auto mangledName = globalValue->mangledName;
+ if (mangledName)
{
- auto& mangledName = ((IRGlobalValue*)inst)->mangledName;
- if(getText(mangledName).Length() != 0)
+ auto mangledNameText = getText(mangledName);
+ if (mangledNameText.Length() != 0)
+ {
return getText(mangledName);
+ }
}
- break;
-
- default:
- break;
}
+ // Otherwise fall back to a construct temporary name
+ // for the instruction.
StringBuilder sb;
sb << "_S";
sb << getID(inst);
@@ -2180,8 +2017,8 @@ struct EmitVisitor
break;
case kIROp_Var:
- case kIROp_global_var:
- case kIROp_global_constant:
+ case kIROp_GlobalVar:
+ case kIROp_GlobalConstant:
case kIROp_Param:
return false;
@@ -2190,7 +2027,7 @@ struct EmitVisitor
case kIROp_boolConst:
case kIROp_FieldAddress:
case kIROp_getElementPtr:
- case kIROp_specialize:
+ case kIROp_Specialize:
case kIROp_BufferElementRef:
return true;
}
@@ -2204,23 +2041,23 @@ struct EmitVisitor
// variables.
auto type = inst->getDataType();
- while (auto ptrType = type->As<PtrTypeBase>())
+ while (auto ptrType = as<IRPtrTypeBase>(type))
{
type = ptrType->getValueType();
}
- if(type->As<UniformParameterGroupType>())
+ if(as<IRUniformParameterGroupType>(type))
{
// TODO: we need to be careful here, because
// HLSL shader model 6 allows these as explicit
// types.
return true;
}
- else if (type->As<HLSLStreamOutputType>())
+ else if (as<IRHLSLStreamOutputType>(type))
{
return true;
}
- else if (type->As<HLSLPatchType>())
+ else if (as<IRHLSLPatchType>(type))
{
return true;
}
@@ -2231,15 +2068,15 @@ struct EmitVisitor
// to fold them into their use sites in all cases
if (getTarget(ctx) == CodeGenTarget::GLSL)
{
- if(type->As<ResourceTypeBase>())
+ if(as<IRResourceTypeBase>(type))
{
return true;
}
- else if(type->As<HLSLStructuredBufferTypeBase>())
+ else if(as<IRHLSLStructuredBufferTypeBase>(type))
{
return true;
}
- else if(type->As<SamplerStateType>())
+ else if(as<IRSamplerStateType>(type))
{
return true;
}
@@ -2255,7 +2092,7 @@ struct EmitVisitor
{
auto type = inst->getDataType();
- if(type->As<UniformParameterGroupType>() && !type->As<ParameterBlockType>())
+ if(as<IRUniformParameterGroupType>(type) && !as<IRParameterBlockType>(type))
{
// TODO: we need to be careful here, because
// HLSL shader model 6 allows these as explicit
@@ -2332,11 +2169,11 @@ struct EmitVisitor
void emitIRRateQualifiers(
EmitContext* ctx,
- Type* rate)
+ IRRate* rate)
{
if(!rate) return;
- if( auto constExprRate = rate->As<ConstExprRate>() )
+ if(as<IRConstExprRate>(rate))
{
switch( getTarget(ctx) )
{
@@ -2348,6 +2185,23 @@ struct EmitVisitor
break;
}
}
+
+ if (as<IRGroupSharedRate>(rate))
+ {
+ switch( getTarget(ctx) )
+ {
+ case CodeGenTarget::HLSL:
+ Emit("groupshared ");
+ break;
+
+ case CodeGenTarget::GLSL:
+ Emit("shared ");
+ break;
+
+ default:
+ break;
+ }
+ }
}
void emitIRRateQualifiers(
@@ -2366,7 +2220,7 @@ struct EmitVisitor
if(!type)
return;
- if (type->Equals(getSession()->getVoidType()))
+ if (as<IRVoidType>(type))
return;
emitIRRateQualifiers(ctx, inst);
@@ -2708,13 +2562,13 @@ struct EmitVisitor
auto textureArg = args[0].get();
auto samplerArg = args[1].get();
- if (auto baseTextureType = textureArg->type->As<TextureType>())
+ if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
{
emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
- if (auto samplerType = samplerArg->type->As<SamplerStateType>())
+ if (auto samplerType = as<IRSamplerStateTypeBase>(samplerArg->getDataType()))
{
- if (samplerType->flavor == SamplerStateFlavor::SamplerComparisonState)
+ if (as<IRSamplerComparisonStateType>(samplerType))
{
Emit("Shadow");
}
@@ -2746,7 +2600,7 @@ struct EmitVisitor
// We are going to hack this *hard* for now.
auto textureArg = args[0].get();
- if (auto baseTextureType = textureArg->type->As<TextureType>())
+ if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
{
emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler");
Emit("(");
@@ -2772,18 +2626,18 @@ struct EmitVisitor
SLANG_RELEASE_ASSERT(argCount >= 1);
auto textureArg = args[0].get();
- if (auto baseTextureType = textureArg->type->As<TextureType>())
+ if (auto baseTextureType = as<IRTextureType>(textureArg->getDataType()))
{
- auto elementType = baseTextureType->elementType;
- if (auto basicType = elementType->As<BasicExpressionType>())
+ auto elementType = baseTextureType->getElementType();
+ if (auto basicType = as<IRBasicType>(elementType))
{
// A scalar result is expected
Emit(".x");
}
- else if (auto vectorType = elementType->As<VectorExpressionType>())
+ else if (auto vectorType = as<IRVectorType>(elementType))
{
// A vector result is expected
- auto elementCount = GetIntVal(vectorType->elementCount);
+ auto elementCount = GetIntVal(vectorType->getElementCount());
if (elementCount < 4)
{
@@ -2813,9 +2667,9 @@ struct EmitVisitor
SLANG_RELEASE_ASSERT(argCount > argIndex);
auto vectorArg = args[argIndex].get();
- if (auto vectorType = vectorArg->type->As<VectorExpressionType>())
+ if (auto vectorType = as<IRVectorType>(vectorArg->getDataType()))
{
- auto elementCount = GetIntVal(vectorType->elementCount);
+ auto elementCount = GetIntVal(vectorType->getElementCount());
Emit(elementCount);
}
else
@@ -2850,7 +2704,7 @@ struct EmitVisitor
UInt operandIndex = 1;
- //
+ //
if (auto targetIntrinsicDecoration = findTargetIntrinsicDecoration(ctx, func))
{
emitTargetIntrinsicCallExpr(
@@ -2869,7 +2723,29 @@ struct EmitVisitor
// be better strategies (including just stuffing
// a pointer to the original decl onto the callee).
- UnmangleContext um(getText(func->mangledName));
+ // If the intrinsic the user is calling is a generic,
+ // then the mangled name will have been set on the
+ // outer-most generic, and not on the leaf value
+ // (which is `func` above), so we need to walk
+ // upwards to find it.
+ //
+ IRGlobalValue* valueForName = func;
+ for(;;)
+ {
+ auto parentBlock = as<IRBlock>(valueForName->parent);
+ if(!parentBlock)
+ break;
+
+ auto parentGeneric = as<IRGeneric>(parentBlock->parent);
+ if(!parentGeneric)
+ break;
+
+ valueForName = parentGeneric;
+ }
+
+ // We will use the `UnmangleContext` utility to
+ // help us split the original name into its pieces.
+ UnmangleContext um(getText(valueForName->mangledName));
um.startUnmangling();
// We'll read through the qualified name of the
@@ -3075,8 +2951,8 @@ struct EmitVisitor
case kIROp_Mul:
// Are we targetting GLSL, and are both operands matrices?
if(getTarget(ctx) == CodeGenTarget::GLSL
- && inst->getOperand(0)->type->As<MatrixExpressionType>()
- && inst->getOperand(1)->type->As<MatrixExpressionType>())
+ && as<IRMatrixType>(inst->getOperand(0)->getDataType())
+ && as<IRMatrixType>(inst->getOperand(1)->getDataType()))
{
emit("matrixCompMult(");
emitIROperand(ctx, inst->getOperand(0), mode);
@@ -3096,7 +2972,7 @@ struct EmitVisitor
case kIROp_Not:
{
- if (inst->getDataType()->Equals(getSession()->getBoolType()))
+ if (as<IRBoolType>(inst->getDataType()))
{
emit("!");
}
@@ -3248,7 +3124,7 @@ struct EmitVisitor
}
break;
- case kIROp_specialize:
+ case kIROp_Specialize:
{
emitIROperand(ctx, inst->getOperand(0), mode);
}
@@ -3322,8 +3198,8 @@ struct EmitVisitor
case kIROp_Var:
{
- auto ptrType = inst->getDataType();
- auto valType = ((PtrType*)ptrType)->getValueType();
+ auto ptrType = cast<IRPtrType>(inst->getDataType());
+ auto valType = ptrType->getValueType();
auto name = getIRName(inst);
emitIRType(ctx, valType, name);
@@ -3384,6 +3260,21 @@ struct EmitVisitor
}
void emitIRSemantics(
+ EmitContext*,
+ VarLayout* varLayout)
+ {
+ if(varLayout->flags & VarLayoutFlag::HasSemantic)
+ {
+ Emit(" : ");
+ emit(varLayout->semanticName);
+ if(varLayout->semanticIndex)
+ {
+ Emit(varLayout->semanticIndex);
+ }
+ }
+ }
+
+ void emitIRSemantics(
EmitContext* ctx,
IRInst* inst)
{
@@ -3397,31 +3288,24 @@ struct EmitVisitor
return;
}
- if(auto layoutDecoration = inst->findDecoration<IRLayoutDecoration>())
+ if (auto semanticDecoration = inst->findDecoration<IRSemanticDecoration>())
{
- if(auto varLayout = layoutDecoration->layout.As<VarLayout>())
- {
- if(varLayout->flags & VarLayoutFlag::HasSemantic)
- {
- Emit(" : ");
- emit(varLayout->semanticName);
- if(varLayout->semanticIndex)
- {
- Emit(varLayout->semanticIndex);
- }
-
- return;
- }
- }
+ Emit(" : ");
+ emit(semanticDecoration->semanticName);
+ return;
}
- // TODO(tfoley): should we ever need to use the high-level declaration
- // for this? It seems like the wrong approach...
-
- auto decoration = inst->findDecoration<IRHighLevelDeclDecoration>();
- if( decoration )
+ if(auto layoutDecoration = inst->findDecoration<IRLayoutDecoration>())
{
- EmitSemantics(decoration->decl);
+ auto layout = layoutDecoration->layout;
+ if(auto varLayout = layout.As<VarLayout>())
+ {
+ emitIRSemantics(ctx, varLayout);
+ }
+ else if (auto entryPointLayout = layout.As<EntryPointLayout>())
+ {
+ emitIRSemantics(ctx, entryPointLayout->resultLayout);
+ }
}
}
@@ -3502,7 +3386,7 @@ struct EmitVisitor
// may exit this region with operations that do *not* branch
// to `end`, but such non-local control flow will hopefully
// be captured.
- //
+ //
void emitIRStmtsForBlocks(
EmitContext* ctx,
IRBlock* begin,
@@ -4003,7 +3887,7 @@ struct EmitVisitor
return getText(entryPointLayout->entryPoint->getName());
}
- //
+ //
return "main";
}
@@ -4250,7 +4134,7 @@ struct EmitVisitor
auto name = getIRFuncName(func);
- emitIRType(ctx, resultType, name);
+ EmitType(resultType, name);
emit("(");
auto firstParam = func->getFirstParam();
@@ -4312,19 +4196,19 @@ struct EmitVisitor
void emitIRParamType(
EmitContext* ctx,
- Type* type,
+ IRType* type,
String const& name)
{
// An `out` or `inout` parameter will have been
// encoded as a parameter of pointer type, so
// we need to decode that here.
//
- if( auto outType = type->As<OutType>() )
+ if( auto outType = as<IROutType>(type))
{
emit("out ");
type = outType->getValueType();
}
- else if( auto inOutType = type->As<InOutType>() )
+ else if( auto inOutType = as<IRInOutType>(type))
{
emit("inout ");
type = inOutType->getValueType();
@@ -4333,16 +4217,29 @@ struct EmitVisitor
emitIRType(ctx, type, name);
}
+ IRInst* getSpecializedValue(IRSpecialize* specInst)
+ {
+ auto base = specInst->getBase();
+ auto baseGeneric = as<IRGeneric>(base);
+ if (!baseGeneric)
+ return base;
+
+ auto lastBlock = baseGeneric->getLastBlock();
+ if (!lastBlock)
+ return base;
+
+ auto returnInst = as<IRReturnVal>(lastBlock->getTerminator());
+ if (!returnInst)
+ return base;
+
+ return returnInst->getVal();
+ }
+
void emitIRFuncDecl(
EmitContext* ctx,
IRFunc* func)
{
- // We don't want to declare generic functions,
- // because none of our targets actually support them.
- if(func->getGenericDecl())
- return;
-
- // We also don't want to emit declarations for operations
+ // We don't want to emit declarations for operations
// that only appear in the IR as stand-ins for built-in
// operations on that target.
if (isTargetIntrinsic(ctx, func))
@@ -4361,7 +4258,7 @@ struct EmitVisitor
// and as a result it *also* doesn't have the IR `param` instructions,
// so we need to emit a declaration entirely from the type.
- auto funcType = func->getType();
+ auto funcType = func->getDataType();
auto resultType = func->getResultType();
auto name = getIRFuncName(func);
@@ -4432,9 +4329,9 @@ struct EmitVisitor
if(!value)
return nullptr;
- if(value->op == kIROp_specialize)
+ while (auto specInst = as<IRSpecialize>(value))
{
- value = ((IRSpecialize*) value)->genericVal.get();
+ value = getSpecializedValue(specInst);
}
if(value->op != kIROp_Func)
@@ -4451,11 +4348,6 @@ struct EmitVisitor
EmitContext* ctx,
IRFunc* func)
{
- if(func->getGenericDecl())
- {
- return;
- }
-
if(!isDefinition(func))
{
// This is just a function declaration,
@@ -4479,27 +4371,39 @@ struct EmitVisitor
}
}
-#if 0
void emitIRStruct(
- EmitContext* context,
- IRStructDecl* structType)
+ EmitContext* ctx,
+ IRStructType* structType)
{
emit("struct ");
- emit(getName(structType));
+ emit(getIRName(structType));
emit("\n{\n");
+ indent();
- for(auto ff = structType->getFirstField(); ff; ff = ff->getNextField())
+ for(auto ff : structType->getFields())
{
+ auto fieldKey = ff->getKey();
auto fieldType = ff->getFieldType();
- emitIRType(context, fieldType, getName(ff));
- emitIRSemantics(context, ff);
+ // Filter out fields with `void` type that might
+ // have been introduced by legalization.
+ if(as<IRVoidType>(fieldType))
+ continue;
+ // Note: GLSL doesn't support interpolation modifiers on `struct` fields
+ if( ctx->shared->target != CodeGenTarget::GLSL )
+ {
+ emitInterpolationModifiers(ctx, fieldKey, fieldType);
+ }
+
+ emitIRType(ctx, fieldType, getIRName(fieldKey));
+ emitIRSemantics(ctx, fieldKey);
emit(";\n");
}
+
+ dedent();
emit("};\n");
}
-#endif
void emitIRMatrixLayoutModifiers(
EmitContext* ctx,
@@ -4552,7 +4456,7 @@ struct EmitVisitor
default:
break;
}
-
+
}
}
@@ -4561,26 +4465,22 @@ struct EmitVisitor
// of the variable is an integer type.
void maybeEmitGLSLFlatModifier(
EmitContext*,
- Type* valueType)
+ IRType* valueType)
{
auto tt = valueType;
- if(auto vecType = tt->As<VectorExpressionType>())
- tt = vecType->elementType;
- if(auto vecType = tt->As<MatrixExpressionType>())
+ if(auto vecType = as<IRVectorType>(tt))
+ tt = vecType->getElementType();
+ if(auto vecType = as<IRMatrixType>(tt))
tt = vecType->getElementType();
- auto baseType = tt->As<BasicExpressionType>();
- if(!baseType)
- return;
-
- switch(baseType->baseType)
+ switch(tt->op)
{
default:
break;
- case BaseType::Int:
- case BaseType::UInt:
- case BaseType::UInt64:
+ case kIROp_IntType:
+ case kIROp_UIntType:
+ case kIROp_UInt64Type:
Emit("flat ");
break;
}
@@ -4588,36 +4488,51 @@ struct EmitVisitor
void emitInterpolationModifiers(
EmitContext* ctx,
- VarDeclBase* decl,
- Type* valueType)
+ IRInst* varInst,
+ IRType* valueType)
{
bool isGLSL = (ctx->shared->target == CodeGenTarget::GLSL);
bool anyModifiers = false;
- if(decl->FindModifier<HLSLNoInterpolationModifier>())
- {
- anyModifiers = true;
- Emit(isGLSL ? "flat " : "nointerpolation ");
- }
- else if(decl->FindModifier<HLSLNoPerspectiveModifier>())
- {
- anyModifiers = true;
- Emit("noperspective ");
- }
- else if(decl->FindModifier<HLSLLinearModifier>())
- {
- anyModifiers = true;
- Emit(isGLSL ? "smooth " : "linear ");
- }
- else if(decl->FindModifier<HLSLSampleModifier>())
- {
- anyModifiers = true;
- Emit("sample ");
- }
- else if(decl->FindModifier<HLSLCentroidModifier>())
+ anyModifiers = true;
+ for(auto dd = varInst->firstDecoration; dd; dd = dd->next)
{
- anyModifiers = true;
- Emit("centroid ");
+ if(dd->op != kIRDecorationOp_InterpolationMode)
+ continue;
+
+ auto decoration = (IRInterpolationModeDecoration*)dd;
+ auto mode = decoration->mode;
+
+ switch(mode)
+ {
+ case IRInterpolationMode::NoInterpolation:
+ anyModifiers = true;
+ Emit(isGLSL ? "flat " : "nointerpolation ");
+ break;
+
+ case IRInterpolationMode::NoPerspective:
+ anyModifiers = true;
+ Emit("noperspective ");
+ break;
+
+ case IRInterpolationMode::Linear:
+ anyModifiers = true;
+ Emit(isGLSL ? "smooth " : "linear ");
+ break;
+
+ case IRInterpolationMode::Sample:
+ anyModifiers = true;
+ Emit("sample ");
+ break;
+
+ case IRInterpolationMode::Centroid:
+ anyModifiers = true;
+ Emit("centroid ");
+ break;
+
+ default:
+ break;
+ }
}
// If the user didn't explicitly qualify a varying
@@ -4629,18 +4544,11 @@ struct EmitVisitor
}
}
- void emitInterpolationModifiers(
- EmitContext* ctx,
- VarLayout* layout,
- Type* valueType)
- {
- emitInterpolationModifiers(ctx, layout->varDecl, valueType);
- }
-
void emitIRVarModifiers(
EmitContext* ctx,
VarLayout* layout,
- Type* valueType)
+ IRInst* varDecl,
+ IRType* varType)
{
if (!layout)
return;
@@ -4651,7 +4559,7 @@ struct EmitVisitor
// for an HLSL `RWTexture*` then we need to emit a `format` layout qualifier.
if(getTarget(context) == CodeGenTarget::GLSL)
{
- if(auto resourceType = unwrapArray(valueType).As<TextureType>())
+ if(auto resourceType = as<IRTextureType>(unwrapArray(varType)))
{
switch(resourceType->getAccess())
{
@@ -4676,6 +4584,12 @@ struct EmitVisitor
}
}
+ if(layout->FindResourceInfo(LayoutResourceKind::VaryingInput)
+ || layout->FindResourceInfo(LayoutResourceKind::VaryingOutput))
+ {
+ emitInterpolationModifiers(ctx, varDecl, varType);
+ }
+
if (ctx->shared->target == CodeGenTarget::GLSL)
{
// Layout-related modifiers need to come before the declaration,
@@ -4696,20 +4610,12 @@ struct EmitVisitor
case LayoutResourceKind::VaryingInput:
{
emit("in ");
- if(layout->stage == Stage::Fragment)
- {
- maybeEmitGLSLFlatModifier(ctx, valueType);
- }
}
break;
- case LayoutResourceKind::FragmentOutput:
+ case LayoutResourceKind::VaryingOutput:
{
emit("out ");
- if(layout->stage != Stage::Fragment)
- {
- maybeEmitGLSLFlatModifier(ctx, valueType);
- }
}
break;
@@ -4723,9 +4629,9 @@ struct EmitVisitor
}
void emitHLSLParameterBlock(
- EmitContext* ctx,
- IRGlobalVar* varDecl,
- ParameterBlockType* type)
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ IRParameterBlockType* type)
{
emit("cbuffer ");
@@ -4768,11 +4674,11 @@ struct EmitVisitor
}
void emitHLSLParameterGroup(
- EmitContext* ctx,
- IRGlobalVar* varDecl,
- UniformParameterGroupType* type)
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ IRUniformParameterGroupType* type)
{
- if(auto parameterBlockType = type->As<ParameterBlockType>())
+ if(auto parameterBlockType = as<IRParameterBlockType>(type))
{
emitHLSLParameterBlock(ctx, varDecl, parameterBlockType);
return;
@@ -4805,45 +4711,52 @@ struct EmitVisitor
auto elementType = type->getElementType();
-
- if(auto declRefType = elementType->As<DeclRefType>())
+ if(auto structType = as<IRStructType>(elementType))
{
- if(auto structDeclRef = declRefType->declRef.As<StructDecl>())
+ auto structTypeLayout = typeLayout.As<StructTypeLayout>();
+ assert(structTypeLayout);
+
+ UInt fieldIndex = 0;
+ for(auto ff : structType->getFields())
{
- auto structTypeLayout = typeLayout.As<StructTypeLayout>();
- assert(structTypeLayout);
+ // TODO: need a plan to deal with the case where the IR-level
+ // `struct` type might not match the high-level type, so that
+ // the numbering of fields is different.
+ //
+ // The right plan is probably to require that the lowering pass
+ // create a fresh layout for any type/variable that it splits
+ // in this fashion, so that the layout information it attaches
+ // can always be assumed to apply to the actual instruciton.
+ //
- UInt fieldIndex = 0;
- for(auto ff : GetFields(structDeclRef))
- {
- // TODO: need a plan to deal with the case where the IR-level
- // `struct` type might not match the high-level type, so that
- // the numbering of fields is different.
- //
- // The right plan is probably to require that the lowering pass
- // create a fresh layout for any type/variable that it splits
- // in this fashion, so that the layout information it attaches
- // can always be assumed to apply to the actual instruciton.
- //
+ auto fieldLayout = structTypeLayout->fields[fieldIndex++];
- auto fieldLayout = structTypeLayout->fields[fieldIndex++];
+ auto fieldKey = ff->getKey();
+ auto fieldType = ff->getFieldType();
- auto fieldType = GetType(ff);
- if(fieldType->Equals(getSession()->getVoidType()))
- continue;
+ // Fields of `void` type aren't valid in HLSL/GLSL.
+ //
+ // TODO: legalization should get rid of any fields that have
+ // empty, or effectively empty types (e.g., emptry structs
+ // should be translated over to `void`).
+ if(as<IRVoidType>(fieldType))
+ continue;
- emitIRVarModifiers(ctx, fieldLayout, fieldType);
+ emitIRVarModifiers(ctx, fieldLayout, fieldKey, fieldType);
- emitIRType(ctx, fieldType, getIRName(ff));
+ emitIRType(ctx, fieldType, getIRName(fieldKey));
- emitHLSLParameterGroupFieldLayoutSemantics(fieldLayout, &elementChain);
+ emitHLSLParameterGroupFieldLayoutSemantics(fieldLayout, &elementChain);
- emit(";\n");
- }
+ emit(";\n");
}
}
else
{
+ // TODO: during legalization we should turn `ParameterGroup<X>` where `X`
+ // is not a `struct` type into `ParameterGroup<S>` where `S` is defined
+ // as something like `struct S { X _; };`
+ //
emit("/* unexpected */");
}
@@ -4852,9 +4765,9 @@ struct EmitVisitor
}
void emitGLSLParameterBlock(
- EmitContext* ctx,
- IRGlobalVar* varDecl,
- ParameterBlockType* type)
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ IRParameterBlockType* type)
{
auto varLayout = getVarLayout(ctx, varDecl);
assert(varLayout);
@@ -4893,11 +4806,11 @@ struct EmitVisitor
}
void emitGLSLParameterGroup(
- EmitContext* ctx,
- IRGlobalVar* varDecl,
- UniformParameterGroupType* type)
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ IRUniformParameterGroupType* type)
{
- if(auto parameterBlockType = type->As<ParameterBlockType>())
+ if(auto parameterBlockType = as<IRParameterBlockType>(type))
{
emitGLSLParameterBlock(ctx, varDecl, parameterBlockType);
return;
@@ -4922,7 +4835,7 @@ struct EmitVisitor
emitGLSLLayoutQualifier(LayoutResourceKind::DescriptorTableSlot, &containerChain);
- if(type->As<GLSLShaderStorageBufferType>())
+ if(as<IRGLSLShaderStorageBufferType>(type))
{
emit("layout(std430) buffer ");
}
@@ -4939,52 +4852,50 @@ struct EmitVisitor
auto elementType = type->getElementType();
- if(auto declRefType = elementType->As<DeclRefType>())
+ if(auto structType = as<IRStructType>(elementType))
{
- if(auto structDeclRef = declRefType->declRef.As<StructDecl>())
- {
- auto structTypeLayout = typeLayout.As<StructTypeLayout>();
- assert(structTypeLayout);
+ auto structTypeLayout = typeLayout.As<StructTypeLayout>();
+ assert(structTypeLayout);
- UInt fieldIndex = 0;
- for(auto ff : GetFields(structDeclRef))
- {
- // TODO: need a plan to deal with the case where the IR-level
- // `struct` type might not match the high-level type, so that
- // the numbering of fields is different.
- //
- // The right plan is probably to require that the lowering pass
- // create a fresh layout for any type/variable that it splits
- // in this fashion, so that the layout information it attaches
- // can always be assumed to apply to the actual instruciton.
- //
+ UInt fieldIndex = 0;
+ for(auto ff : structType->getFields())
+ {
+ // TODO: need a plan to deal with the case where the IR-level
+ // `struct` type might not match the high-level type, so that
+ // the numbering of fields is different.
+ //
+ // The right plan is probably to require that the lowering pass
+ // create a fresh layout for any type/variable that it splits
+ // in this fashion, so that the layout information it attaches
+ // can always be assumed to apply to the actual instruciton.
+ //
- auto fieldLayout = structTypeLayout->fields[fieldIndex++];
+ auto fieldLayout = structTypeLayout->fields[fieldIndex++];
- auto fieldType = GetType(ff);
- if(fieldType->Equals(getSession()->getVoidType()))
- continue;
+ auto fieldKey = ff->getKey();
+ auto fieldType = ff->getFieldType();
+ if(as<IRVoidType>(fieldType))
+ continue;
- // Note: we will emit matrix-layout modifiers here, but
- // we will refrain from emitting other modifiers that
- // might not be appropriate to the context (e.g., we
- // shouldn't go emitting `uniform` just because these
- // things are uniform...).
- //
- // TODO: we need a more refined set of modifiers that
- // we should allow on fields, because we might end
- // up supporting layout that isn't the default for
- // the given block type (e.g., something other than
- // `std140` for a uniform block).
- //
- emitIRMatrixLayoutModifiers(ctx, fieldLayout);
+ // Note: we will emit matrix-layout modifiers here, but
+ // we will refrain from emitting other modifiers that
+ // might not be appropriate to the context (e.g., we
+ // shouldn't go emitting `uniform` just because these
+ // things are uniform...).
+ //
+ // TODO: we need a more refined set of modifiers that
+ // we should allow on fields, because we might end
+ // up supporting layout that isn't the default for
+ // the given block type (e.g., something other than
+ // `std140` for a uniform block).
+ //
+ emitIRMatrixLayoutModifiers(ctx, fieldLayout);
- emitIRType(ctx, fieldType, getIRName(ff));
+ emitIRType(ctx, fieldType, getIRName(fieldKey));
// emitHLSLParameterGroupFieldLayoutSemantics(layout, fieldLayout);
- emit(";\n");
- }
+ emit(";\n");
}
}
else
@@ -5002,9 +4913,9 @@ struct EmitVisitor
}
void emitIRParameterGroup(
- EmitContext* ctx,
- IRGlobalVar* varDecl,
- UniformParameterGroupType* type)
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ IRUniformParameterGroupType* type)
{
switch (ctx->shared->target)
{
@@ -5042,8 +4953,8 @@ struct EmitVisitor
// Need to emit appropriate modifiers here.
auto layout = getVarLayout(ctx, varDecl);
-
- emitIRVarModifiers(ctx, layout, varType);
+
+ emitIRVarModifiers(ctx, layout, varDecl, varType);
#if 0
switch (addressSpace)
@@ -5067,12 +4978,12 @@ struct EmitVisitor
emit(";\n");
}
- RefPtr<Type> unwrapArray(Type* type)
+ IRType* unwrapArray(IRType* type)
{
- Type* t = type;
- while( auto arrayType = t->As<ArrayExpressionType>() )
+ IRType* t = type;
+ while( auto arrayType = as<IRArrayTypeBase>(t) )
{
- t = arrayType->baseType;
+ t = arrayType->getElementType();
}
return t;
}
@@ -5080,7 +4991,7 @@ struct EmitVisitor
void emitIRStructuredBuffer_GLSL(
EmitContext* ctx,
IRGlobalVar* varDecl,
- HLSLStructuredBufferTypeBase* structuredBufferType)
+ IRHLSLStructuredBufferTypeBase* structuredBufferType)
{
// Shader storage buffer is an OpenGL 430 feature
//
@@ -5145,7 +5056,7 @@ struct EmitVisitor
// Emit a blank line so that the formatting is nicer.
emit("\n");
- if (auto paramBlockType = varType->As<UniformParameterGroupType>())
+ if (auto paramBlockType = as<IRUniformParameterGroupType>(varType))
{
emitIRParameterGroup(
ctx,
@@ -5158,7 +5069,7 @@ struct EmitVisitor
{
// When outputting GLSL, we need to transform any declaration of
// a `*StructuredBuffer<T>` into an ordinary `buffer` declaration.
- if( auto structuredBufferType = unwrapArray(varType)->As<HLSLStructuredBufferTypeBase>() )
+ if( auto structuredBufferType = as<IRHLSLStructuredBufferTypeBase>(unwrapArray(varType)) )
{
emitIRStructuredBuffer_GLSL(
ctx,
@@ -5205,7 +5116,7 @@ struct EmitVisitor
}
}
- emitIRVarModifiers(ctx, layout, varType);
+ emitIRVarModifiers(ctx, layout, varDecl, varType);
emitIRType(ctx, varType, getIRName(varDecl));
@@ -5282,11 +5193,11 @@ struct EmitVisitor
emitIRFunc(ctx, (IRFunc*) inst);
break;
- case kIROp_global_var:
+ case kIROp_GlobalVar:
emitIRGlobalVar(ctx, (IRGlobalVar*) inst);
break;
- case kIROp_global_constant:
+ case kIROp_GlobalConstant:
emitIRGlobalConstant(ctx, (IRGlobalConstant*) inst);
break;
@@ -5294,202 +5205,158 @@ struct EmitVisitor
emitIRVar(ctx, (IRVar*) inst);
break;
+ case kIROp_StructType:
+ emitIRStruct(ctx, cast<IRStructType>(inst));
+ break;
+
default:
break;
}
}
- void ensureStructDecl(
- EmitContext* ctx,
- DeclRef<StructDecl> declRef)
+ // An action to be performed during code emit.
+ struct EmitAction
{
- auto mangledName = getMangledName(declRef);
- if(ctx->shared->irDeclsVisited.Contains(mangledName))
- return;
-
- ctx->shared->irDeclsVisited.Add(mangledName);
-
- // First emit any types used by fields of this type
- for( auto ff : GetFields(declRef) )
+ enum Level
{
- if(ff.getDecl()->HasModifier<HLSLStaticModifier>())
- continue;
+ ForwardDeclaration,
+ Definition,
+ };
+ Level level;
+ IRInst* inst;
+ };
- auto fieldType = GetType(ff);
- emitIRUsedType(ctx, fieldType);
- }
+ struct ComputeEmitActionsContext
+ {
+ IRInst* moduleInst;
+ HashSet<IRInst*> openInsts;
+ Dictionary<IRInst*, EmitAction::Level> mapInstToLevel;
+ List<EmitAction>* actions;
+ };
- // Don't emit declarations for types that should be built-in on the target.
- //
- // TODO: This should really be checking if the type is a target intrinsic
- // for the chosen target, and not just whether it is globally declared
- // as a builtin (so that we can have types that are builtin in some cases,
- // but not others).
- if(declRef.getDecl()->HasModifier<BuiltinModifier>())
- return;
+ void ensureInstOperand(
+ ComputeEmitActionsContext* ctx,
+ IRInst* inst,
+ EmitAction::Level requiredLevel = EmitAction::Level::Definition)
+ {
+ if(!inst) return;
- Emit("\nstruct ");
- EmitDeclRef(declRef);
- Emit("\n{\n");
- indent();
- for( auto ff : GetFields(declRef) )
+ if(inst->getParent() == ctx->moduleInst)
{
- if(ff.getDecl()->HasModifier<HLSLStaticModifier>())
- continue;
-
- auto fieldType = GetType(ff);
-
- // Skip `void` fields that might have been created by legalization.
- if(fieldType->Equals(getSession()->getVoidType()))
- continue;
-
- // Note: GLSL doesn't support interpolation modifiers on `struct` fields
- if( ctx->shared->target != CodeGenTarget::GLSL )
- {
- emitInterpolationModifiers(ctx, ff.getDecl(), fieldType);
- }
- emitIRType(ctx, fieldType, getIRName(ff));
-
- EmitSemantics(ff.getDecl());
-
- emit(";\n");
+ ensureGlobalInst(ctx, inst, requiredLevel);
}
- dedent();
- Emit("};\n");
}
- void emitIRUsedDeclRef(
- EmitContext* ctx,
- DeclRef<Decl> declRef)
+ void ensureInstOperandsRec(
+ ComputeEmitActionsContext* ctx,
+ IRInst* inst)
{
- auto decl = declRef.getDecl();
+ ensureInstOperand(ctx, inst->getFullType());
- if(decl->HasModifier<BuiltinTypeModifier>()
- || decl->HasModifier<MagicTypeModifier>())
+ UInt operandCount = inst->operandCount;
+ for(UInt ii = 0; ii < operandCount; ++ii)
{
- return;
+ // TODO: there are some special cases we can add here,
+ // to avoid outputting full definitions in cases that
+ // can get by with forward declarations.
+ //
+ // For example, true pointer types should (in principle)
+ // only need the type they point to to be forward-declared.
+ // Similarly, a `call` instruction only needs the callee
+ // to be forward-declared, etc.
+
+ ensureInstOperand(ctx, inst->getOperand(ii));
}
- if( auto structDeclRef = declRef.As<StructDecl>() )
+ if(auto parentInst = as<IRParentInst>(inst))
{
- //
- ensureStructDecl(ctx, structDeclRef);
+ for(auto child : parentInst->getChildren())
+ {
+ ensureInstOperandsRec(ctx, child);
+ }
}
}
- // A type is going to be used by the IR, so
- // make sure that we have emitted whatever
- // it needs.
- void emitIRUsedType(
- EmitContext* ctx,
- Type* type)
+ void ensureGlobalInst(
+ ComputeEmitActionsContext* ctx,
+ IRInst* inst,
+ EmitAction::Level requiredLevel)
{
- if(type->As<BasicExpressionType>())
- {}
- else if(type->As<VectorExpressionType>())
- {}
- else if(type->As<MatrixExpressionType>())
- {}
- else if(auto arrayType = type->As<ArrayExpressionType>())
- {
- emitIRUsedType(ctx, arrayType->baseType);
- }
- else if( auto textureType = type->As<TextureTypeBase>() )
- {
- emitIRUsedType(ctx, textureType->elementType);
- }
- else if( auto genericType = type->As<BuiltinGenericType>() )
- {
- emitIRUsedType(ctx, genericType->elementType);
- }
- else if( auto ptrType = type->As<PtrTypeBase>() )
- {
- emitIRUsedType(ctx, ptrType->getValueType());
- }
- else if(type->As<SamplerStateType>() )
- {
- }
- else if( auto declRefType = type->As<DeclRefType>() )
+ // Skip certain instrutions, since they
+ // don't affect output.
+ switch(inst->op)
{
- auto declRef = declRefType->declRef;
- emitIRUsedDeclRef(ctx, declRef);
+ case kIROp_WitnessTable:
+ case kIROp_Generic:
+ return;
+
+ default:
+ break;
}
- else
- {}
- }
- void emitIRUsedTypesForGlobalValueWithCode(
- EmitContext* ctx,
- IRGlobalValueWithCode* value)
- {
- for( auto bb = value->getFirstBlock(); bb; bb = bb->getNextBlock() )
+ // Have we already processed this instruction?
+ EmitAction::Level existingLevel;
+ if(ctx->mapInstToLevel.TryGetValue(inst, existingLevel))
{
- for( auto pp = bb->getFirstParam(); pp; pp = pp->getNextParam() )
- {
- emitIRUsedTypesForValue(ctx, pp);
- }
-
- for( auto ii = bb->getFirstInst(); ii; ii = ii->getNextInst() )
- {
- emitIRUsedTypesForValue(ctx, ii);
- }
+ // If we've already emitted it suitably,
+ // then don't worry about it.
+ if(existingLevel >= requiredLevel)
+ return;
}
- }
- void emitIRUsedTypesForValue(
- EmitContext* ctx,
- IRInst* value)
- {
- if(!value) return;
- switch( value->op )
+ EmitAction action;
+ action.level = requiredLevel;
+ action.inst = inst;
+
+ if(requiredLevel == EmitAction::Level::Definition)
{
- case kIROp_Func:
+ if(ctx->openInsts.Contains(inst))
{
- auto irFunc = (IRFunc*) value;
+ SLANG_UNEXPECTED("circularity during codegen");
+ return;
+ }
- // Don't emit anything for a generic function,
- // since we only care about the types used by
- // the actual specializations.
- if (irFunc->getGenericDecl())
- return;
+ ctx->openInsts.Add(inst);
- emitIRUsedType(ctx, irFunc->getResultType());
+ ensureInstOperandsRec(ctx, inst);
- emitIRUsedTypesForGlobalValueWithCode(ctx, irFunc);
- }
- break;
+ ctx->openInsts.Remove(inst);
+ }
- case kIROp_global_var:
- {
- auto irGlobal = (IRGlobalVar*) value;
- emitIRUsedType(ctx, irGlobal->type);
- emitIRUsedTypesForGlobalValueWithCode(ctx, irGlobal);
- }
- break;
+ ctx->mapInstToLevel[inst] = requiredLevel;
+ ctx->actions->Add(action);
+ }
- case kIROp_global_constant:
- {
- auto irGlobal = (IRGlobalConstant*) value;
- emitIRUsedType(ctx, irGlobal->type);
- emitIRUsedTypesForGlobalValueWithCode(ctx, irGlobal);
- }
- break;
+ void computeIREmitActions(
+ IRModule* module,
+ List<EmitAction>& ioActions)
+ {
+ ComputeEmitActionsContext ctx;
+ ctx.moduleInst = module->getModuleInst();
+ ctx.actions = &ioActions;
- default:
- {
- emitIRUsedType(ctx, value->type);
- }
- break;
+ for(auto inst : module->getGlobalInsts())
+ {
+ ensureGlobalInst(&ctx, inst, EmitAction::Level::Definition);
}
}
- void emitIRUsedTypesForModule(
- EmitContext* ctx,
- IRModule* module)
+ void executeIREmitActions(
+ EmitContext* ctx,
+ List<EmitAction> const& actions)
{
- for(auto ii : module->getGlobalInsts())
+ for(auto action : actions)
{
- emitIRUsedTypesForValue(ctx, ii);
+ switch(action.level)
+ {
+ case EmitAction::Level::ForwardDeclaration:
+ emitIRFuncDecl(ctx, cast<IRFunc>(action.inst));
+ break;
+
+ case EmitAction::Level::Definition:
+ emitIRGlobalInst(ctx, action.inst);
+ break;
+ }
}
}
@@ -5497,27 +5364,16 @@ struct EmitVisitor
EmitContext* ctx,
IRModule* module)
{
- emitIRUsedTypesForModule(ctx, module);
+ // The IR will usually come in an order that respects
+ // dependencies between global declarations, but this
+ // isn't guaranteed, so we need to be careful about
+ // the order in which we emit things.
- // Before we emit code, we need to forward-declare
- // all of our functions so that we don't have to
- // sort them by dependencies.
- for(auto ii : module->getGlobalInsts())
- {
- if(ii->op != kIROp_Func)
- continue;
+ List<EmitAction> actions;
- auto func = (IRFunc*) ii;
- emitIRFuncDecl(ctx, func);
- }
-
- for(auto ii : module->getGlobalInsts())
- {
- emitIRGlobalInst(ctx, ii);
- }
+ computeIREmitActions(module, actions);
+ executeIREmitActions(ctx, actions);
}
-
-
};
//
@@ -5614,7 +5470,7 @@ String emitEntryPoint(
TargetRequest* targetRequest)
{
auto translationUnit = entryPoint->getTranslationUnit();
-
+
SharedEmitContext sharedContext;
sharedContext.target = target;
sharedContext.finalTarget = targetRequest->target;
@@ -5651,19 +5507,26 @@ String emitEntryPoint(
target,
targetRequest);
{
- TypeLegalizationContext typeLegalizationContext;
- typeLegalizationContext.session = entryPoint->compileRequest->mSession;
-
IRModule* irModule = getIRModule(irSpecializationState);
auto compileRequest = translationUnit->compileRequest;
+ auto session = compileRequest->mSession;
- typeLegalizationContext.irModule = irModule;
+ TypeLegalizationContext typeLegalizationContext;
+ initialize(&typeLegalizationContext,
+ session,
+ irModule);
specializeIRForEntryPoint(
irSpecializationState,
entryPoint,
&sharedContext.extensionUsageTracker);
+#if 0
+ fprintf(stderr, "### CLONED:\n");
+ dumpIR(irModule);
+ fprintf(stderr, "###\n");
+#endif
+
validateIRModuleIfEnabled(compileRequest, irModule);
// If the user specified the flag that they want us to dump
@@ -5685,15 +5548,16 @@ String emitEntryPoint(
// Debugging code for IR transformations...
#if 0
fprintf(stderr, "### SPECIALIZED:\n");
- dumpIR(lowered);
+ dumpIR(irModule);
fprintf(stderr, "###\n");
#endif
+ validateIRModuleIfEnabled(compileRequest, irModule);
// After we've fully specialized all generics, and
// "devirtualized" all the calls through interfaces,
// we need to ensure that the code only uses types
// that are legal on the chosen target.
- //
+ //
legalizeTypes(
&typeLegalizationContext,
irModule);
@@ -5701,9 +5565,10 @@ String emitEntryPoint(
// Debugging output of legalization
#if 0
fprintf(stderr, "### LEGALIZED:\n");
- dumpIR(lowered);
+ dumpIR(irModule);
fprintf(stderr, "###\n");
#endif
+ validateIRModuleIfEnabled(compileRequest, irModule);
// Once specialization and type legalization have been performed,
// we should perform some of our basic optimization steps again,
@@ -5712,6 +5577,11 @@ String emitEntryPoint(
// so that we can work with the individual fields).
constructSSA(irModule);
+#if 0
+ fprintf(stderr, "### AFTER SSA:\n");
+ dumpIR(irModule);
+ fprintf(stderr, "###\n");
+#endif
validateIRModuleIfEnabled(compileRequest, irModule);
// After all of the required optimization and legalization
@@ -5721,9 +5591,9 @@ String emitEntryPoint(
// TODO: do we want to emit directly from IR, or translate the
// IR back into AST for emission?
visitor.emitIRModule(&context, irModule);
-
+
// retain the specialized ir module, because the current
- // GlobalGenericParamSubstitution implementation may reference ir objects
+ // GlobalGenericParamSubstitution implementation may reference ir objects
targetRequest->compileRequest->compiledModules.Add(irModule);
}
destroyIRSpecializationState(irSpecializationState);
@@ -5755,7 +5625,7 @@ String emitEntryPoint(
finalResultBuilder << code;
String finalResult = finalResultBuilder.ProduceString();
-
+
return finalResult;
}