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.cpp227
1 files changed, 88 insertions, 139 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 3834945f9..1ef42bdf0 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1,7 +1,6 @@
// emit.cpp
#include "emit.h"
-#include "ast-legalize.h"
#include "ir-insts.h"
#include "legalize-types.h"
#include "lower-to-ir.h"
@@ -113,13 +112,6 @@ struct SharedEmitContext
Dictionary<IRBlock*, IRBlock*> irMapContinueTargetToLoopHead;
HashSet<String> irTupleTypes;
-
- // Map used to tell AST lowering what decls are represented by IR.
- HashSet<Decl*>* irDeclSetForAST = nullptr;
-
- // Are we doing IR-only emit, so that everything should get
- // its mangled name?
- bool isFullIRMode = false;
};
struct EmitContext
@@ -3010,31 +3002,14 @@ struct EmitVisitor
void EmitDeclRef(DeclRef<Decl> declRef)
{
- // Are we emitting an AST in a context where some declarations
- // are actually stored as IR code?
-
- if(auto irDeclSet = context->shared->irDeclSetForAST)
+ // When refering to anything other than a builtin, use its IR-facing name
+ if (!isBuiltinDecl(declRef.getDecl()))
{
- Decl* decl = declRef.getDecl();
- if(irDeclSet->Contains(decl))
- {
- emit(getIRName(declRef));
- return;
- }
- }
-
- if (context->shared->isFullIRMode)
- {
- // Don't apply this to builting declarations
- if (!isBuiltinDecl(declRef.getDecl()))
- {
- emit(getIRName(declRef));
- return;
- }
+ emit(getIRName(declRef));
+ return;
}
-
// TODO: need to qualify a declaration name based on parent scopes/declarations
// Emit the name for the declaration itself
@@ -5061,6 +5036,11 @@ emitDeclImpl(decl, nullptr);
default:
break;
+ case kIROp_Var:
+ case kIROp_global_var:
+ case kIROp_Param:
+ return false;
+
case kIROp_IntLit:
case kIROp_FloatLit:
case kIROp_boolConst:
@@ -5075,6 +5055,12 @@ emitDeclImpl(decl, nullptr);
// because they aren't allowed as types for temporary
// variables.
auto type = inst->getType();
+
+ while (auto ptrType = type->As<PtrTypeBase>())
+ {
+ type = ptrType->getValueType();
+ }
+
if(type->As<UniformParameterGroupType>())
{
// TODO: we need to be careful here, because
@@ -5086,18 +5072,29 @@ emitDeclImpl(decl, nullptr);
{
return true;
}
- else if(type->As<TextureTypeBase>())
+ else if (type->As<HLSLPatchType>())
{
- // GLSL doesn't allow texture/resource types to
- // be used as first-class values, so we need
- // to fold them into their use sites in all cases
- if(getTarget(ctx) == CodeGenTarget::GLSL)
- return true;
+ return true;
}
- else if(type->As<HLSLStructuredBufferTypeBase>())
+
+
+ // GLSL doesn't allow texture/resource types to
+ // be used as first-class values, so we need
+ // to fold them into their use sites in all cases
+ if (getTarget(ctx) == CodeGenTarget::GLSL)
{
- if(getTarget(ctx) == CodeGenTarget::GLSL)
+ if(type->As<ResourceTypeBase>())
+ {
return true;
+ }
+ else if(type->As<HLSLStructuredBufferTypeBase>())
+ {
+ return true;
+ }
+ else if(type->As<SamplerStateType>())
+ {
+ return true;
+ }
}
// By default we will *not* fold things into their use sites.
@@ -5576,8 +5573,11 @@ emitDeclImpl(decl, nullptr);
IRFieldExtract* fieldExtract = (IRFieldExtract*) inst;
- emitIROperand(ctx, fieldExtract->getBase());
- emit(".");
+ if (!isDerefBaseImplicit(ctx, fieldExtract->getBase()))
+ {
+ emitIROperand(ctx, fieldExtract->getBase());
+ emit(".");
+ }
emit(getIRName(fieldExtract->getField()));
}
break;
@@ -5814,6 +5814,10 @@ emitDeclImpl(decl, nullptr);
}
break;
+ case kIROp_Param:
+ emit(getIRName(inst));
+ break;
+
default:
emit("/* unhandled */");
break;
@@ -7003,11 +7007,56 @@ emitDeclImpl(decl, nullptr);
emit("}\n");
}
+ void emitGLSLParameterBlock(
+ EmitContext* ctx,
+ IRGlobalVar* varDecl,
+ ParameterBlockType* type)
+ {
+ auto varLayout = getVarLayout(ctx, varDecl);
+ assert(varLayout);
+
+ EmitVarChain blockChain(varLayout);
+
+ EmitVarChain containerChain = blockChain;
+ EmitVarChain elementChain = blockChain;
+
+ auto typeLayout = varLayout->typeLayout;
+ if( auto parameterGroupTypeLayout = typeLayout.As<ParameterGroupTypeLayout>() )
+ {
+ containerChain = EmitVarChain(parameterGroupTypeLayout->containerVarLayout, &blockChain);
+ elementChain = EmitVarChain(parameterGroupTypeLayout->elementVarLayout, &blockChain);
+
+ typeLayout = parameterGroupTypeLayout->elementVarLayout->getTypeLayout();
+ }
+
+ emitGLSLLayoutQualifier(LayoutResourceKind::DescriptorTableSlot, &containerChain);
+ emit("layout(std140) uniform ");
+
+ // Generate a dummy name for the block
+ emit("_S");
+ Emit(ctx->shared->uniqueIDCounter++);
+
+ emit("\n{\n");
+
+ auto elementType = type->getElementType();
+
+ emitIRType(ctx, elementType, getIRName(varDecl));
+ emit(";\n");
+
+ emit("};\n");
+ }
+
void emitGLSLParameterGroup(
EmitContext* ctx,
IRGlobalVar* varDecl,
UniformParameterGroupType* type)
{
+ if(auto parameterBlockType = type->As<ParameterBlockType>())
+ {
+ emitGLSLParameterBlock(ctx, varDecl, parameterBlockType);
+ return;
+ }
+
auto varLayout = getVarLayout(ctx, varDecl);
assert(varLayout);
@@ -7655,93 +7704,6 @@ String emitEntryPoint(
EmitVisitor visitor(&context);
- // Depending on how the compiler was invoked, we may need to perform
- // some amount of preocessing on the code before we can emit it.
- //
- // We try to partition the cases we need to handle into a few broad
- // categories, each of which is reflected as a different code path
- // below:
- //
- // 1. REMOVED: "Full rewriter" mode, where the user provides HLSL/GLSL, opts
- // out of semantic checking, and doesn't make use of any Slang
- // code via `import`.
- //
- // 2. "Partial rewriter" modes, where the user starts with HLSL/GLSL
- // and opts out of checking for that code, but also imports some
- // Slang code which may need cross-compilation. They may also
- // need us to rewrite the AST for some of their HLSL/GLSL function
- // bodies to make things work. This actually has two main sub-modes:
- //
- // a) "Without IR." If the user doesn't opt into using the IR, then
- // the imported Slang code gets translated to the target languge
- // via the same AST-to-AST pass that legalized the user's code. This
- // mode will eventually go away, but it is the main one used right now.
- //
- // b) REMOVED: "With IR." If the user opts into using the IR, then we need to
- // apply the AST-to-AST pass to their HLSL/GLSL code, but *also* use
- // the IR to compile everything else.
- //
- // 3. "Full IR" mode, where we can assume all the input code is in Slang
- // (or the subset of HLSL we understand) that has undergone full
- // semantic checking, and the user has opted into using the IR.
- //
- // We'll try to detect the cases here, starting with case (1):
- //
- // REMOVED.
- //
- // Next we will check for case (2a):
- 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.
- //
- // Note: This case should go away completely once the IR is able to be relied
- // upon for all cross-compilation scenarios.
-
- // We will apply our AST-to-AST legalization pass before we emit
- // any code, and we will emit code for the AST that comes out
- // of this pass instead of the original.
-
- // We perform legalization of the program before emitting *anything*,
- // because the lowering process might change how we emit some
- // boilerplate at the start of the ouput for GLSL (e.g., what
- // version we require).
-
- List<Decl*> astDecls;
- findDeclsUsedByASTEntryPoint(
- entryPoint,
- target,
- nullptr,
- astDecls);
-
- auto lowered = lowerEntryPoint(
- entryPoint,
- programLayout,
- target,
- &sharedContext.extensionUsageTracker,
- nullptr,
- &typeLegalizationContext,
- astDecls);
- sharedContext.program = lowered.program;
-
- // Note that we emit the main body code of the program *before*
- // we emit any leading preprocessor directives for GLSL.
- // This is to give the emit logic a change to make last-minute
- // adjustments like changing the required GLSL version.
- //
- // TODO: All such adjustments would be better handled during
- // lowering, but that requires having a semantic rather than
- // textual format for the HLSL->GLSL mapping.
- visitor.EmitDeclsInContainer(lowered.program.Ptr());
- }
- //
- // The remaining cases all require the use of our IR, and so there
- // are certain steps that need to be shared.
- else
{
TypeLegalizationContext typeLegalizationContext;
typeLegalizationContext.session = entryPoint->compileRequest->mSession;
@@ -7757,13 +7719,6 @@ String emitEntryPoint(
typeLegalizationContext.irModule = irModule;
- // We are in case (3), where all of the code is in Slang, and
- // has already been lowered to IR as part of the front-end
- // compilation work. We thus start by cloning any code needed
- // by the entry point over to our fresh IR module.
-
- sharedContext.isFullIRMode = true;
-
specializeIRForEntryPoint(
irSpecializationState,
entryPoint);
@@ -7807,12 +7762,6 @@ String emitEntryPoint(
fprintf(stderr, "###\n");
#endif
- LoweredEntryPoint lowered;
-
- // When emitting IR-based declarations, we wnat to
- // track which decls have already been lowered.
- 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.