summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/emit.cpp80
-rw-r--r--source/slang/ir-inst-defs.h75
-rw-r--r--source/slang/ir-insts.h256
-rw-r--r--source/slang/ir-legalize-types.cpp54
-rw-r--r--source/slang/ir-missing-return.cpp7
-rw-r--r--source/slang/ir-restructure-scoping.cpp2
-rw-r--r--source/slang/ir-sccp.cpp14
-rw-r--r--source/slang/ir-serialize.cpp438
-rw-r--r--source/slang/ir-serialize.h9
-rw-r--r--source/slang/ir-ssa.cpp19
-rw-r--r--source/slang/ir-validate.cpp11
-rw-r--r--source/slang/ir.cpp609
-rw-r--r--source/slang/ir.h340
-rw-r--r--source/slang/legalize-types.cpp2
-rw-r--r--source/slang/lower-to-ir.cpp84
-rw-r--r--source/slang/slang.natvis28
16 files changed, 805 insertions, 1223 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index ba1b2177a..d7abbff24 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -1419,7 +1419,7 @@ struct EmitVisitor
bool isTargetIntrinsicModifierApplicable(
IRTargetIntrinsicDecoration* decoration)
{
- auto targetName = String(decoration->targetName);
+ auto targetName = String(decoration->getTargetName());
// If no target name was specified, then the modifier implicitly
// applies to all targets.
@@ -2170,7 +2170,7 @@ struct EmitVisitor
// then use that name instead.
if(auto intrinsicDecoration = findTargetIntrinsicDecoration(context, inst))
{
- return String(intrinsicDecoration->definition);
+ return String(intrinsicDecoration->getDefinition());
}
// If we have a name hint on the instruction, then we will try to use that
@@ -2200,7 +2200,7 @@ struct EmitVisitor
// name hint already ends with one.
//
- String nameHint = nameHintDecoration->name->text;
+ String nameHint = nameHintDecoration->getName();
nameHint = scrubName(nameHint);
StringBuilder sb;
@@ -2928,9 +2928,9 @@ struct EmitVisitor
EmitContext* /* ctx */,
IRInst* inst)
{
- for (auto dd = inst->firstDecoration; dd; dd = dd->next)
+ for(auto dd : inst->getDecorations())
{
- if (dd->op != kIRDecorationOp_TargetIntrinsic)
+ if (dd->op != kIROp_TargetIntrinsicDecoration)
continue;
auto targetIntrinsic = (IRTargetIntrinsicDecoration*)dd;
@@ -2978,7 +2978,7 @@ struct EmitVisitor
args++;
argCount--;
- auto name = String(targetIntrinsic->definition);
+ auto name = String(targetIntrinsic->getDefinition());
if(isOrdinaryName(name))
@@ -3512,19 +3512,19 @@ struct EmitVisitor
decoratedValue = getSpecializedValue(specInst);
}
- for( auto decoration = decoratedValue->firstDecoration; decoration; decoration = decoration->next )
+ for( auto decoration : decoratedValue->getDecorations() )
{
switch(decoration->op)
{
default:
break;
- case kIRDecorationOp_RequireGLSLExtension:
- requireGLSLExtension(String(((IRRequireGLSLExtensionDecoration*)decoration)->extensionName));
+ case kIROp_RequireGLSLExtensionDecoration:
+ requireGLSLExtension(String(((IRRequireGLSLExtensionDecoration*)decoration)->getExtensionName()));
break;
- case kIRDecorationOp_RequireGLSLVersion:
- requireGLSLVersion(int(((IRRequireGLSLVersionDecoration*)decoration)->languageVersion));
+ case kIROp_RequireGLSLVersionDecoration:
+ requireGLSLVersion(int(((IRRequireGLSLVersionDecoration*)decoration)->getLanguageVersion()));
break;
}
}
@@ -3800,7 +3800,7 @@ struct EmitVisitor
auto prec = kEOp_Postfix;
needClose = maybeEmitParens(outerPrec, prec);
- emit(decoration->outerArrayName);
+ emit(decoration->getOuterArrayName());
emit("[");
emitIROperand(ctx, inst->getOperand(1), mode, kEOp_General);
emit("].");
@@ -3968,12 +3968,6 @@ struct EmitVisitor
}
break;
- case kIROp_NotePatchConstantFunc:
- {
- // No-op
- break;
- }
-
case kIROp_Var:
{
auto ptrType = cast<IRPtrType>(inst->getDataType());
@@ -4108,13 +4102,13 @@ struct EmitVisitor
if (auto semanticDecoration = inst->findDecoration<IRSemanticDecoration>())
{
Emit(" : ");
- emit(semanticDecoration->semanticName);
+ emit(semanticDecoration->getSemanticName());
return;
}
if(auto layoutDecoration = inst->findDecoration<IRLayoutDecoration>())
{
- auto layout = layoutDecoration->layout;
+ auto layout = layoutDecoration->getLayout();
if(auto varLayout = layout->dynamicCast<VarLayout>())
{
emitIRSemantics(ctx, varLayout);
@@ -4137,7 +4131,7 @@ struct EmitVisitor
if (!decoration)
return nullptr;
- return (VarLayout*) decoration->layout;
+ return (VarLayout*) decoration->getLayout();
}
void emitIRLayoutSemantics(
@@ -4354,7 +4348,7 @@ struct EmitVisitor
//
if (auto loopControlDecoration = loopInst->findDecoration<IRLoopControlDecoration>())
{
- switch (loopControlDecoration->mode)
+ switch (loopControlDecoration->getMode())
{
case kIRLoopControl_Unroll:
// Note: loop unrolling control is only available in HLSL, not GLSL
@@ -4468,23 +4462,6 @@ struct EmitVisitor
}
}
-
-
- IRInst* findFirstInst(IRFunc* irFunc, IROp op)
- {
- for (auto block : irFunc->getBlocks())
- {
- for (auto inst : block->getChildren())
- {
- if (inst->op == op)
- {
- return inst;
- }
- }
- }
- return nullptr;
- }
-
void emitAttributeSingleString(const char* name, FuncDecl* entryPoint, Attribute* attrib)
{
assert(attrib);
@@ -4543,11 +4520,11 @@ struct EmitVisitor
{
SLANG_UNUSED(attrib);
- auto irPatchFunc = static_cast<IRNotePatchConstantFunc*>(findFirstInst(irFunc, kIROp_NotePatchConstantFunc));
+ auto irPatchFunc = irFunc->findDecoration<IRPatchConstantFuncDecoration>();
assert(irPatchFunc);
if (!irPatchFunc)
{
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), entryPoint->loc, "Unable to find NotePatchConstantFunc instruction");
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), entryPoint->loc, "Unable to find [patchConstantFunc(...)] decoration");
return;
}
@@ -4897,7 +4874,7 @@ struct EmitVisitor
{
if (auto layoutDecor = pp->findDecoration<IRLayoutDecoration>())
{
- Layout* layout = layoutDecor->layout;
+ Layout* layout = layoutDecor->getLayout();
VarLayout* varLayout = dynamic_cast<VarLayout*>(layout);
if (varLayout)
@@ -5053,7 +5030,7 @@ struct EmitVisitor
{
if( auto layoutDecoration = func->findDecoration<IRLayoutDecoration>() )
{
- return layoutDecoration->layout->dynamicCast<EntryPointLayout>();
+ return layoutDecoration->getLayout()->dynamicCast<EntryPointLayout>();
}
return nullptr;
}
@@ -5062,7 +5039,7 @@ struct EmitVisitor
{
if (auto layoutDecoration = func->findDecoration<IRLayoutDecoration>())
{
- if (auto entryPointLayout = layoutDecoration->layout->dynamicCast<EntryPointLayout>())
+ if (auto entryPointLayout = layoutDecoration->getLayout()->dynamicCast<EntryPointLayout>())
{
return entryPointLayout;
}
@@ -5268,13 +5245,13 @@ struct EmitVisitor
bool isGLSL = (ctx->shared->target == CodeGenTarget::GLSL);
bool anyModifiers = false;
- for(auto dd = varInst->firstDecoration; dd; dd = dd->next)
+ for(auto dd : varInst->getDecorations())
{
- if(dd->op != kIRDecorationOp_InterpolationMode)
+ if(dd->op != kIROp_InterpolationModeDecoration)
continue;
auto decoration = (IRInterpolationModeDecoration*)dd;
- auto mode = decoration->mode;
+ auto mode = decoration->getMode();
switch(mode)
{
@@ -6055,7 +6032,7 @@ struct EmitVisitor
// We expect the terminator to be a `return`
// instruction with a value.
- auto returnInst = (IRReturnVal*) block->getLastInst();
+ auto returnInst = (IRReturnVal*) block->getLastDecorationOrChild();
SLANG_RELEASE_ASSERT(returnInst->op == kIROp_ReturnVal);
// We will emit the value in the `GlobalConstant` mode, which
@@ -6188,12 +6165,9 @@ struct EmitVisitor
ensureInstOperand(ctx, inst->getOperand(ii));
}
- if(auto parentInst = as<IRParentInst>(inst))
+ for(auto child : inst->getDecorationsAndChildren())
{
- for(auto child : parentInst->getChildren())
- {
- ensureInstOperandsRec(ctx, child);
- }
+ ensureInstOperandsRec(ctx, child);
}
}
diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h
index 09c11ed16..202e80bcf 100644
--- a/source/slang/ir-inst-defs.h
+++ b/source/slang/ir-inst-defs.h
@@ -149,45 +149,37 @@ INST(Nop, nop, 0, 0)
// This is a parent instruction that holds zero or more
// `field` instructions.
//
-// Note: we are being a bit slippery here, because a `struct`
-// instruction is really an `IRParentInst`, but we want it
-// to also be caught in any dynamic cast to `IRType`, so we
-// ensure that it comes at the *end* of the range for `IRType`,
-// and the start of the range for `IRParentInst` (and `IRGlobalValue`)
INST(StructType, struct, 0, PARENT)
INST_RANGE(Type, VoidType, StructType)
-/*IRParentInst*/
+/*IRGlobalValue*/
- /*IRGlobalValue*/
+ /*IRGlobalValueWithCode*/
+ /* IRGlobalValueWIthParams*/
+ INST(Func, func, 0, PARENT)
+ INST(Generic, generic, 0, PARENT)
+ INST_RANGE(GlobalValueWithParams, Func, Generic)
- /*IRGlobalValueWithCode*/
- /* IRGlobalValueWIthParams*/
- INST(Func, func, 0, PARENT)
- INST(Generic, generic, 0, PARENT)
- INST_RANGE(GlobalValueWithParams, Func, Generic)
+ INST(GlobalVar, global_var, 0, 0)
+ INST(GlobalConstant, global_constant, 0, 0)
+ INST_RANGE(GlobalValueWithCode, Func, GlobalConstant)
- INST(GlobalVar, global_var, 0, 0)
- INST(GlobalConstant, global_constant, 0, 0)
- INST_RANGE(GlobalValueWithCode, Func, GlobalConstant)
+ INST(StructKey, key, 0, 0)
+ INST(GlobalGenericParam, global_generic_param, 0, 0)
+ INST(WitnessTable, witness_table, 0, 0)
- INST(StructKey, key, 0, 0)
- INST(GlobalGenericParam, global_generic_param, 0, 0)
- INST(WitnessTable, witness_table, 0, 0)
+INST_RANGE(GlobalValue, StructType, WitnessTable)
- INST_RANGE(GlobalValue, StructType, WitnessTable)
+INST(Module, module, 0, PARENT)
- INST(Module, module, 0, PARENT)
-
- INST(Block, block, 0, PARENT)
-
-INST_RANGE(ParentInst, StructType, Block)
+INST(Block, block, 0, PARENT)
/* IRConstant */
INST(BoolLit, boolConst, 0, 0)
INST(IntLit, integer_constant, 0, 0)
INST(FloatLit, float_constant, 0, 0)
+ INST(PtrLit, ptr_constant, 0, 0)
INST(StringLit, string_constant, 0, 0)
INST_RANGE(Constant, BoolLit, StringLit)
@@ -363,7 +355,40 @@ INST(SampleGrad, sampleGrad, 4, 0)
INST(GroupMemoryBarrierWithGroupSync, GroupMemoryBarrierWithGroupSync, 0, 0)
-INST(NotePatchConstantFunc, notePatchConstantFunc, 1, 0)
+/* Decoration */
+
+INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
+ INST(LayoutDecoration, layout, 1, 0)
+ INST(LoopControlDecoration, loopControl, 1, 0)
+ /* TargetSpecificDecoration */
+ INST(TargetDecoration, target, 1, 0)
+ INST(TargetIntrinsicDecoration, targetIntrinsic, 2, 0)
+ INST_RANGE(TargetSpecificDecoration, TargetDecoration, TargetIntrinsicDecoration)
+ INST(GLSLOuterArrayDecoration, glslOuterArray, 1, 0)
+ INST(SemanticDecoration, semantic, 1, 0)
+ INST(InterpolationModeDecoration, interpolationMode, 1, 0)
+ INST(NameHintDecoration, nameHint, 1, 0)
+
+ /** The decorated _instruction_ is transitory. Such a decoration should NEVER be found on an output instruction a module.
+ Typically used mark an instruction so can be specially handled - say when creating a IRConstant literal, and the payload of
+ needs to be special cased for lookup. */
+ INST(TransitoryDecoration, transitory, 0, 0)
+
+ INST(VulkanRayPayloadDecoration, vulkanRayPayload, 0, 0)
+ INST(VulkanHitAttributesDecoration, vulkanHitAttributes, 0, 0)
+ INST(RequireGLSLVersionDecoration, requireGLSLVersion, 1, 0)
+ INST(RequireGLSLExtensionDecoration, requireGLSLExtension, 1, 0)
+ INST(ReadNoneDecoration, readNone, 0, 0)
+ INST(VulkanCallablePayloadDecoration, vulkanCallablePayload, 0, 0)
+ INST(EarlyDepthStencilDecoration, earlyDepthStencil, 0, 0)
+ INST(GloballyCoherentDecoration, globallyCoherent, 0, 0)
+ INST(PatchConstantFuncDecoration, patchConstantFunc, 1, 0)
+
+INST_RANGE(Decoration, HighLevelDeclDecoration, PatchConstantFuncDecoration)
+
+
+//
+
PSEUDO_INST(Pos)
PSEUDO_INST(PreInc)
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index 31bc11ca4..c3d21a4bd 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -17,22 +17,36 @@ namespace Slang {
class Decl;
+struct IRDecoration : IRInst
+{
+ IR_PARENT_ISA(Decoration)
+
+ IRDecoration* getNextDecoration()
+ {
+ return as<IRDecoration>(getNextInst());
+ }
+};
+
// Associates an IR-level decoration with a source declaration
// in the high-level AST, that can be used to extract
// additional information that informs code emission.
struct IRHighLevelDeclDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_HighLevelDecl };
+ enum { kOp = kIROp_HighLevelDeclDecoration };
+ IR_LEAF_ISA(HighLevelDeclDecoration)
- Decl* decl;
+ IRPtrLit* getDeclOperand() { return cast<IRPtrLit>(getOperand(0)); }
+ Decl* getDecl() { return (Decl*) getDeclOperand()->getValue(); }
};
// Associates an IR-level decoration with a source layout
struct IRLayoutDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_Layout };
+ enum { kOp = kIROp_LayoutDecoration };
+ IR_LEAF_ISA(LayoutDecoration)
- Layout* layout;
+ IRPtrLit* getLayoutOperand() { return cast<IRPtrLit>(getOperand(0)); }
+ Layout* getLayout() { return (Layout*) getLayoutOperand()->getValue(); }
};
enum IRLoopControl
@@ -42,35 +56,60 @@ enum IRLoopControl
struct IRLoopControlDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_LoopControl };
+ enum { kOp = kIROp_LoopControlDecoration };
+ IR_LEAF_ISA(LoopControlDecoration)
- IRLoopControl mode;
+ IRConstant* getModeOperand() { return cast<IRConstant>(getOperand(0)); }
+
+ IRLoopControl getMode()
+ {
+ return IRLoopControl(getModeOperand()->value.intVal);
+ }
};
struct IRTargetSpecificDecoration : IRDecoration
{
- // TODO: have a more structured representation of target specifiers
- StringRepresentation* targetName;
+ IR_PARENT_ISA(TargetSpecificDecoration)
+
+ IRStringLit* getTargetNameOperand() { return cast<IRStringLit>(getOperand(0)); }
+
+ UnownedStringSlice getTargetName()
+ {
+ return getTargetNameOperand()->getStringSlice();
+ }
};
struct IRTargetDecoration : IRTargetSpecificDecoration
{
- enum { kDecorationOp = kIRDecorationOp_Target };
+ enum { kOp = kIROp_TargetDecoration };
+ IR_LEAF_ISA(TargetDecoration)
};
struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration
{
- enum { kDecorationOp = kIRDecorationOp_TargetIntrinsic };
+ enum { kOp = kIROp_TargetIntrinsicDecoration };
+ IR_LEAF_ISA(TargetIntrinsicDecoration)
+
+ IRStringLit* getDefinitionOperand() { return cast<IRStringLit>(getOperand(1)); }
- StringRepresentation* definition;
+ UnownedStringSlice getDefinition()
+ {
+ return getDefinitionOperand()->getStringSlice();
+ }
};
struct IRGLSLOuterArrayDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_GLSLOuterArray };
+ enum { kOp = kIROp_GLSLOuterArrayDecoration };
+ IR_LEAF_ISA(GLSLOuterArrayDecoration)
+
+ IRStringLit* getOuterArraynameOperand() { return cast<IRStringLit>(getOperand(0)); }
- char const* outerArrayName;
+ UnownedStringSlice getOuterArrayName()
+ {
+ return getOuterArraynameOperand()->getStringSlice();
+ }
};
// A decoration that marks a field key as having been associated
@@ -84,9 +123,15 @@ struct IRGLSLOuterArrayDecoration : IRDecoration
//
struct IRSemanticDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_Semantic };
+ enum { kOp = kIROp_SemanticDecoration };
+ IR_LEAF_ISA(SemanticDecoration)
+
+ IRStringLit* getSemanticNameOperand() { return cast<IRStringLit>(getOperand(0)); }
- Name* semanticName;
+ UnownedStringSlice getSemanticName()
+ {
+ return getSemanticNameOperand()->getStringSlice();
+ }
};
enum class IRInterpolationMode
@@ -101,9 +146,15 @@ enum class IRInterpolationMode
struct IRInterpolationModeDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_InterpolationMode };
+ enum { kOp = kIROp_InterpolationModeDecoration };
+ IR_LEAF_ISA(InterpolationModeDecoration)
- IRInterpolationMode mode;
+ IRConstant* getModeOperand() { return cast<IRConstant>(getOperand(0)); }
+
+ IRInterpolationMode getMode()
+ {
+ return IRInterpolationMode(getModeOperand()->value.intVal);
+ }
};
/// A decoration that provides a desired name to be used
@@ -112,63 +163,69 @@ struct IRInterpolationModeDecoration : IRDecoration
/// names, emit debug information, etc.
struct IRNameHintDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_NameHint };
+ enum { kOp = kIROp_NameHintDecoration };
+ IR_LEAF_ISA(NameHintDecoration)
- Name* name;
+ IRStringLit* getNameOperand() { return cast<IRStringLit>(getOperand(0)); }
+
+ UnownedStringSlice getName()
+ {
+ return getNameOperand()->getStringSlice();
+ }
};
+#define IR_SIMPLE_DECORATION(NAME) \
+ struct IR##NAME : IRDecoration \
+ { \
+ enum { kOp = kIROp_##NAME }; \
+ IR_LEAF_ISA(NAME) \
+ }; \
+ /**/
+
/// A decoration that indicates that a variable represents
/// a vulkan ray payload, and should have a location assigned
/// to it.
-struct IRVulkanRayPayloadDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_VulkanRayPayload };
-};
+IR_SIMPLE_DECORATION(VulkanRayPayloadDecoration)
/// A decoration that indicates that a variable represents
/// a vulkan callable shader payload, and should have a location assigned
/// to it.
-struct IRVulkanCallablePayloadDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_VulkanCallablePayload };
-};
+IR_SIMPLE_DECORATION(VulkanCallablePayloadDecoration)
/// A decoration that indicates that a variable represents
/// vulkan hit attributes, and should have a location assigned
/// to it.
-struct IRVulkanHitAttributesDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_VulkanHitAttributes };
-};
+IR_SIMPLE_DECORATION(VulkanHitAttributesDecoration)
struct IRRequireGLSLVersionDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_RequireGLSLVersion };
+ enum { kOp = kIROp_RequireGLSLVersionDecoration };
+ IR_LEAF_ISA(RequireGLSLVersionDecoration)
+
+ IRConstant* getLanguageVersionOperand() { return cast<IRConstant>(getOperand(0)); }
- Int languageVersion;
+ Int getLanguageVersion()
+ {
+ return Int(getLanguageVersionOperand()->value.intVal);
+ }
};
struct IRRequireGLSLExtensionDecoration : IRDecoration
{
- enum { kDecorationOp = kIRDecorationOp_RequireGLSLExtension };
+ enum { kOp = kIROp_RequireGLSLExtensionDecoration };
+ IR_LEAF_ISA(RequireGLSLExtensionDecoration)
- StringRepresentation* extensionName;
-};
+ IRStringLit* getExtensionNameOperand() { return cast<IRStringLit>(getOperand(0)); }
-struct IRReadNoneDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_ReadNone };
-};
-
-struct IREarlyDepthStencilDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_EarlyDepthStencil };
+ UnownedStringSlice getExtensionName()
+ {
+ return getExtensionNameOperand()->getStringSlice();
+ }
};
-struct IRGloballyCoherentDecoration : IRDecoration
-{
- enum { kDecorationOp = kIRDecorationOp_GloballyCoherent };
-};
+IR_SIMPLE_DECORATION(ReadNoneDecoration)
+IR_SIMPLE_DECORATION(EarlyDepthStencilDecoration)
+IR_SIMPLE_DECORATION(GloballyCoherentDecoration)
// An instruction that specializes another IR value
// (representing a generic) to a particular set of generic arguments
@@ -426,10 +483,12 @@ struct IRSwizzledStore : IRInst
};
-struct IRNotePatchConstantFunc: IRInst
+struct IRPatchConstantFuncDecoration : IRDecoration
{
+ enum { kOp = kIROp_PatchConstantFuncDecoration };
+ IR_LEAF_ISA(PatchConstantFuncDecoration)
+
IRInst* getFunc() { return getOperand(0); }
- IR_LEAF_ISA(NotePatchConstantFunc)
};
// An IR `var` instruction conceptually represents
@@ -573,7 +632,7 @@ struct IRBuilder
// The current parent being inserted into (this might
// be the global scope, a function, a block inside
// a function, etc.)
- IRParentInst* insertIntoParent = nullptr;
+ IRInst* insertIntoParent = nullptr;
//
// An instruction in the current parent that we should insert before
IRInst* insertBeforeInst = nullptr;
@@ -585,7 +644,7 @@ struct IRBuilder
// that we are inserting into (if any).
IRGlobalValueWithCode* getFunc();
- void setInsertInto(IRParentInst* insertInto);
+ void setInsertInto(IRInst* insertInto);
void setInsertBefore(IRInst* insertBefore);
IRBuilderSourceLocRAII* sourceLocInfo = nullptr;
@@ -596,6 +655,7 @@ struct IRBuilder
IRInst* getIntValue(IRType* type, IRIntegerValue value);
IRInst* getFloatValue(IRType* type, IRFloatingPointValue value);
IRStringLit* getStringValue(const UnownedStringSlice& slice);
+ IRPtrLit* getPtrValue(void* value);
IRBasicType* getBasicType(BaseType baseType);
IRBasicType* getVoidType();
@@ -771,9 +831,6 @@ struct IRBuilder
IRParam* emitParam(
IRType* type);
- IRNotePatchConstantFunc* emitNotePatchConstantFunc(
- IRInst* func);
-
IRVar* emitVar(
IRType* type);
@@ -902,21 +959,17 @@ struct IRBuilder
IRInst* param,
IRInst* val);
- template<typename T>
- T* addDecoration(IRInst* value, IRDecorationOp op)
- {
- SLANG_ASSERT(getModule());
- auto decorationSize = sizeof(T);
- auto decoration = (T*)getModule()->memoryArena.allocateAndZero(decorationSize);
-
- // TODO: Do we need to run ctor after zeroing?
- new(decoration)T();
+ IRDecoration* addDecoration(IRInst* value, IROp op, IRInst* const* operands, Int operandCount);
- decoration->op = op;
+ IRDecoration* addDecoration(IRInst* value, IROp op, IRInst* operand)
+ {
+ return addDecoration(value, op, &operand, 1);
+ }
- decoration->next = value->firstDecoration;
- value->firstDecoration = decoration;
- return decoration;
+ IRDecoration* addDecoration(IRInst* value, IROp op, IRInst* operand0, IRInst* operand1)
+ {
+ IRInst* operands[] = { operand0, operand1 };
+ return addDecoration(value, op, operands, SLANG_COUNT_OF(operands));
}
template <typename T>
@@ -925,22 +978,71 @@ struct IRBuilder
getModule()->getObjectScopeManager()->addMaybeNull(ptr);
return ptr;
}
- StringRepresentation* addStringToFree(const String& string)
+
+ template<typename T>
+ void addSimpleDecoration(IRInst* value)
{
- StringRepresentation* stringRep = string.getStringRepresentation();
- getModule()->getObjectScopeManager()->addMaybeNull(stringRep);
- return stringRep;
+ addDecoration(value, IROp(T::kOp), (IRInst* const*) nullptr, 0);
}
+ void addHighLevelDeclDecoration(IRInst* value, Decl* decl);
+ void addLayoutDecoration(IRInst* value, Layout* layout);
- template<typename T>
- T* addDecoration(IRInst* value)
+ void addNameHintDecoration(IRInst* value, IRStringLit* name)
+ {
+ addDecoration(value, kIROp_NameHintDecoration, name);
+ }
+
+ void addNameHintDecoration(IRInst* value, UnownedStringSlice const& text)
+ {
+ addNameHintDecoration(value, getStringValue(text));
+ }
+
+ void addGLSLOuterArrayDecoration(IRInst* value, UnownedStringSlice const& text)
+ {
+ addDecoration(value, kIROp_GLSLOuterArrayDecoration, getStringValue(text));
+ }
+
+ void addInterpolationModeDecoration(IRInst* value, IRInterpolationMode mode)
+ {
+ addDecoration(value, kIROp_InterpolationModeDecoration, getIntValue(getIntType(), IRIntegerValue(mode)));
+ }
+
+ void addLoopControlDecoration(IRInst* value, IRLoopControl mode)
+ {
+ addDecoration(value, kIROp_LoopControlDecoration, getIntValue(getIntType(), IRIntegerValue(mode)));
+ }
+
+ void addSemanticDecoration(IRInst* value, UnownedStringSlice const& text)
+ {
+ addDecoration(value, kIROp_SemanticDecoration, getStringValue(text));
+ }
+
+ void addTargetIntrinsicDecoration(IRInst* value, UnownedStringSlice const& target, UnownedStringSlice const& definition)
+ {
+ addDecoration(value, kIROp_TargetIntrinsicDecoration, getStringValue(target), getStringValue(definition));
+ }
+
+ void addTargetDecoration(IRInst* value, UnownedStringSlice const& target)
+ {
+ addDecoration(value, kIROp_TargetDecoration, getStringValue(target));
+ }
+
+ void addRequireGLSLExtensionDecoration(IRInst* value, UnownedStringSlice const& extensionName)
+ {
+ addDecoration(value, kIROp_RequireGLSLExtensionDecoration, getStringValue(extensionName));
+ }
+
+ void addRequireGLSLVersionDecoration(IRInst* value, Int version)
+ {
+ addDecoration(value, kIROp_RequireGLSLVersionDecoration, getIntValue(getIntType(), IRIntegerValue(version)));
+ }
+
+ void addPatchConstantFuncDecoration(IRInst* value, IRInst* patchConstantFunc)
{
- return addDecoration<T>(value, IRDecorationOp(T::kDecorationOp));
+ addDecoration(value, kIROp_PatchConstantFuncDecoration, patchConstantFunc);
}
- IRHighLevelDeclDecoration* addHighLevelDeclDecoration(IRInst* value, Decl* decl);
- IRLayoutDecoration* addLayoutDecoration(IRInst* value, Layout* layout);
};
// Helper to establish the source location that will be used
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index b86c9f6e9..46ba59bcd 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -114,12 +114,12 @@ struct IRGlobalNameInfo
};
static LegalVal declareVars(
- IRTypeLegalizationContext* context,
+ IRTypeLegalizationContext* context,
IROp op,
LegalType type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
- String const* nameHint,
+ UnownedStringSlice nameHint,
IRGlobalNameInfo* globalNameInfo);
static LegalType legalizeType(
@@ -844,17 +844,17 @@ static LegalVal legalizeInst(
RefPtr<VarLayout> findVarLayout(IRInst* value)
{
if (auto layoutDecoration = value->findDecoration<IRLayoutDecoration>())
- return layoutDecoration->layout->dynamicCast<VarLayout>();
+ return layoutDecoration->getLayout()->dynamicCast<VarLayout>();
return nullptr;
}
-static String const* findNameHint(IRInst* inst)
+static UnownedStringSlice findNameHint(IRInst* inst)
{
if( auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>() )
{
- return &nameHintDecoration->name->text;
+ return nameHintDecoration->getName();
}
- return nullptr;
+ return UnownedStringSlice();
}
static LegalVal legalizeLocalVar(
@@ -912,7 +912,7 @@ static LegalVal legalizeLocalVar(
varChain = &varChainStorage;
}
- String const* nameHint = findNameHint(irLocalVar);
+ UnownedStringSlice nameHint = findNameHint(irLocalVar);
LegalVal newVal = declareVars(context, kIROp_Var, legalValueType, typeLayout, varChain, nameHint, nullptr);
// Remove the old local var.
@@ -944,7 +944,7 @@ static LegalVal legalizeParam(
context->insertBeforeParam = originalParam;
- String const* nameHint = findNameHint(originalParam);
+ UnownedStringSlice nameHint = findNameHint(originalParam);
auto newVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nameHint, nullptr);
originalParam->removeFromParent();
@@ -1096,10 +1096,10 @@ static void addParamType(List<IRType*>& ioParamTypes, LegalType t)
static void legalizeInstsInParent(
IRTypeLegalizationContext* context,
- IRParentInst* parent)
+ IRInst* parent)
{
IRInst* nextChild = nullptr;
- for(auto child = parent->getFirstChild(); child; child = nextChild)
+ for(auto child = parent->getFirstDecorationOrChild(); child; child = nextChild)
{
nextChild = child->getNextInst();
@@ -1147,25 +1147,13 @@ static LegalVal legalizeFunc(
return LegalVal::simple(irFunc);
}
-static void addNameHint(
- IRTypeLegalizationContext* context,
- IRInst* inst,
- String const& text)
-{
- if(text.Length() == 0)
- return;
-
- auto name = context->session->getNameObj(text);
- context->builder->addDecoration<IRNameHintDecoration>(inst)->name = name;
-}
-
static LegalVal declareSimpleVar(
IRTypeLegalizationContext* context,
IROp op,
IRType* type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
- String const* nameHint,
+ UnownedStringSlice nameHint,
IRGlobalNameInfo* globalNameInfo)
{
RefPtr<VarLayout> varLayout = createVarLayout(varChain, typeLayout);
@@ -1252,9 +1240,9 @@ static LegalVal declareSimpleVar(
builder->addHighLevelDeclDecoration(irVar, varDeclRef.getDecl());
}
- if( nameHint )
+ if( nameHint.size() )
{
- addNameHint(context, irVar, *nameHint);
+ context->builder->addNameHintDecoration(irVar, nameHint);
}
}
@@ -1267,7 +1255,7 @@ static LegalVal declareVars(
LegalType type,
TypeLayout* typeLayout,
LegalVarChain* varChain,
- String const* nameHint,
+ UnownedStringSlice nameHint,
IRGlobalNameInfo* globalNameInfo)
{
switch (type.flavor)
@@ -1329,17 +1317,17 @@ static LegalVal declareVars(
newVarChain = &newVarChainStorage;
}
- String* fieldNameHint = nullptr;
+ UnownedStringSlice fieldNameHint;
String joinedNameHintStorage;
- if( nameHint )
+ if( nameHint.size() )
{
if( auto fieldNameHintDecoration = ee.key->findDecoration<IRNameHintDecoration>() )
{
- joinedNameHintStorage.append(*nameHint);
+ joinedNameHintStorage.append(nameHint);
joinedNameHintStorage.append(".");
- joinedNameHintStorage.append(fieldNameHintDecoration->name->text);
+ joinedNameHintStorage.append(fieldNameHintDecoration->getName());
- fieldNameHint = &joinedNameHintStorage;
+ fieldNameHint = joinedNameHintStorage.getUnownedSlice();
}
}
@@ -1409,7 +1397,7 @@ static LegalVal legalizeGlobalVar(
globalNameInfo.globalVar = irGlobalVar;
globalNameInfo.counter = 0;
- String const* nameHint = findNameHint(irGlobalVar);
+ UnownedStringSlice nameHint = findNameHint(irGlobalVar);
LegalVal newVal = declareVars(context, kIROp_GlobalVar, legalValueType, typeLayout, varChain, nameHint, &globalNameInfo);
// Register the new value as the replacement for the old
@@ -1452,7 +1440,7 @@ static LegalVal legalizeGlobalConstant(
// TODO: need to handle initializer here!
- String const* nameHint = findNameHint(irGlobalConstant);
+ UnownedStringSlice nameHint = findNameHint(irGlobalConstant);
LegalVal newVal = declareVars(context, kIROp_GlobalConstant, legalValueType, nullptr, nullptr, nameHint, &globalNameInfo);
// Register the new value as the replacement for the old
diff --git a/source/slang/ir-missing-return.cpp b/source/slang/ir-missing-return.cpp
index 0396fbce9..c32b71ab6 100644
--- a/source/slang/ir-missing-return.cpp
+++ b/source/slang/ir-missing-return.cpp
@@ -26,12 +26,9 @@ void checkForMissingReturnsRec(
}
}
- if( auto parentInst = as<IRParentInst>(inst) )
+ for( auto childInst : inst->getDecorationsAndChildren() )
{
- for( auto childInst : parentInst->getChildren() )
- {
- checkForMissingReturnsRec(childInst, sink);
- }
+ checkForMissingReturnsRec(childInst, sink);
}
}
diff --git a/source/slang/ir-restructure-scoping.cpp b/source/slang/ir-restructure-scoping.cpp
index 61b56e190..c5e628e71 100644
--- a/source/slang/ir-restructure-scoping.cpp
+++ b/source/slang/ir-restructure-scoping.cpp
@@ -424,7 +424,7 @@ void fixValueScoping(RegionTree* regionTree)
if(!parentRegion)
continue;
- for(auto inst : block->getChildren())
+ for(auto inst : block->getDecorationsAndChildren())
{
fixValueScopingForInst(inst, parentRegion, regionTree);
}
diff --git a/source/slang/ir-sccp.cpp b/source/slang/ir-sccp.cpp
index 6c7f637c1..66b370848 100644
--- a/source/slang/ir-sccp.cpp
+++ b/source/slang/ir-sccp.cpp
@@ -633,7 +633,7 @@ struct SCCPContext
// may in turn add other blocks/instructions to
// the work lists.
//
- for( auto inst : block->getChildren() )
+ for( auto inst : block->getDecorationsAndChildren() )
{
updateValueForInst(inst);
}
@@ -702,7 +702,7 @@ struct SCCPContext
List<IRInst*> instsToRemove;
for( auto block : code->getBlocks() )
{
- for( auto inst : block->getChildren() )
+ for( auto inst : block->getDecorationsAndChildren() )
{
// We look for instructions that have a constnat value on
// the lattice.
@@ -869,7 +869,7 @@ struct SCCPContext
// err on the side of allowing unreachable code without
// a warning.
//
- block->removeAndDeallocateAllChildren();
+ block->removeAndDeallocateAllDecorationsAndChildren();
}
//
// At this point every one of our unreachable blocks is empty,
@@ -929,14 +929,10 @@ static void applySparseConditionalConstantPropagationRec(
}
}
- if( auto parentInst = as<IRParentInst>(inst) )
+ for( auto childInst : inst->getDecorationsAndChildren() )
{
- for( auto childInst : parentInst->getChildren() )
- {
- applySparseConditionalConstantPropagationRec(shared, childInst);
- }
+ applySparseConditionalConstantPropagationRec(shared, childInst);
}
-
}
void applySparseConditionalConstantPropagation(
diff --git a/source/slang/ir-serialize.cpp b/source/slang/ir-serialize.cpp
index 03e10c8e2..0fc8a0806 100644
--- a/source/slang/ir-serialize.cpp
+++ b/source/slang/ir-serialize.cpp
@@ -16,12 +16,9 @@ namespace Slang {
/* Note that an IRInst can be derived from, but when it derived from it's new members are IRUse variables, and they in
effect alias over the operands - and reflected in the operand count. There _could_ be other members after these IRUse
-variables, but in practice there do not appear to be.
-
-The only difference to this is IRParentInst derived types, as it contains IRInstListBase children. Thus IRParentInst derived classes can
-have no operands - because it would write over the top of IRInstListBase. BUT they can contain members after the list
-types which do this are
+variables, but only a few types include extra data, and these do not have any operands:
+* IRConstant - Needs special-case handling
* IRModuleInst - Presumably we can just set to the module pointer on reconstruction
* IRGlobalValue - There are types derived from this type, but they don't add a parameter
@@ -44,12 +41,6 @@ bother to check if it's correct, and just casts it.
{ 0, 0 } // Int64,
};
-static bool isParentDerived(IROp opIn)
-{
- const int op = (kIROpMeta_PseudoOpMask & opIn);
- return op >= kIROp_FirstParentInst && op <= kIROp_LastParentInst;
-}
-
static bool isGlobalValueDerived(IROp opIn)
{
const int op = (kIROpMeta_PseudoOpMask & opIn);
@@ -273,7 +264,6 @@ size_t IRSerialData::calcSizeInBytes() const
return
_calcArraySize(m_insts) +
_calcArraySize(m_childRuns) +
- _calcArraySize(m_decorationRuns) +
_calcArraySize(m_externalOperands) +
_calcArraySize(m_stringTable) +
/* Raw source locs */
@@ -293,7 +283,6 @@ void IRSerialData::clear()
memset(&m_insts[0], 0, sizeof(Inst));
m_childRuns.Clear();
- m_decorationRuns.Clear();
m_externalOperands.Clear();
m_rawSourceLocs.Clear();
@@ -307,8 +296,6 @@ void IRSerialData::clear()
m_stringTable.SetSize(2);
m_stringTable[int(kNullStringIndex)] = 0;
m_stringTable[int(kEmptyStringIndex)] = 0;
-
- m_decorationBaseIndex = 0;
}
template <typename T>
@@ -344,10 +331,8 @@ static bool _isEqual(const List<T>& aIn, const List<T>& bIn)
bool IRSerialData::operator==(const ThisType& rhs) const
{
return (this == &rhs) ||
- (m_decorationBaseIndex == rhs.m_decorationBaseIndex &&
- _isEqual(m_insts, rhs.m_insts) &&
+ (_isEqual(m_insts, rhs.m_insts) &&
_isEqual(m_childRuns, rhs.m_childRuns) &&
- _isEqual(m_decorationRuns, rhs.m_decorationRuns) &&
_isEqual(m_externalOperands, rhs.m_externalOperands) &&
_isEqual(m_rawSourceLocs, rhs.m_rawSourceLocs) &&
_isEqual(m_stringTable, rhs.m_stringTable));
@@ -363,33 +348,6 @@ void IRSerialWriter::_addInstruction(IRInst* inst)
// Add to the map
m_instMap.Add(inst, Ser::InstIndex(m_insts.Count()));
m_insts.Add(inst);
-
- // Add all the decorations, to the list.
- // We don't add to the decoration map, as we only want to do this once all the instructions have been hit
- if (inst->firstDecoration)
- {
- m_instWithFirstDecoration.Add(inst);
-
- IRDecoration* decor = inst->firstDecoration;
-
- const int initialNumDecor = int(m_decorations.Count());
- while (decor)
- {
- m_decorations.Add(decor);
- decor = decor->next;
- }
-
- const Ser::SizeType numDecor = Ser::SizeType(int(m_decorations.Count()) - initialNumDecor);
-
- Ser::InstRun run;
- run.m_parentIndex = m_instMap[inst];
-
- // NOTE! This isn't quite correct, as we need to correct for when all the instructions are added, this is done at the end
- run.m_startInstIndex = Ser::InstIndex(initialNumDecor);
- run.m_numChildren = numDecor;
-
- m_serialData->m_decorationRuns.Add(run);
- }
}
// Find a view index that matches the view by file (and perhaps other characteristics in the future)
@@ -433,7 +391,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
m_decorations.Clear();
// Stack for parentInst
- List<IRParentInst*> parentInstStack;
+ List<IRInst*> parentInstStack;
IRModuleInst* moduleInst = module->getModuleInst();
parentInstStack.Add(moduleInst);
@@ -445,7 +403,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
while (parentInstStack.Count())
{
// If it's in the stack it is assumed it is already in the inst map
- IRParentInst* parentInst = parentInstStack.Last();
+ IRInst* parentInst = parentInstStack.Last();
parentInstStack.RemoveLast();
SLANG_ASSERT(m_instMap.ContainsKey(parentInst));
@@ -453,7 +411,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
// cos we want breadth first so the order of children is the same as their index order, meaning we don't need to store explicit indices
const Ser::InstIndex startChildInstIndex = Ser::InstIndex(m_insts.Count());
- IRInstListBase childrenList = parentInst->getChildren();
+ IRInstListBase childrenList = parentInst->getDecorationsAndChildren();
for (IRInst* child : childrenList)
{
// This instruction can't be in the map...
@@ -461,11 +419,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
_addInstruction(child);
- IRParentInst* childAsParent = as<IRParentInst>(child);
- if (childAsParent)
- {
- parentInstStack.Add(childAsParent);
- }
+ parentInstStack.Add(child);
}
// If it had any children, then store the information about it
@@ -480,32 +434,10 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
}
}
- // Now fix the decorations
- {
- const int decorationBaseIndex = int(m_insts.Count());
- m_serialData->m_decorationBaseIndex = decorationBaseIndex;
- const int numDecorRuns = int(m_serialData->m_decorationRuns.Count());
-
- // Work out the total num of decoration
- int totalNumDecorations = 0;
- if (numDecorRuns)
- {
- const auto& lastDecorInfo = m_serialData->m_decorationRuns.Last();
- totalNumDecorations = int(lastDecorInfo.m_startInstIndex) + lastDecorInfo.m_numChildren;
- }
-
- // Fix the indices
- for (int i = 0; i < numDecorRuns; ++i)
- {
- Ser::InstRun& info = m_serialData->m_decorationRuns[i];
- info.m_startInstIndex = Ser::InstIndex(decorationBaseIndex + int(info.m_startInstIndex));
- }
-
- // Set to the right size
- m_serialData->m_insts.SetSize(decorationBaseIndex + totalNumDecorations);
- // Clear all instructions
- memset(m_serialData->m_insts.begin(), 0, sizeof(Ser::Inst) * m_serialData->m_insts.Count());
- }
+ // Set to the right size
+ m_serialData->m_insts.SetSize(m_insts.Count());
+ // Clear all instructions
+ memset(m_serialData->m_insts.begin(), 0, sizeof(Ser::Inst) * m_serialData->m_insts.Count());
// Need to set up the actual instructions
{
@@ -543,6 +475,12 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
dstInst.m_payload.m_int64 = irConst->value.intVal;
break;
}
+ case kIROp_PtrLit:
+ {
+ dstInst.m_payloadType = PayloadType::Int64;
+ dstInst.m_payload.m_int64 = (intptr_t) irConst->value.ptrVal;
+ break;
+ }
case kIROp_FloatLit:
{
dstInst.m_payloadType = PayloadType::Float64;
@@ -616,128 +554,6 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
}
}
- // Now need to do the decorations
-
- {
- const int decorationBaseIndex = m_serialData->m_decorationBaseIndex;
- const int numDecor = int(m_decorations.Count());
- SLANG_ASSERT(decorationBaseIndex + numDecor == int(m_serialData->m_insts.Count()));
-
- // Have to be able to store in a byte!
- SLANG_COMPILE_TIME_ASSERT(kIROpCount + kIRDecorationOp_CountOf < 0x100);
-
- for (int i = 0; i < numDecor; ++i)
- {
- IRDecoration* srcDecor = m_decorations[i];
- Ser::Inst& dstInst = m_serialData->m_insts[decorationBaseIndex + i];
-
- dstInst.m_op = uint8_t(kIROpCount + srcDecor->op);
-
- switch (srcDecor->op)
- {
- case kIRDecorationOp_HighLevelDecl:
- {
- // TODO!
- // Decl* decl;
- break;
- }
- case kIRDecorationOp_Layout:
- {
- // TODO!
- // Layout* layout;
- break;
- }
- case kIRDecorationOp_LoopControl:
- {
- auto loopDecor = static_cast<IRLoopControlDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::UInt32;
- dstInst.m_payload.m_uint32 = uint32_t(loopDecor->mode);
- break;
- }
- case kIRDecorationOp_Target:
- {
- auto targetDecor = static_cast<IRTargetDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::String_1;
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(targetDecor->targetName);
- break;
- }
- case kIRDecorationOp_TargetIntrinsic:
- {
- auto targetDecor = static_cast<IRTargetIntrinsicDecoration*>(srcDecor);
- dstInst.m_payloadType = PayloadType::String_2;
-
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(targetDecor->targetName);
- dstInst.m_payload.m_stringIndices[1] = getStringIndex(targetDecor->definition);
- break;
- }
- case kIRDecorationOp_GLSLOuterArray:
- {
- auto arrayDecor = static_cast<IRGLSLOuterArrayDecoration*>(srcDecor);
- dstInst.m_payloadType = PayloadType::String_1;
-
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(arrayDecor->outerArrayName);
- break;
- }
- case kIRDecorationOp_Semantic:
- {
- auto semanticDecor = static_cast<IRSemanticDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::String_1;
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(semanticDecor->semanticName);
- break;
- }
- case kIRDecorationOp_InterpolationMode:
- {
- auto semanticDecor = static_cast<IRInterpolationModeDecoration*>(srcDecor);
- dstInst.m_payloadType = PayloadType::UInt32;
- dstInst.m_payload.m_uint32 = uint32_t(semanticDecor->mode);
- break;
- }
- case kIRDecorationOp_NameHint:
- {
- auto nameDecor = static_cast<IRNameHintDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::String_1;
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(nameDecor->name);
- break;
- }
- case kIRDecorationOp_VulkanRayPayload:
- case kIRDecorationOp_VulkanCallablePayload:
- case kIRDecorationOp_VulkanHitAttributes:
- case kIRDecorationOp_EarlyDepthStencil:
- case kIRDecorationOp_ReadNone:
- case kIRDecorationOp_GloballyCoherent:
- {
- dstInst.m_payloadType = PayloadType::Empty;
- break;
- }
- case kIRDecorationOp_RequireGLSLExtension:
- {
- auto extDecor = static_cast<IRRequireGLSLExtensionDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::String_1;
- dstInst.m_payload.m_stringIndices[0] = getStringIndex(extDecor->extensionName);
- break;
- }
- case kIRDecorationOp_RequireGLSLVersion:
- {
- auto verDecor = static_cast<IRRequireGLSLVersionDecoration*>(srcDecor);
-
- dstInst.m_payloadType = PayloadType::UInt32;
- dstInst.m_payload.m_uint32 = uint32_t(verDecor->languageVersion);
- break;
- }
- default:
- {
- SLANG_ASSERT(!"Unhandled decoration type");
- return SLANG_FAIL;
- }
- }
- }
- }
-
// Convert strings into a string table
{
SerialStringTableUtil::encodeStringTable(m_stringSlicePool, serialData->m_stringTable);
@@ -1083,7 +899,6 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
totalSize += sizeof(Bin::SlangHeader) +
_calcInstChunkSize(compressionType, data.m_insts) +
_calcChunkSize(compressionType, data.m_childRuns) +
- _calcChunkSize(compressionType, data.m_decorationRuns) +
_calcChunkSize(compressionType, data.m_externalOperands) +
_calcChunkSize(Bin::CompressionType::None, data.m_stringTable) +
_calcChunkSize(Bin::CompressionType::None, data.m_rawSourceLocs);
@@ -1099,7 +914,6 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
Bin::SlangHeader slangHeader;
slangHeader.m_chunk.m_type = Bin::kSlangFourCc;
slangHeader.m_chunk.m_size = uint32_t(sizeof(slangHeader) - sizeof(Bin::Chunk));
- slangHeader.m_decorationBase = uint32_t(data.m_decorationBaseIndex);
slangHeader.m_compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
stream->Write(&slangHeader, sizeof(slangHeader));
@@ -1107,7 +921,6 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
SLANG_RETURN_ON_FAIL(_writeInstArrayChunk(compressionType, Bin::kInstFourCc, data.m_insts, stream));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kChildRunFourCc, data.m_childRuns, stream));
- SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kDecoratorRunFourCc, data.m_decorationRuns, stream));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kExternalOperandsFourCc, data.m_externalOperands, stream));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, Bin::kStringFourCc, data.m_stringTable, stream));
@@ -1430,7 +1243,6 @@ int64_t _calcChunkTotalSize(const IRSerialBinary::Chunk& chunk)
stream->Read(&slangHeader.m_chunk + 1, sizeof(slangHeader) - sizeof(chunk));
- dataOut->m_decorationBaseIndex = slangHeader.m_decorationBase;
remainingBytes -= _calcChunkTotalSize(chunk);
break;
}
@@ -1441,13 +1253,6 @@ int64_t _calcChunkTotalSize(const IRSerialBinary::Chunk& chunk)
remainingBytes -= _calcChunkTotalSize(chunk);
break;
}
- case SLANG_MAKE_COMPRESSED_FOUR_CC(Bin::kDecoratorRunFourCc):
- case Bin::kDecoratorRunFourCc:
- {
- SLANG_RETURN_ON_FAIL(_readArrayChunk(slangHeader, chunk, stream, &bytesRead, dataOut->m_decorationRuns));
- remainingBytes -= _calcChunkTotalSize(chunk);
- break;
- }
case SLANG_MAKE_COMPRESSED_FOUR_CC(Bin::kChildRunFourCc):
case Bin::kChildRunFourCc:
{
@@ -1486,135 +1291,6 @@ int64_t _calcChunkTotalSize(const IRSerialBinary::Chunk& chunk)
return SLANG_OK;
}
-IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
-{
- typedef Ser::Inst::PayloadType PayloadType;
-
- IRDecorationOp decorOp = IRDecorationOp(srcInst.m_op - kIROpCount);
- SLANG_ASSERT(decorOp < kIRDecorationOp_CountOf);
-
- switch (decorOp)
- {
- case kIRDecorationOp_HighLevelDecl:
- {
- // TODO!
- // Decl* decl;
- return createEmptyDecoration<IRHighLevelDeclDecoration>(m_module);
- }
- case kIRDecorationOp_Layout:
- {
- // TODO!
- // Layout* layout;
- return createEmptyDecoration<IRLayoutDecoration>(m_module);
- }
- case kIRDecorationOp_LoopControl:
- {
- auto decor = createEmptyDecoration<IRLoopControlDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::UInt32);
- decor->mode = IRLoopControl(srcInst.m_payload.m_uint32);
- return decor;
- }
- case kIRDecorationOp_Target:
- {
- auto decor = createEmptyDecoration<IRTargetDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- decor->targetName = m_stringRepresentationCache.getStringRepresentation(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- return decor;
- }
- case kIRDecorationOp_TargetIntrinsic:
- {
- auto decor = createEmptyDecoration<IRTargetIntrinsicDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_2);
- decor->targetName = m_stringRepresentationCache.getStringRepresentation(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- decor->definition = m_stringRepresentationCache.getStringRepresentation(StringHandle(srcInst.m_payload.m_stringIndices[1]));
- return decor;
- }
- case kIRDecorationOp_GLSLOuterArray:
- {
- auto decor = createEmptyDecoration<IRGLSLOuterArrayDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- decor->outerArrayName = m_stringRepresentationCache.getCStr(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- return decor;
- }
- case kIRDecorationOp_Semantic:
- {
- auto decor = createEmptyDecoration<IRSemanticDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- decor->semanticName = m_stringRepresentationCache.getName(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- return decor;
- }
- case kIRDecorationOp_InterpolationMode:
- {
- auto decor = createEmptyDecoration<IRInterpolationModeDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == Ser::Inst::PayloadType::UInt32);
- decor->mode = IRInterpolationMode(srcInst.m_payload.m_uint32);
- return decor;
- }
- case kIRDecorationOp_NameHint:
- {
- auto decor = createEmptyDecoration<IRNameHintDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- decor->name = m_stringRepresentationCache.getName(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- return decor;
- }
- case kIRDecorationOp_VulkanRayPayload:
- {
- auto decor = createEmptyDecoration<IRVulkanRayPayloadDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- case kIRDecorationOp_VulkanCallablePayload:
- {
- auto decor = createEmptyDecoration<IRVulkanCallablePayloadDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- case kIRDecorationOp_EarlyDepthStencil:
- {
- auto decor = createEmptyDecoration<IREarlyDepthStencilDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- case kIRDecorationOp_GloballyCoherent:
- {
- auto decor = createEmptyDecoration<IRGloballyCoherentDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- case kIRDecorationOp_VulkanHitAttributes:
- {
- auto decor = createEmptyDecoration<IRVulkanHitAttributesDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- case kIRDecorationOp_RequireGLSLExtension:
- {
- auto decor = createEmptyDecoration<IRRequireGLSLExtensionDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- decor->extensionName = m_stringRepresentationCache.getStringRepresentation(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- return decor;
- }
- case kIRDecorationOp_RequireGLSLVersion:
- {
- auto decor = createEmptyDecoration<IRRequireGLSLVersionDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == Ser::Inst::PayloadType::UInt32);
- decor->languageVersion = Int(srcInst.m_payload.m_uint32);
- return decor;
- }
- case kIRDecorationOp_ReadNone:
- {
- auto decor = createEmptyDecoration<IRReadNoneDecoration>(m_module);
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Empty);
- return decor;
- }
- default:
- {
- SLANG_ASSERT(!"Unhandled decoration type");
- return nullptr;
- }
- }
-}
-
/* static */Result IRSerialReader::read(const IRSerialData& data, Session* session, RefPtr<IRModule>& moduleOut)
{
typedef Ser::Inst::PayloadType PayloadType;
@@ -1633,18 +1309,14 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
// Add all the instructions
List<IRInst*> insts;
- List<IRDecoration*> decorations;
- const int numInsts = data.m_decorationBaseIndex;
- const int numDecorations = int(data.m_insts.Count() - numInsts);
+ const int numInsts = int(data.m_insts.Count());
SLANG_ASSERT(numInsts > 0);
insts.SetSize(numInsts);
insts[0] = nullptr;
- decorations.SetSize(numDecorations);
-
// 0 holds null
// 1 holds the IRModuleInst
{
@@ -1668,25 +1340,16 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
const IROp op((IROp)srcInst.m_op);
- if (isParentDerived(op))
+ if (isGlobalValueDerived(op))
{
// Cannot have operands
SLANG_ASSERT(srcInst.getNumOperands() == 0);
- if (isGlobalValueDerived(op))
- {
- IRGlobalValue* globalValueInst = static_cast<IRGlobalValue*>(createEmptyInstWithSize(module, op, sizeof(IRGlobalValue)));
- insts[i] = globalValueInst;
- // Set the global value
- SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
- globalValueInst->mangledName = m_stringRepresentationCache.getName(StringHandle(srcInst.m_payload.m_stringIndices[0]));
- }
- else
- {
- // Just needs to big enough to hold IRParentInst
- IRParentInst* parentInst = static_cast<IRParentInst*>(createEmptyInstWithSize(module, op, sizeof(IRParentInst)));
- insts[i] = parentInst;
- }
+ IRGlobalValue* globalValueInst = static_cast<IRGlobalValue*>(createEmptyInstWithSize(module, op, sizeof(IRGlobalValue)));
+ insts[i] = globalValueInst;
+ // Set the global value
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::String_1);
+ globalValueInst->mangledName = m_stringRepresentationCache.getName(StringHandle(srcInst.m_payload.m_stringIndices[0]));
}
else
{
@@ -1714,6 +1377,13 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
irConst->value.intVal = srcInst.m_payload.m_int64;
break;
}
+ case kIROp_PtrLit:
+ {
+ SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Int64);
+ irConst = static_cast<IRConstant*>(createEmptyInstWithSize(module, op, prefixSize + sizeof(void*)));
+ irConst->value.ptrVal = (void*) (intptr_t) srcInst.m_payload.m_int64;
+ break;
+ }
case kIROp_FloatLit:
{
SLANG_ASSERT(srcInst.m_payloadType == PayloadType::Float64);
@@ -1808,56 +1478,12 @@ IRDecoration* IRSerialReader::_createDecoration(const Ser::Inst& srcInst)
const auto& run = data.m_childRuns[i];
IRInst* inst = insts[int(run.m_parentIndex)];
- IRParentInst* parentInst = as<IRParentInst>(inst);
- SLANG_ASSERT(parentInst);
for (int j = 0; j < int(run.m_numChildren); ++j)
{
IRInst* child = insts[j + int(run.m_startInstIndex)];
SLANG_ASSERT(child->parent == nullptr);
- //child->parent = parentInst;
- child->insertAtEnd(parentInst);
- }
- }
- }
-
- // Create the decorations
- for (int i = 0; i < numDecorations; ++i)
- {
- IRDecoration* decor = _createDecoration(data.m_insts[i + numInsts]);
- if (!decor)
- {
- return SLANG_FAIL;
- }
- decorations[i] = decor;
- }
-
- // Associate the decorations with the instructions
-
- {
- const int decorationBaseIndex = m_serialData->m_decorationBaseIndex;
-
- const int numRuns = int(m_serialData->m_decorationRuns.Count());
- for (int i = 0; i < numRuns; ++i)
- {
- const Ser::InstRun& run = m_serialData->m_decorationRuns[i];
-
- // Decorations must be associated with instructions
- SLANG_ASSERT(int(run.m_parentIndex) < decorationBaseIndex);
-
- IRInst* inst = insts[int(run.m_parentIndex)];
- SLANG_ASSERT(int(run.m_startInstIndex) >= decorationBaseIndex && int(run.m_startInstIndex) + run.m_numChildren <= m_serialData->m_insts.Count());
-
- // Calculate the offset in the decoration list, which index 0, is decorationBaseIndex in instruction indices
- const int decorStartIndex = int(run.m_startInstIndex) - decorationBaseIndex;
-
- // Go in reverse order so that linked list is in same order as original
- for (int j = int(run.m_numChildren) - 1; j >= 0; --j)
- {
- IRDecoration* decor = decorations[decorStartIndex + j];
- // And to the linked list on the
- decor->next = inst->firstDecoration;
- inst->firstDecoration = decor;
+ child->insertAtEnd(inst);
}
}
}
diff --git a/source/slang/ir-serialize.h b/source/slang/ir-serialize.h
index ec560233f..c205e7a35 100644
--- a/source/slang/ir-serialize.h
+++ b/source/slang/ir-serialize.h
@@ -212,14 +212,12 @@ struct IRSerialData
size_t calcSizeInBytes() const;
/// Ctor
- IRSerialData() :
- m_decorationBaseIndex(0)
+ IRSerialData()
{}
List<Inst> m_insts; ///< The instructions
List<InstRun> m_childRuns; ///< Holds the information about children that belong to an instruction
- List<InstRun> m_decorationRuns; ///< Holds instruction decorations
List<InstIndex> m_externalOperands; ///< Holds external operands (for instructions with more than kNumOperands)
@@ -234,8 +232,6 @@ struct IRSerialData
List<char> m_debugStrings; ///< All of the debug strings
static const PayloadInfo s_payloadInfos[int(Inst::PayloadType::CountOf)];
-
- int m_decorationBaseIndex; ///< All decorations insts are at indices >= to this value
};
// --------------------------------------------------------------------------
@@ -323,12 +319,10 @@ struct IRSerialBinary
static const uint32_t kSlangFourCc = SLANG_FOUR_CC('S', 'L', 'N', 'G'); ///< Holds all the slang specific chunks
static const uint32_t kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
- static const uint32_t kDecoratorRunFourCc = SLANG_FOUR_CC('S', 'L', 'd', 'r');
static const uint32_t kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
static const uint32_t kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
static const uint32_t kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc);
- static const uint32_t kCompressedDecoratorRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kDecoratorRunFourCc);
static const uint32_t kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc);
static const uint32_t kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc);
@@ -339,7 +333,6 @@ struct IRSerialBinary
struct SlangHeader
{
Chunk m_chunk;
- uint32_t m_decorationBase;
uint32_t m_compressionType; ///< Holds the compression type used (if used at all)
};
struct ArrayHeader
diff --git a/source/slang/ir-ssa.cpp b/source/slang/ir-ssa.cpp
index 973030852..d893137de 100644
--- a/source/slang/ir-ssa.cpp
+++ b/source/slang/ir-ssa.cpp
@@ -364,7 +364,7 @@ void maybeApplyNameHint(
{
if( !val->findDecoration<IRNameHintDecoration>() )
{
- context->getBuilder()->addDecoration<IRNameHintDecoration>(val)->name = nameHint->name;
+ context->getBuilder()->addNameHintDecoration(val, nameHint->getName());
}
}
}
@@ -838,7 +838,9 @@ void processBlock(
}
}
- blockInfo->builder.setInsertBefore(block->getLastChild());
+ auto terminator = block->getTerminator();
+ SLANG_ASSERT(terminator);
+ blockInfo->builder.setInsertBefore(terminator);
// Once we are done with all of the instructions
// in a block, we can mark it as "filled," which
@@ -1066,9 +1068,16 @@ void constructSSA(ConstructSSAContext* context)
newArgCount,
newArgs.Buffer());
- // Swap decorations over to the new instruction
- newTerminator->firstDecoration = oldTerminator->firstDecoration;
- oldTerminator->firstDecoration = nullptr;
+ // Swap decorations (all children, really) over to the new instruction
+ //
+ // TODO: We might want to encapsualte this in a reusable subroutine if
+ // we often need to copy decorations from one instruction to another.
+ //
+ while( auto firstChild = oldTerminator->getFirstDecoration() )
+ {
+ firstChild->removeFromParent();
+ firstChild->insertAtEnd(newTerminator);
+ }
// A terminator better not have uses, so we shouldn't have
// to replace them.
diff --git a/source/slang/ir-validate.cpp b/source/slang/ir-validate.cpp
index 1f5112a51..924ec71b3 100644
--- a/source/slang/ir-validate.cpp
+++ b/source/slang/ir-validate.cpp
@@ -35,10 +35,10 @@ namespace Slang
void validateIRInstChildren(
IRValidateContext* context,
- IRParentInst* parent)
+ IRInst* parent)
{
IRInst* prevChild = nullptr;
- for (auto child = parent->getFirstChild(); child; child = child->getNextInst())
+ for(auto child : parent->getDecorationsAndChildren() )
{
// We need to check the integrity of the parent/next/prev links of
// all of our instructions
@@ -53,7 +53,7 @@ namespace Slang
// * The last instruction of a block should always be a terminator
// * No other instruction should be a terminator
//
- if(as<IRBlock>(parent) && (child == parent->getLastChild()))
+ if(as<IRBlock>(parent) && (child == parent->getLastDecorationOrChild()))
{
validate(context, as<IRTerminatorInst>(child) != nullptr, child, "last instruction in block must be terminator");
}
@@ -174,10 +174,7 @@ namespace Slang
// If `inst` is itself a parent instruction, then we need to recursively
// validate its children.
- if (auto parent = as<IRParentInst>(inst))
- {
- validateIRInstChildren(context, parent);
- }
+ validateIRInstChildren(context, inst);
}
void validateIRModule(IRModule* module, DiagnosticSink* sink)
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index c0715fca3..bc33527cf 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -166,6 +166,19 @@ namespace Slang
}
}
+ // IRInstListBase
+
+ void IRInstListBase::Iterator::operator++()
+ {
+ if (inst)
+ {
+ inst = inst->next;
+ }
+ }
+
+ IRInstListBase::Iterator IRInstListBase::begin() { return Iterator(first); }
+ IRInstListBase::Iterator IRInstListBase::end() { return Iterator(last ? last->next : nullptr); }
+
//
IRUse* IRInst::getOperands()
@@ -180,9 +193,9 @@ namespace Slang
return (IRUse*)(this + 1);
}
- IRDecoration* IRInst::findDecorationImpl(IRDecorationOp decorationOp)
+ IRDecoration* IRInst::findDecorationImpl(IROp decorationOp)
{
- for( auto dd = firstDecoration; dd; dd = dd->next )
+ for(auto dd : getDecorations())
{
if(dd->op == decorationOp)
return dd;
@@ -239,14 +252,31 @@ namespace Slang
void IRBlock::addParam(IRParam* param)
{
- auto lastParam = getLastParam();
- if (lastParam)
+ // If there are any existing parameters,
+ // then insert after the last of them.
+ //
+ if (auto lastParam = getLastParam())
{
param->insertAfter(lastParam);
}
+ //
+ // Otherwise, if there are any existing
+ // "ordinary" instructions, insert before
+ // the first of them.
+ //
+ else if(auto firstOrdinary = getFirstOrdinaryInst())
+ {
+ param->insertBefore(firstOrdinary);
+ }
+ //
+ // Otherwise the block currently has neither
+ // parameters nor orindary instructions,
+ // so we can safely insert at the end of
+ // the list of (raw) children.
+ //
else
{
- param->insertAtStart(this);
+ param->insertAtEnd(this);
}
}
@@ -585,7 +615,7 @@ namespace Slang
}
- void IRBuilder::setInsertInto(IRParentInst* insertInto)
+ void IRBuilder::setInsertInto(IRInst* insertInto)
{
insertIntoParent = insertInto;
insertBeforeInst = nullptr;
@@ -620,7 +650,7 @@ namespace Slang
// Given two parent instructions, pick the better one to use as as
// insertion location for a "hoistable" instruction.
//
- IRParentInst* mergeCandidateParentsForHoistableInst(IRParentInst* left, IRParentInst* right)
+ IRInst* mergeCandidateParentsForHoistableInst(IRInst* left, IRInst* right)
{
// If the candidates are both the same, then who cares?
if(left == right) return left;
@@ -681,7 +711,7 @@ namespace Slang
// If the non-block on the left or right is a descendent of
// the other, then that is what we should use.
//
- IRParentInst* parentNonBlock = nullptr;
+ IRInst* parentNonBlock = nullptr;
for (auto ll = leftNonBlock; ll; ll = ll->getParent())
{
if (ll == rightNonBlock)
@@ -715,7 +745,7 @@ namespace Slang
parentNonBlock = leftNonBlock;
}
- IRParentInst* parent = parentNonBlock;
+ IRInst* parent = parentNonBlock;
// At this point we've found a non-block parent where we
// could stick things, but we have to fix things up in
@@ -791,19 +821,6 @@ namespace Slang
return inst;
}
-
- IRDecoration* createEmptyDecoration(
- IRModule* module,
- IRDecorationOp op,
- size_t sizeInBytes)
- {
- SLANG_ASSERT(sizeInBytes >= sizeof(IRDecoration));
- SLANG_ASSERT(module);
- IRDecoration* decor = (IRDecoration*)module->memoryArena.allocateAndZero(sizeInBytes);
- decor->op = op;
- return decor;
- }
-
// Given an instruction that represents a constant, a type, etc.
// Try to "hoist" it as far toward the global scope as possible
// to insert it at a location where it will be maximally visible.
@@ -814,7 +831,7 @@ namespace Slang
{
// Start with the assumption that we would insert this instruction
// into the global scope (the instruction that represents the module)
- IRParentInst* parent = builder->getModule()->getModuleInst();
+ IRInst* parent = builder->getModule()->getModuleInst();
// The above decision might be invalid, because there might be
// one or more operands of the instruction that are defined in
@@ -1177,13 +1194,14 @@ namespace Slang
return code;
}
- UnownedStringSlice IRConstant::getStringSlice() const
+ UnownedStringSlice IRConstant::getStringSlice()
{
assert(op == kIROp_StringLit);
// If the transitory decoration is set, then this is uses the transitoryStringVal for the text storage.
// This is typically used when we are using a transitory IRInst held on the stack (such that it can be looked up in cached),
// that just points to a string elsewhere, and NOT the typical normal style, where the string is held after the instruction in memory.
- if (firstDecoration && firstDecoration->op == kIRDecorationOp_Transitory)
+ //
+ if(findDecorationImpl(kIROp_TransitoryDecoration))
{
return UnownedStringSlice(value.transitoryStringVal.chars, value.transitoryStringVal.numChars);
}
@@ -1217,6 +1235,10 @@ namespace Slang
// ... we can just compare as bits
return value.intVal == rhs.value.intVal;
}
+ case kIROp_PtrLit:
+ {
+ return value.ptrVal == rhs.value.ptrVal;
+ }
case kIROp_StringLit:
{
return getStringSlice() == rhs.getStringSlice();
@@ -1243,6 +1265,10 @@ namespace Slang
// ... we can just compare as bits
return combineHash(code, Slang::GetHashCode(value.intVal));
}
+ case kIROp_PtrLit:
+ {
+ return combineHash(code, Slang::GetHashCode(value.ptrVal));
+ }
case kIROp_StringLit:
{
const UnownedStringSlice slice = getStringSlice();
@@ -1283,6 +1309,10 @@ namespace Slang
switch (keyInst.op)
{
+ default:
+ SLANG_UNEXPECTED("missing case for IR constant");
+ break;
+
case kIROp_BoolLit:
case kIROp_IntLit:
{
@@ -1296,6 +1326,12 @@ namespace Slang
irValue->value.floatVal = keyInst.value.floatVal;
break;
}
+ case kIROp_PtrLit:
+ {
+ irValue = static_cast<IRConstant*>(createInstWithSizeImpl(builder, keyInst.op, keyInst.getFullType(), prefixSize + sizeof(void*)));
+ irValue->value.ptrVal = keyInst.value.ptrVal;
+ break;
+ }
case kIROp_StringLit:
{
const UnownedStringSlice slice = keyInst.getStringSlice();
@@ -1363,8 +1399,10 @@ namespace Slang
memset(&keyInst, 0, sizeof(keyInst));
// Mark that this is on the stack...
- static IRDecoration stackDecoration = IRDecoration::make(kIRDecorationOp_Transitory);
- keyInst.firstDecoration = &stackDecoration;
+ IRDecoration stackDecoration;
+ memset(&stackDecoration, 0, sizeof(stackDecoration));
+ stackDecoration.op = kIROp_TransitoryDecoration;
+ stackDecoration.insertAtEnd(&keyInst);
keyInst.op = kIROp_StringLit;
keyInst.typeUse.usedValue = getStringType();
@@ -1375,6 +1413,19 @@ namespace Slang
return static_cast<IRStringLit*>(findOrEmitConstant(this, keyInst));
}
+
+ IRPtrLit* IRBuilder::getPtrValue(void* value)
+ {
+ IRType* type = getPtrType(getVoidType());
+
+ IRConstant keyInst;
+ memset(&keyInst, 0, sizeof(keyInst));
+ keyInst.op = kIROp_PtrLit;
+ keyInst.typeUse.usedValue = type;
+ keyInst.value.ptrVal = value;
+ return (IRPtrLit*) findOrEmitConstant(this, keyInst);
+ }
+
IRInst* findOrEmitHoistableInst(
IRBuilder* builder,
@@ -2162,19 +2213,6 @@ namespace Slang
return inst;
}
- IRNotePatchConstantFunc* IRBuilder::emitNotePatchConstantFunc(
- IRInst* func)
- {
- auto inst = createInst<IRNotePatchConstantFunc>(
- this,
- kIROp_NotePatchConstantFunc,
- nullptr,
- func);
-
- addInst(inst);
- return inst;
- }
-
IRInst* IRBuilder::emitFieldExtract(
IRType* type,
IRInst* base,
@@ -2549,18 +2587,40 @@ namespace Slang
return inst;
}
- IRHighLevelDeclDecoration* IRBuilder::addHighLevelDeclDecoration(IRInst* inst, Decl* decl)
+ IRDecoration* IRBuilder::addDecoration(IRInst* value, IROp op, IRInst* const* operands, Int operandCount)
{
- auto decoration = addDecoration<IRHighLevelDeclDecoration>(inst, kIRDecorationOp_HighLevelDecl);
- decoration->decl = decl;
+ auto decoration = createInstWithTrailingArgs<IRDecoration>(
+ this,
+ op,
+ getVoidType(),
+ operandCount,
+ operands);
+
+ // Decoration order should not, in general, be semantically
+ // meaningful, so we will elect to insert a new decoration
+ // at the start of an instruction (constant time) rather
+ // than at the end of any existing list of deocrations
+ // (which would take time linear in the number of decorations).
+ //
+ // TODO: revisit this if maintaining decoration ordering
+ // from input source code is desirable.
+ //
+ decoration->insertAtStart(value);
+
return decoration;
}
- IRLayoutDecoration* IRBuilder::addLayoutDecoration(IRInst* inst, Layout* layout)
+
+ void IRBuilder::addHighLevelDeclDecoration(IRInst* inst, Decl* decl)
{
- auto decoration = addDecoration<IRLayoutDecoration>(inst);
- decoration->layout = addRefObjectToFree(layout);
- return decoration;
+ auto ptrConst = getPtrValue(addRefObjectToFree(decl));
+ addDecoration(inst, kIROp_HighLevelDeclDecoration, ptrConst);
+ }
+
+ void IRBuilder::addLayoutDecoration(IRInst* inst, Layout* layout)
+ {
+ auto ptrConst = getPtrValue(addRefObjectToFree(layout));
+ addDecoration(inst, kIROp_LayoutDecoration, ptrConst);
}
//
@@ -2905,74 +2965,25 @@ namespace Slang
for(; inst; inst = inst->getNextInst())
{
dumpInst(context, inst);
+ dump(context, "\n");
}
}
+ static void dumpInstBody(
+ IRDumpContext* context,
+ IRInst* inst);
+
void dumpIRDecorations(
IRDumpContext* context,
IRInst* inst)
{
- for( auto dd = inst->firstDecoration; dd; dd = dd->next )
+ for(auto dd : inst->getDecorations())
{
- switch( dd->op )
- {
- case kIRDecorationOp_Target:
- {
- auto decoration = (IRTargetDecoration*) dd;
-
- dump(context, "\n");
- dumpIndent(context);
- dump(context, "[target(");
- dump(context, StringRepresentation::getData(decoration->targetName));
- dump(context, ")]");
- }
- break;
+ dump(context, "[");
+ dumpInstBody(context, dd);
+ dump(context, "]\n");
- case kIRDecorationOp_TargetIntrinsic:
- {
- auto decoration = (IRTargetIntrinsicDecoration*) dd;
-
- dump(context, "\n");
- dumpIndent(context);
- dump(context, "[targetIntrinsic(");
- dump(context, StringRepresentation::getData(decoration->targetName));
- dump(context, ", ");
- dump(context, StringRepresentation::getData(decoration->definition));
- dump(context, ")]");
- }
- break;
-
- case kIRDecorationOp_VulkanRayPayload:
- {
- dump(context, "\n[__vulkanRayPayload]");
- }
- break;
- case kIRDecorationOp_VulkanCallablePayload:
- {
- dump(context, "\n[__vulkanCallPayload]");
- }
- break;
- case kIRDecorationOp_VulkanHitAttributes:
- {
- dump(context, "\n[__vulkanHitAttributes]");
- }
- break;
- case kIRDecorationOp_ReadNone:
- {
- dump(context, "\n[__readNone]");
- }
- break;
- case kIRDecorationOp_EarlyDepthStencil:
- {
- dump(context, "\n[earlydepthstencil]");
- }
- break;
- case kIRDecorationOp_GloballyCoherent:
- {
- dump(context, "\n[globallycoherent]");
- }
- break;
- }
+ dumpIndent(context);
}
}
@@ -2982,7 +2993,6 @@ namespace Slang
{
auto opInfo = getIROpInfo(code->op);
- dump(context, "\n");
dumpIndent(context);
dump(context, opInfo.name);
dump(context, " ");
@@ -3038,11 +3048,10 @@ namespace Slang
void dumpIRParentInst(
IRDumpContext* context,
- IRParentInst* inst)
+ IRInst* inst)
{
auto opInfo = getIROpInfo(inst->op);
- dump(context, "\n");
dumpIndent(context);
dump(context, opInfo.name);
dump(context, " ");
@@ -3063,9 +3072,10 @@ namespace Slang
dump(context, "{\n");
context->indent++;
- for (auto child = inst->getFirstChild(); child; child = child->getNextInst())
+ for(auto child : inst->getChildren())
{
dumpInst(context, child);
+ dump(context, "\n");
}
context->indent--;
@@ -3086,19 +3096,19 @@ namespace Slang
for (auto ii : witnessTable->getChildren())
{
dumpInst(context, ii);
+ dump(context, "\n");
}
context->indent--;
dump(context, "}\n");
}
- static void dumpInst(
+ static void dumpInstBody(
IRDumpContext* context,
IRInst* inst)
{
if (!inst)
{
- dumpIndent(context);
dump(context, "<null>");
return;
}
@@ -3121,7 +3131,7 @@ namespace Slang
case kIROp_WitnessTable:
case kIROp_StructType:
- dumpIRParentInst(context, (IRWitnessTable*)inst);
+ dumpIRParentInst(context, inst);
return;
case kIROp_WitnessTableEntry:
@@ -3133,8 +3143,6 @@ namespace Slang
}
// Okay, we have a seemingly "ordinary" op now
- dumpIndent(context);
-
auto opInfo = getIROpInfo(op);
auto dataType = inst->getDataType();
auto rate = inst->getRate();
@@ -3201,8 +3209,14 @@ namespace Slang
}
dump(context, ")");
+ }
- dump(context, "\n");
+ static void dumpInst(
+ IRDumpContext* context,
+ IRInst* inst)
+ {
+ dumpIndent(context);
+ dumpInstBody(context, inst);
}
void dumpIRModule(
@@ -3212,6 +3226,7 @@ namespace Slang
for(auto ii : module->getGlobalInsts())
{
dumpInst(context, ii);
+ dump(context, "\n");
}
}
@@ -3257,6 +3272,57 @@ namespace Slang
//
//
+ IRDecoration* IRInst::getFirstDecoration()
+ {
+ return as<IRDecoration>(getFirstDecorationOrChild());
+ }
+
+ IRDecoration* IRInst::getLastDecoration()
+ {
+ IRDecoration* decoration = getFirstDecoration();
+ if (!decoration) return nullptr;
+
+ while (auto nextDecoration = decoration->getNextDecoration())
+ decoration = nextDecoration;
+
+ return decoration;
+ }
+
+ IRInstList<IRDecoration> IRInst::getDecorations()
+ {
+ return IRInstList<IRDecoration>(
+ getFirstDecoration(),
+ getLastDecoration());
+ }
+
+ IRInst* IRInst::getFirstChild()
+ {
+ // The children come after any decorations,
+ // so if there are any decorations, then the
+ // first child is right after the last decoration.
+ //
+ if(auto lastDecoration = getLastDecoration())
+ return lastDecoration->getNextInst();
+ //
+ // Otherwise, there must be no decorations, so
+ // that the first "child or decoration" is a child.
+ //
+ return getFirstDecorationOrChild();
+ }
+
+ IRInst* IRInst::getLastChild()
+ {
+ // The children come after any decorations, so
+ // that the last item in the list of children
+ // and decorations is the last child *unless*
+ // it is a decoration, in which case there are
+ // no children.
+ //
+ auto lastChild = getLastDecorationOrChild();
+ return as<IRDecoration>(lastChild) ? nullptr : lastChild;
+ }
+
+
IRRate* IRInst::getRate()
{
if(auto rateQualifiedType = as<IRRateQualifiedType>(getFullType()))
@@ -3345,13 +3411,13 @@ namespace Slang
void IRInst::insertBefore(IRInst* other)
{
SLANG_ASSERT(other);
- insertBefore(other, other->parent);
+ _insertAt(other->getPrevInst(), other, other->getParent());
}
- void IRInst::insertAtStart(IRParentInst* newParent)
+ void IRInst::insertAtStart(IRInst* newParent)
{
SLANG_ASSERT(newParent);
- insertBefore(newParent->children.first, newParent);
+ _insertAt(nullptr, newParent->getFirstDecorationOrChild(), newParent);
}
void IRInst::moveToStart()
@@ -3361,52 +3427,49 @@ namespace Slang
insertAtStart(p);
}
- void IRInst::insertBefore(IRInst* other, IRParentInst* newParent)
+ void IRInst::_insertAt(IRInst* inPrev, IRInst* inNext, IRInst* inParent)
{
// Make sure this instruction has been removed from any previous parent
this->removeFromParent();
- SLANG_ASSERT(other || newParent);
- if (!other) other = newParent->children.first;
- if (!newParent) newParent = other->parent;
- SLANG_ASSERT(newParent);
-
- auto nn = other;
- auto pp = other ? other->getPrevInst() : nullptr;
+ SLANG_ASSERT(inParent);
+ SLANG_ASSERT(!inPrev || (inPrev->getNextInst() == inNext) && (inPrev->getParent() == inParent));
+ SLANG_ASSERT(!inNext || (inNext->getPrevInst() == inPrev) && (inNext->getParent() == inParent));
- if( pp )
+ if( inPrev )
{
- pp->next = this;
+ inPrev->next = this;
}
else
{
- newParent->children.first = this;
+ inParent->m_decorationsAndChildren.first = this;
}
- if (nn)
+ if (inNext)
{
- nn->prev = this;
+ inNext->prev = this;
}
else
{
- newParent->children.last = this;
+ inParent->m_decorationsAndChildren.last = this;
}
- this->prev = pp;
- this->next = nn;
- this->parent = newParent;
+ this->prev = inPrev;
+ this->next = inNext;
+ this->parent = inParent;
}
void IRInst::insertAfter(IRInst* other)
{
SLANG_ASSERT(other);
- insertAfter(other, other->parent);
+
+ _insertAt(other, other->getNextInst(), other->getParent());
}
- void IRInst::insertAtEnd(IRParentInst* newParent)
+ void IRInst::insertAtEnd(IRInst* newParent)
{
SLANG_ASSERT(newParent);
- insertAfter(newParent->children.last, newParent);
+ _insertAt(newParent->getLastDecorationOrChild(), nullptr, newParent);
}
void IRInst::moveToEnd()
@@ -3416,42 +3479,6 @@ namespace Slang
insertAtEnd(p);
}
- void IRInst::insertAfter(IRInst* other, IRParentInst* newParent)
- {
- // Make sure this instruction has been removed from any previous parent
- this->removeFromParent();
-
- SLANG_ASSERT(other || newParent);
- if (!other) other = newParent->children.last;
- if (!newParent) newParent = other->parent;
- SLANG_ASSERT(newParent);
-
- auto pp = other;
- auto nn = other ? other->next : nullptr;
-
- if (pp)
- {
- pp->next = this;
- }
- else
- {
- newParent->children.first = this;
- }
-
- if (nn)
- {
- nn->prev = this;
- }
- else
- {
- newParent->children.last = this;
- }
-
- this->prev = pp;
- this->next = nn;
- this->parent = newParent;
- }
-
// Remove this instruction from its parent block,
// and then destroy it (it had better have no uses!)
void IRInst::removeFromParent()
@@ -3473,7 +3500,7 @@ namespace Slang
}
else
{
- oldParent->children.first = nn;
+ oldParent->m_decorationsAndChildren.first = nn;
}
if(nn)
@@ -3483,7 +3510,7 @@ namespace Slang
}
else
{
- oldParent->children.last = pp;
+ oldParent->m_decorationsAndChildren.last = pp;
}
prev = nullptr;
@@ -3507,23 +3534,16 @@ namespace Slang
{
removeFromParent();
removeArguments();
-
- // If this is a parent instruction then we had
- // better remove all its children as well.
- //
- if(auto parentInst = as<IRParentInst>(this))
- {
- parentInst->removeAndDeallocateAllChildren();
- }
+ removeAndDeallocateAllDecorationsAndChildren();
// Run destructor to be sure...
this->~IRInst();
}
- void IRParentInst::removeAndDeallocateAllChildren()
+ void IRInst::removeAndDeallocateAllDecorationsAndChildren()
{
IRInst* nextChild = nullptr;
- for( IRInst* child = getFirstChild(); child; child = nextChild )
+ for( IRInst* child = getFirstDecorationOrChild(); child; child = nextChild )
{
nextChild = child->getNextInst();
child->removeAndDeallocate();
@@ -4153,8 +4173,7 @@ namespace Slang
if(auto outerArrayName = systemValueInfo->outerArrayName)
{
- auto decoration = builder->addDecoration<IRGLSLOuterArrayDecoration>(globalVariable);
- decoration->outerArrayName = outerArrayName;
+ builder->addGLSLOuterArrayDecoration(globalVariable, UnownedTerminatedStringSlice(outerArrayName));
}
}
@@ -4689,13 +4708,13 @@ namespace Slang
IRInst* val,
String const& targetName)
{
- for( auto dd = val->firstDecoration; dd; dd = dd->next )
+ for(auto dd : val->getDecorations())
{
- if(dd->op != kIRDecorationOp_TargetIntrinsic)
+ if(dd->op != kIROp_TargetIntrinsicDecoration)
continue;
auto decoration = (IRTargetIntrinsicDecoration*) dd;
- if(String(decoration->targetName) == targetName)
+ if(String(decoration->getTargetName()) == targetName)
return decoration;
}
@@ -4864,7 +4883,7 @@ namespace Slang
if(!decoration)
continue;
- if(StringRepresentation::asSlice(decoration->definition) != UnownedStringSlice::fromLiteral("EmitVertex()"))
+ if(decoration->getDefinition() != UnownedStringSlice::fromLiteral("EmitVertex()"))
{
continue;
}
@@ -5340,117 +5359,40 @@ namespace Slang
}
}
- void cloneDecorations(
+ IRInst* cloneInst(
+ IRSpecContextBase* context,
+ IRBuilder* builder,
+ IRInst* originalInst,
+ IROriginalValuesForClone const& originalValues);
+
+ IRInst* cloneInst(
IRSpecContextBase* context,
- IRInst* clonedValue,
- IRInst* originalValue)
+ IRBuilder* builder,
+ IRInst* originalInst)
{
- for (auto dd = originalValue->firstDecoration; dd; dd = dd->next)
- {
- switch (dd->op)
- {
- case kIRDecorationOp_HighLevelDecl:
- {
- auto originalDecoration = (IRHighLevelDeclDecoration*)dd;
-
- context->builder->addHighLevelDeclDecoration(clonedValue, originalDecoration->decl);
- }
- break;
-
- case kIRDecorationOp_LoopControl:
- {
- auto originalDecoration = (IRLoopControlDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRLoopControlDecoration>(clonedValue);
- newDecoration->mode = originalDecoration->mode;
- }
- break;
-
- case kIRDecorationOp_TargetIntrinsic:
- {
- auto originalDecoration = (IRTargetIntrinsicDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRTargetIntrinsicDecoration>(clonedValue);
- newDecoration->targetName = originalDecoration->targetName;
- newDecoration->definition = originalDecoration->definition;
- }
- break;
-
- case kIRDecorationOp_Semantic:
- {
- auto originalDecoration = (IRSemanticDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRSemanticDecoration>(clonedValue);
- newDecoration->semanticName = originalDecoration->semanticName;
- }
- break;
-
- case kIRDecorationOp_InterpolationMode:
- {
- auto originalDecoration = (IRInterpolationModeDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRInterpolationModeDecoration>(clonedValue);
- newDecoration->mode = originalDecoration->mode;
- }
- break;
-
- case kIRDecorationOp_NameHint:
- {
- auto originalDecoration = (IRNameHintDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRNameHintDecoration>(clonedValue);
- newDecoration->name = originalDecoration->name;
- }
- break;
-
- case kIRDecorationOp_VulkanRayPayload:
- {
- context->builder->addDecoration<IRVulkanRayPayloadDecoration>(clonedValue);
- }
- break;
-
- case kIRDecorationOp_VulkanCallablePayload:
- {
- context->builder->addDecoration<IRVulkanCallablePayloadDecoration>(clonedValue);
- }
- break;
- case kIRDecorationOp_EarlyDepthStencil:
- {
- context->builder->addDecoration<IREarlyDepthStencilDecoration>(clonedValue);
- }
- break;
- case kIRDecorationOp_GloballyCoherent:
- {
- context->builder->addDecoration<IRGloballyCoherentDecoration>(clonedValue);
- }
- break;
- case kIRDecorationOp_VulkanHitAttributes:
- {
- context->builder->addDecoration<IRVulkanHitAttributesDecoration>(clonedValue);
- }
- break;
+ return cloneInst(context, builder, originalInst, originalInst);
+ }
- case kIRDecorationOp_RequireGLSLExtension:
- {
- auto originalDecoration = (IRRequireGLSLExtensionDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRRequireGLSLExtensionDecoration>(clonedValue);
- newDecoration->extensionName = originalDecoration->extensionName;
- }
- break;
+ /// Clone any decorations from `originalValue` onto `clonedValue`
+ void cloneDecorations(
+ IRSpecContextBase* context,
+ IRInst* clonedValue,
+ IRInst* originalValue)
+ {
+ // TODO: In many cases we might be able to use this as a general-purpose
+ // place to do cloning of *all* the children of an instruction, and
+ // not just its decorations. We should look to refactor this code
+ // later.
- case kIRDecorationOp_RequireGLSLVersion:
- {
- auto originalDecoration = (IRRequireGLSLVersionDecoration*)dd;
- auto newDecoration = context->builder->addDecoration<IRRequireGLSLVersionDecoration>(clonedValue);
- newDecoration->languageVersion = originalDecoration->languageVersion;
- }
- break;
+ IRBuilder builderStorage = *context->builder;
+ IRBuilder* builder = &builderStorage;
+ builder->setInsertInto(clonedValue);
- case kIRDecorationOp_ReadNone:
- {
- context->builder->addDecoration<IRReadNoneDecoration>(clonedValue);
- }
- break;
- default:
- // Don't clone any decorations we don't understand.
- break;
- }
+ SLANG_UNUSED(context);
+ for(auto originalDecoration : originalValue->getDecorations())
+ {
+ cloneInst(context, builder, originalDecoration);
}
// We will also clone the location here, just because this is a convenient bottleneck
@@ -5510,6 +5452,20 @@ namespace Slang
}
break;
+ case kIROp_StringLit:
+ {
+ IRConstant* c = (IRConstant*)originalValue;
+ return builder->getStringValue(c->getStringSlice());
+ }
+ break;
+
+ case kIROp_PtrLit:
+ {
+ IRConstant* c = (IRConstant*)originalValue;
+ return builder->getPtrValue(c->value.ptrVal);
+ }
+ break;
+
default:
{
// In the deafult case, assume that we have some sort of "hoistable"
@@ -5596,20 +5552,6 @@ namespace Slang
return cloneValue(context, originalValue);
}
- IRInst* cloneInst(
- IRSpecContextBase* context,
- IRBuilder* builder,
- IRInst* originalInst,
- IROriginalValuesForClone const& originalValues);
-
- IRInst* cloneInst(
- IRSpecContextBase* context,
- IRBuilder* builder,
- IRInst* originalInst)
- {
- return cloneInst(context, builder, originalInst, originalInst);
- }
-
void cloneGlobalValueWithCodeCommon(
IRSpecContextBase* context,
IRGlobalValueWithCode* clonedValue,
@@ -5652,8 +5594,6 @@ namespace Slang
auto mangledName = originalVar->mangledName;
clonedVar->mangledName = mangledName;
- cloneDecorations(context, clonedVar, originalVar);
-
VarLayout* layout = nullptr;
if (context->globalVarLayouts.TryGetValue(mangledName, layout))
{
@@ -5683,8 +5623,6 @@ namespace Slang
auto mangledName = originalVal->mangledName;
clonedVal->mangledName = mangledName;
- cloneDecorations(context, clonedVal, originalVal);
-
// Clone any code in the body of the constant, since this
// represents the initializer.
cloneGlobalValueWithCodeCommon(
@@ -5707,8 +5645,6 @@ namespace Slang
auto mangledName = originalVal->mangledName;
clonedVal->mangledName = mangledName;
- cloneDecorations(context, clonedVal, originalVal);
-
// Clone any code in the body of the generic, since this
// computes its result value.
cloneGlobalValueWithCodeCommon(
@@ -5732,15 +5668,13 @@ namespace Slang
auto mangledName = originalInst->mangledName;
clonedInst->mangledName = mangledName;
- cloneDecorations(context, clonedInst, originalInst);
-
// Set up an IR builder for inserting into the inst
IRBuilder builderStorage = *context->builder;
IRBuilder* builder = &builderStorage;
builder->setInsertInto(clonedInst);
// Clone any children of the instruction
- for (auto child : originalInst->getChildren())
+ for (auto child : originalInst->getDecorationsAndChildren())
{
cloneInst(context, builder, child);
}
@@ -5812,6 +5746,7 @@ namespace Slang
IRBuilder* builder = &builderStorage;
builder->setInsertInto(clonedValue);
+ cloneDecorations(context, clonedValue, originalValue);
// We will walk through the blocks of the function, and clone each of them.
//
@@ -5864,10 +5799,10 @@ namespace Slang
}
- void checkIRDuplicate(IRInst* inst, IRParentInst* moduleInst, Name* mangledName)
+ void checkIRDuplicate(IRInst* inst, IRInst* moduleInst, Name* mangledName)
{
#ifdef _DEBUG
- for (auto child : moduleInst->getChildren())
+ for (auto child : moduleInst->getDecorationsAndChildren())
{
if (child == inst)
continue;
@@ -5898,8 +5833,6 @@ namespace Slang
clonedFunc->mangledName = originalFunc->mangledName;
clonedFunc->setFullType(cloneType(context, originalFunc->getFullType()));
- cloneDecorations(context, clonedFunc, originalFunc);
-
cloneGlobalValueWithCodeCommon(
context,
clonedFunc,
@@ -6052,13 +5985,13 @@ namespace Slang
}
TargetSpecializationLevel result = TargetSpecializationLevel::notSpecialized;
- for( auto dd = val->firstDecoration; dd; dd = dd->next )
+ for(auto dd : val->getDecorations())
{
- if(dd->op != kIRDecorationOp_Target)
+ if(dd->op != kIROp_TargetDecoration)
continue;
auto decoration = (IRTargetDecoration*) dd;
- if(String(decoration->targetName) == targetName)
+ if(String(decoration->getTargetName()) == targetName)
return TargetSpecializationLevel::specializedForTarget;
result = TargetSpecializationLevel::specializedForOtherTarget;
@@ -6124,7 +6057,7 @@ namespace Slang
case kIROp_GlobalConstant:
case kIROp_Func:
case kIROp_Generic:
- return ((IRParentInst*)val)->getFirstChild() != nullptr;
+ return val->getFirstChild() != nullptr;
case kIROp_StructType:
case kIROp_GlobalVar:
@@ -6704,18 +6637,13 @@ namespace Slang
// We do *not* consider generics, or instructions nested under them.
return;
}
- else if(auto parentInst = as<IRParentInst>(inst))
+ else
{
- // For a parent instruction, we will scan through its contents,
- // since that will be where the `specialize` instructions are
-
- for(auto child : parentInst->children)
+ for(auto child : inst->getChildren())
{
addToSpecializationWorkListRec(sharedContext, child);
}
- }
- else
- {
+
// Default case: consider this instruction for specialization.
sharedContext->addToWorkList(inst);
}
@@ -6806,12 +6734,9 @@ namespace Slang
// We expect a generic to only ever contain a single block.
SLANG_ASSERT(bb == genericVal->getFirstBlock());
- for (auto ii : bb->getChildren())
+ // Iterate over the non-parameter ("ordinary") instructions.
+ for (auto ii : bb->getOrdinaryInsts())
{
- // Skip parameters, since they were handled earlier.
- if (auto param = as<IRParam>(ii))
- continue;
-
// The last block of the generic is expected to end with
// a `return` instruction for the specialized value that
// comes out of the abstraction.
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 0b75a487f..8183e038a 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -137,68 +137,93 @@ struct IRUse
void debugValidate();
};
-enum IRDecorationOp : uint16_t
-{
- kIRDecorationOp_HighLevelDecl,
- kIRDecorationOp_Layout,
- kIRDecorationOp_LoopControl,
- kIRDecorationOp_Target,
- kIRDecorationOp_TargetIntrinsic,
- kIRDecorationOp_GLSLOuterArray,
- kIRDecorationOp_Semantic,
- kIRDecorationOp_InterpolationMode,
- kIRDecorationOp_NameHint,
-
- /** The _instruction_ is transitory. Such a decoration should NEVER be found on an output instruction a module.
- Typically used mark an instruction so can be specially handled - say when creating a IRConstant literal, and the payload of
- needs to be special cased for lookup. */
- kIRDecorationOp_Transitory,
- kIRDecorationOp_VulkanRayPayload,
- kIRDecorationOp_VulkanHitAttributes,
- kIRDecorationOp_RequireGLSLVersion,
- kIRDecorationOp_RequireGLSLExtension,
- kIRDecorationOp_ReadNone,
- kIRDecorationOp_VulkanCallablePayload,
-
- kIRDecorationOp_EarlyDepthStencil,
- kIRDecorationOp_GloballyCoherent,
-
- kIRDecorationOp_CountOf
-};
+struct IRBlock;
+struct IRDecoration;
+struct IRRate;
+struct IRType;
-// represents an object allocated in an IR memory arena
-struct IRObject
+// A double-linked list of instruction
+struct IRInstListBase
{
+ IRInstListBase()
+ {}
+
+ IRInstListBase(IRInst* first, IRInst* last)
+ : first(first)
+ , last(last)
+ {}
+
+
+
+ IRInst* first = nullptr;
+ IRInst* last = nullptr;
+
+ IRInst* getFirst() { return first; }
+ IRInst* getLast() { return last; }
+
+ struct Iterator
+ {
+ IRInst* inst;
+
+ Iterator() : inst(nullptr) {}
+ Iterator(IRInst* inst) : inst(inst) {}
+
+ void operator++();
+ IRInst* operator*()
+ {
+ return inst;
+ }
+
+ bool operator!=(Iterator const& i)
+ {
+ return inst != i.inst;
+ }
+ };
+
+ Iterator begin();
+ Iterator end();
};
-// A "decoration" that gets applied to an instruction.
-// These usually don't affect semantics, but are useful
-// for preserving high-level source information.
-struct IRDecoration : public IRObject
+// Specialization of `IRInstListBase` for the case where
+// we know (or at least expect) all of the instructions
+// to be of type `T`
+template<typename T>
+struct IRInstList : IRInstListBase
{
- static IRDecoration make(IRDecorationOp opIn, IRDecoration* nextIn = nullptr)
+ IRInstList() {}
+
+ IRInstList(T* first, T* last)
+ : IRInstListBase(first, last)
+ {}
+
+ explicit IRInstList(IRInstListBase const& list)
+ : IRInstListBase(list)
+ {}
+
+ T* getFirst() { return (T*) first; }
+ T* getLast() { return (T*) last; }
+
+ struct Iterator : public IRInstListBase::Iterator
{
- IRDecoration dec;
- dec.next = nextIn;
- dec.op = opIn;
- return dec;
- }
+ Iterator() {}
+ Iterator(IRInst* inst) : IRInstListBase::Iterator(inst) {}
- // Next decoration attached to the same instruction
- IRDecoration* next;
+ T* operator*()
+ {
+ return (T*) inst;
+ }
+ };
- IRDecorationOp op;
+ Iterator begin() { return Iterator(first); }
+ Iterator end();
};
-struct IRBlock;
-struct IRParentInst;
-struct IRRate;
-struct IRType;
+
// Every value in the IR is an instruction (even things
// like literal values).
//
-struct IRInst : public IRObject
+struct IRInst
{
// The operation that this value represents
IROp op;
@@ -220,15 +245,21 @@ struct IRInst : public IRObject
// Source location information for this value, if any
SourceLoc sourceLoc;
- // The linked list of decorations attached to this value
- IRDecoration* firstDecoration = nullptr;
+ // Each instruction can have zero or more "decorations"
+ // attached to it. A decoration is a specialized kind
+ // of instruction that either attaches metadata to,
+ // or modifies the sematnics of, its parent instruction.
+ //
+ IRDecoration* getFirstDecoration();
+ IRDecoration* getLastDecoration();
+ IRInstList<IRDecoration> getDecorations();
// Look up a decoration in the list of decorations
- IRDecoration* findDecorationImpl(IRDecorationOp op);
+ IRDecoration* findDecorationImpl(IROp op);
template<typename T>
T* findDecoration()
{
- return (T*) findDecorationImpl(IRDecorationOp(T::kDecorationOp));
+ return (T*) findDecorationImpl(IROp(T::kOp));
}
// The first use of this value (start of a linked list)
@@ -236,9 +267,9 @@ struct IRInst : public IRObject
// The parent of this instruction.
- IRParentInst* parent;
+ IRInst* parent;
- IRParentInst* getParent() { return parent; }
+ IRInst* getParent() { return parent; }
// The next and previous instructions with the same parent
IRInst* next;
@@ -247,6 +278,42 @@ struct IRInst : public IRObject
IRInst* getNextInst() { return next; }
IRInst* getPrevInst() { return prev; }
+ // An instruction can have zero or more children, although
+ // only certain instruction opcodes are allowed to have
+ // children.
+ //
+ // For example, a function will have children that are
+ // its basic blocks, and the basic blocks will have children
+ // that represent parameters and ordinary executable instructions.
+ //
+ IRInst* getFirstChild();
+ IRInst* getLastChild();
+ IRInstList<IRInst> getChildren()
+ {
+ return IRInstList<IRInst>(
+ getFirstChild(),
+ getLastChild());
+ }
+
+ /// A doubly-linked list containing any decorations and then any children of this instruction.
+ ///
+ /// We store both the decorations and children of an instruction
+ /// in the same list, to conserve space in the instruction itself
+ /// (rather than storing distinct lists for decorations and children).
+ ///
+ // Note: This field is *not* being declared `private` because doing so could
+ // mess with our required memory layout, where `typeUse` below is assumed
+ // to be the last field in `IRInst` and to come right before any additional
+ // `IRUse` values that represent operands.
+ //
+ IRInstListBase m_decorationsAndChildren;
+
+ IRInst* getFirstDecorationOrChild() { return m_decorationsAndChildren.first; }
+ IRInst* getLastDecorationOrChild() { return m_decorationsAndChildren.last; }
+ IRInstListBase getDecorationsAndChildren() { return m_decorationsAndChildren; }
+
+ void removeAndDeallocateAllDecorationsAndChildren();
+
// The type of the result value of this instruction,
// or `null` to indicate that the instruction has
// no value.
@@ -289,17 +356,13 @@ struct IRInst : public IRObject
void insertAfter(IRInst* other);
// Insert as first/last child of given parent
- void insertAtStart(IRParentInst* parent);
- void insertAtEnd(IRParentInst* parent);
+ void insertAtStart(IRInst* parent);
+ void insertAtEnd(IRInst* parent);
// Move to the start/end of current parent
void moveToStart();
void moveToEnd();
- // Insert before/after the given instruction, in a specific block
- void insertBefore(IRInst* other, IRParentInst* parent);
- void insertAfter(IRInst* other, IRParentInst* parent);
-
// Remove this instruction from its parent block,
// but don't delete it, or replace uses.
void removeFromParent();
@@ -332,6 +395,16 @@ struct IRInst : public IRObject
/// If this instruction is transitively nested inside some IR module,
/// this function will return it, and will otherwise return `null`.
IRModule* getModule();
+
+ /// Insert this instruction into `inParent`, after `inPrev` and before `inNext`.
+ ///
+ /// `inParent` must be non-null
+ /// If `inPrev` is non-null it must satisfy `inPrev->getNextInst() == inNext` and `inPrev->getParent() == inParent`
+ /// If `inNext` is non-null it must satisfy `inNext->getPrevInst() == inPrev` and `inNext->getParent() == inParent`
+ ///
+ /// If both `inPrev` and `inNext` are null, then `inParent` must have no (raw) children.
+ ///
+ void _insertAt(IRInst* inPrev, IRInst* inNext, IRInst* inParent);
};
// `dynamic_cast` equivalent
@@ -351,89 +424,15 @@ T* cast(IRInst* inst, T* /* */ = nullptr)
return (T*)inst;
}
+// Now that `IRInst` is defined we can back-fill the `IRInstList<T>` members
+// that need to access it.
-// A double-linked list of instruction
-struct IRInstListBase
-{
- IRInstListBase()
- {}
-
- IRInstListBase(IRInst* first, IRInst* last)
- : first(first)
- , last(last)
- {}
-
-
-
- IRInst* first = nullptr;
- IRInst* last = nullptr;
-
- IRInst* getFirst() { return first; }
- IRInst* getLast() { return last; }
-
- struct Iterator
- {
- IRInst* inst;
-
- Iterator() : inst(nullptr) {}
- Iterator(IRInst* inst) : inst(inst) {}
-
- void operator++()
- {
- if (inst)
- {
- inst = inst->next;
- }
- }
-
- IRInst* operator*()
- {
- return inst;
- }
-
- bool operator!=(Iterator const& i)
- {
- return inst != i.inst;
- }
- };
-
- Iterator begin() { return Iterator(first); }
- Iterator end() { return Iterator(last ? last->next : nullptr); }
-};
-
-// Specialization of `IRInstListBase` for the case where
-// we know (or at least expect) all of the instructions
-// to be of type `T`
template<typename T>
-struct IRInstList : IRInstListBase
+typename IRInstList<T>::Iterator IRInstList<T>::end()
{
- IRInstList() {}
-
- IRInstList(T* first, T* last)
- : IRInstListBase(first, last)
- {}
-
- explicit IRInstList(IRInstListBase const& list)
- : IRInstListBase(list)
- {}
-
- T* getFirst() { return (T*) first; }
- T* getLast() { return (T*) last; }
-
- struct Iterator : public IRInstListBase::Iterator
- {
- Iterator() {}
- Iterator(IRInst* inst) : IRInstListBase::Iterator(inst) {}
-
- T* operator*()
- {
- return (T*) inst;
- }
- };
+ return Iterator(last ? last->next : nullptr);
+}
- Iterator begin() { return Iterator(first); }
- Iterator end() { return Iterator(last ? last->next : nullptr); }
-};
// Types
@@ -494,16 +493,17 @@ struct IRConstant : IRInst
{
IRIntegerValue intVal; ///< Used for integrals and boolean
IRFloatingPointValue floatVal;
+ void* ptrVal;
/// Either of these types could be set with kIROp_StringLit.
- /// Which is used is currently determined with IRDecorationOp - if a kDecorationOp_Transitory is set, then the transitory StringVal is used, else stringVal
+ /// Which is used is currently determined with decorations - if a kIROp_TransitoryDecoration is set, then the transitory StringVal is used, else stringVal
// which relies on chars being held after the struct).
StringValue stringVal;
StringSliceValue transitoryStringVal;
};
/// Returns a string slice (or empty string if not appropriate)
- UnownedStringSlice getStringSlice() const;
+ UnownedStringSlice getStringSlice();
/// True if constants are equal
bool equal(IRConstant& rhs);
@@ -542,6 +542,13 @@ struct IRStringLit : IRConstant
IR_LEAF_ISA(StringLit);
};
+struct IRPtrLit : IRConstant
+{
+ IR_LEAF_ISA(PtrLit);
+
+ void* getValue() { return value.ptrVal; }
+};
+
// A instruction that ends a basic block (usually because of control flow)
struct IRTerminatorInst : IRInst
{
@@ -564,49 +571,36 @@ struct IRParam : IRInst
IR_LEAF_ISA(Param)
};
-// A "parent" instruction is one that contains other instructions
-// as its children. The most common case of a parent instruction
-// is a basic block, but there are other cases (e.g., a function
-// is in turn a parent for basic blocks).
-struct IRParentInst : IRInst
-{
- // The instructions stored under this parent
- IRInstListBase children;
-
- IRInst* getFirstChild() { return children.first; }
- IRInst* getLastChild() { return children.last; }
- IRInstListBase getChildren() { return children; }
-
- void removeAndDeallocateAllChildren();
-
- IR_PARENT_ISA(ParentInst)
-};
-
// A basic block is a parent instruction that adds the constraint
// that all the children need to be "ordinary" instructions (so
// no function declarations, or nested blocks). We also expect
// that the previous/next instruction are always a basic block.
//
-struct IRBlock : IRParentInst
+struct IRBlock : IRInst
{
// Linked list of the instructions contained in this block
//
- IRInstListBase getChildren() { return children; }
- IRInst* getFirstInst() { return children.first; }
- IRInst* getLastInst() { return children.last; }
+ IRInst* getFirstInst() { return getChildren().first; }
+ IRInst* getLastInst() { return getChildren().last; }
// In a valid program, every basic block should end with
// a "terminator" instruction.
//
// This function will return the terminator, if it exists,
// or `null` if there is none.
- IRTerminatorInst* getTerminator() { return as<IRTerminatorInst>(getLastInst()); }
+ IRTerminatorInst* getTerminator() { return as<IRTerminatorInst>(getLastDecorationOrChild()); }
// We expect that the siblings of a basic block will
// always be other basic blocks (we don't allow
// mixing of blocks and other instructions in the
// same parent).
- IRBlock* getPrevBlock() { return cast<IRBlock>(getPrevInst()); }
+ //
+ // The exception to this is that decorations on the function
+ // that contains a block could appear before the first block,
+ // so we need to be careful to do a dynamic cast (`as`) in
+ // the `getPrevBlock` case, but don't need to worry about
+ // it for `getNextBlock`.
+ IRBlock* getPrevBlock() { return as<IRBlock>(getPrevInst()); }
IRBlock* getNextBlock() { return cast<IRBlock>(getNextInst()); }
// The parameters of a block are represented by `IRParam`
@@ -922,7 +916,7 @@ struct IRFuncType : IRType
// A "global value" is an instruction that might have
// linkage, so that it can be declared in one module
// and then resolved to a definition in another module.
-struct IRGlobalValue : IRParentInst
+struct IRGlobalValue : IRInst
{
// The mangled name, for a symbol that should have linkage,
// or which might have multiple declarations.
@@ -1064,7 +1058,7 @@ IRInst* getResolvedInstForDecorations(IRInst* inst);
// The IR module itself is represented as an instruction, which
// serves at the root of the tree of all instructions in the module.
-struct IRModuleInst : IRParentInst
+struct IRModuleInst : IRInst
{
// Pointer back to the non-instruction object that represents
// the module, so that we can get back to it in algorithms
@@ -1125,18 +1119,6 @@ IRInst* createEmptyInstWithSize(
IRModule* module,
IROp op,
size_t totalSizeInBytes);
-
-IRDecoration* createEmptyDecoration(
- IRModule* module,
- IRDecorationOp op,
- size_t sizeInBytes);
-
-template <typename T>
-T* createEmptyDecoration(IRModule* module)
-{
- return static_cast<T*>(createEmptyDecoration(module, IRDecorationOp(T::kDecorationOp), sizeof(T)));
-}
-
}
diff --git a/source/slang/legalize-types.cpp b/source/slang/legalize-types.cpp
index 1f0fe93cb..15d7a4621 100644
--- a/source/slang/legalize-types.cpp
+++ b/source/slang/legalize-types.cpp
@@ -355,7 +355,7 @@ struct TupleTypeBuilder
if(auto nameHintDecoration = originalStructType->findDecoration<IRNameHintDecoration>())
{
- builder->addDecoration<IRNameHintDecoration>(ordinaryStructType)->name = nameHintDecoration->name;
+ builder->addNameHintDecoration(ordinaryStructType, nameHintDecoration->getNameOperand());
}
// The new struct type will appear right after the original in the IR,
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index 09f463ab6..8af6292e6 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -1238,39 +1238,39 @@ void addVarDecorations(
{
if(mod.As<HLSLNoInterpolationModifier>())
{
- builder->addDecoration<IRInterpolationModeDecoration>(inst)->mode = IRInterpolationMode::NoInterpolation;
+ builder->addInterpolationModeDecoration(inst, IRInterpolationMode::NoInterpolation);
}
else if(mod.As<HLSLNoPerspectiveModifier>())
{
- builder->addDecoration<IRInterpolationModeDecoration>(inst)->mode = IRInterpolationMode::NoPerspective;
+ builder->addInterpolationModeDecoration(inst, IRInterpolationMode::NoPerspective);
}
else if(mod.As<HLSLLinearModifier>())
{
- builder->addDecoration<IRInterpolationModeDecoration>(inst)->mode = IRInterpolationMode::Linear;
+ builder->addInterpolationModeDecoration(inst, IRInterpolationMode::Linear);
}
else if(mod.As<HLSLSampleModifier>())
{
- builder->addDecoration<IRInterpolationModeDecoration>(inst)->mode = IRInterpolationMode::Sample;
+ builder->addInterpolationModeDecoration(inst, IRInterpolationMode::Sample);
}
else if(mod.As<HLSLCentroidModifier>())
{
- builder->addDecoration<IRInterpolationModeDecoration>(inst)->mode = IRInterpolationMode::Centroid;
+ builder->addInterpolationModeDecoration(inst, IRInterpolationMode::Centroid);
}
else if(mod.As<VulkanRayPayloadAttribute>())
{
- builder->addDecoration<IRVulkanRayPayloadDecoration>(inst);
+ builder->addSimpleDecoration<IRVulkanRayPayloadDecoration>(inst);
}
else if(mod.As<VulkanCallablePayloadAttribute>())
{
- builder->addDecoration<IRVulkanCallablePayloadDecoration>(inst);
+ builder->addSimpleDecoration<IRVulkanCallablePayloadDecoration>(inst);
}
else if(mod.As<VulkanHitAttributesAttribute>())
{
- builder->addDecoration<IRVulkanHitAttributesDecoration>(inst);
+ builder->addSimpleDecoration<IRVulkanHitAttributesDecoration>(inst);
}
else if(mod.As<GloballyCoherentModifier>())
{
- builder->addDecoration<IRGloballyCoherentDecoration>(inst);
+ builder->addSimpleDecoration<IRGloballyCoherentDecoration>(inst);
}
// TODO: what are other modifiers we need to propagate through?
@@ -1294,7 +1294,7 @@ void maybeSetRate(
}
}
-static Name* getNameForNameHint(
+static String getNameForNameHint(
IRGenContext* context,
Decl* decl)
{
@@ -1311,9 +1311,9 @@ static Name* getNameForNameHint(
// There is no point in trying to provide a name hint for something with no name,
// or with an empty name
if(!leafName)
- return nullptr;
+ return String();
if(leafName->text.Length() == 0)
- return nullptr;
+ return String();
if(auto varDecl = dynamic_cast<VarDeclBase*>(decl))
@@ -1326,7 +1326,7 @@ static Name* getNameForNameHint(
// TODO: consider whether global/static variables should
// follow different rules.
//
- return leafName;
+ return leafName->text;
}
// For other cases of declaration, we want to consider
@@ -1338,9 +1338,9 @@ static Name* getNameForNameHint(
parentDecl = genericParentDecl->ParentDecl;
auto parentName = getNameForNameHint(context, parentDecl);
- if(!parentName)
+ if(parentName.Length() == 0)
{
- return leafName;
+ return leafName->text;
}
// TODO: at some point we will start giving `ModuleDecl`s names,
@@ -1351,11 +1351,11 @@ static Name* getNameForNameHint(
// combining the name of the parent and the leaf declaration.
StringBuilder sb;
- sb.append(parentName->text);
+ sb.append(parentName);
sb.append(".");
sb.append(leafName->text);
- return context->getSession()->getNameObj(sb.ProduceString());
+ return sb.ProduceString();
}
/// Try to add an appropriate name hint to the instruction,
@@ -1365,10 +1365,10 @@ static void addNameHint(
IRInst* inst,
Decl* decl)
{
- Name* name = getNameForNameHint(context, decl);
- if(!name)
+ String name = getNameForNameHint(context, decl);
+ if(name.Length() == 0)
return;
- context->irBuilder->addDecoration<IRNameHintDecoration>(inst)->name = name;
+ context->irBuilder->addNameHintDecoration(inst, name.getUnownedSlice());
}
/// Add a name hint based on a fixed string.
@@ -1377,8 +1377,7 @@ static void addNameHint(
IRInst* inst,
char const* text)
{
- Name* name = context->getSession()->getNameObj(text);
- context->irBuilder->addDecoration<IRNameHintDecoration>(inst)->name = name;
+ context->irBuilder->addNameHintDecoration(inst, UnownedTerminatedStringSlice(text));
}
LoweredValInfo createVar(
@@ -2410,8 +2409,7 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
{
if( stmt->FindModifier<UnrollAttribute>() )
{
- auto decoration = getBuilder()->addDecoration<IRLoopControlDecoration>(inst);
- decoration->mode = kIRLoopControl_Unroll;
+ getBuilder()->addLoopControlDecoration(inst, kIRLoopControl_Unroll);
}
// TODO: handle other cases here
}
@@ -4313,8 +4311,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
if (auto semanticModifier = fieldDecl->FindModifier<HLSLSimpleSemantic>())
{
- auto semanticDecoration = builder->addDecoration<IRSemanticDecoration>(irFieldKey);
- semanticDecoration->semanticName = semanticModifier->name.getName();
+ builder->addSemanticDecoration(irFieldKey, semanticModifier->name.getName()->text.getUnownedSlice());
}
// We allow a field to be marked as a target intrinsic,
@@ -4779,18 +4776,18 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
for (auto targetMod : decl->GetModifiersOfType<TargetIntrinsicModifier>())
{
- auto decoration = builder->addDecoration<IRTargetIntrinsicDecoration>(irInst);
- decoration->targetName = builder->addStringToFree(targetMod->targetToken.Content);
-
+ String definition;
auto definitionToken = targetMod->definitionToken;
if (definitionToken.type == TokenType::StringLiteral)
{
- decoration->definition = builder->addStringToFree(getStringLiteralTokenValue(definitionToken));
+ definition = getStringLiteralTokenValue(definitionToken);
}
else
{
- decoration->definition = builder->addStringToFree(definitionToken.Content);
+ definition = definitionToken.Content;
}
+
+ builder->addTargetIntrinsicDecoration(irInst, targetMod->targetToken.Content.getUnownedSlice(), definition.getUnownedSlice());
}
}
@@ -5076,12 +5073,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// Convert the patch constant function into IRInst
IRInst* irPatchConstantFunc = getSimpleVal(context, ensureDecl(subContext, patchConstantFunc));
- // Emit the note patch constant func
- subContext->irBuilder->emitIntrinsicInst(
- nullptr,
- kIROp_NotePatchConstantFunc,
- 1,
- &irPatchConstantFunc);
+ // Attach a decoration so that our IR function references
+ // the patch constant function.
+ //
+ subContext->irBuilder->addPatchConstantFuncDecoration(
+ irFunc,
+ irPatchConstantFunc);
}
}
@@ -5122,8 +5119,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// a specialized definition of the particular function for the given
// target, and we need to reflect that at the IR level.
- auto decoration = getBuilder()->addDecoration<IRTargetDecoration>(irFunc);
- decoration->targetName = getBuilder()->addStringToFree(targetMod->targetToken.Content);
+ getBuilder()->addTargetDecoration(irFunc, targetMod->targetToken.Content.getUnownedSlice());
}
// If this declaration was marked as having a target-specific lowering
@@ -5138,23 +5134,21 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
//
for(auto extensionMod : decl->GetModifiersOfType<RequiredGLSLExtensionModifier>())
{
- auto decoration = getBuilder()->addDecoration<IRRequireGLSLExtensionDecoration>(irFunc);
- decoration->extensionName = getBuilder()->addStringToFree(extensionMod->extensionNameToken.Content);
+ getBuilder()->addRequireGLSLExtensionDecoration(irFunc, extensionMod->extensionNameToken.Content.getUnownedSlice());
}
for(auto versionMod : decl->GetModifiersOfType<RequiredGLSLVersionModifier>())
{
- auto decoration = getBuilder()->addDecoration<IRRequireGLSLVersionDecoration>(irFunc);
- decoration->languageVersion = Int(getIntegerLiteralValue(versionMod->versionNumberToken));
+ getBuilder()->addRequireGLSLVersionDecoration(irFunc, Int(getIntegerLiteralValue(versionMod->versionNumberToken)));
}
if(decl->FindModifier<ReadNoneAttribute>())
{
- getBuilder()->addDecoration<IRReadNoneDecoration>(irFunc);
+ getBuilder()->addSimpleDecoration<IRReadNoneDecoration>(irFunc);
}
if (decl->FindModifier<EarlyDepthStencilAttribute>())
{
- getBuilder()->addDecoration<IREarlyDepthStencilDecoration>(irFunc);
+ getBuilder()->addSimpleDecoration<IREarlyDepthStencilDecoration>(irFunc);
}
// For convenience, ensure that any additional global
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 247064f3a..0045b8f84 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -93,31 +93,6 @@
</Expand>
</Synthetic>
<Item Name="[parent]">parent</Item>
- <Synthetic Name="[children]" Condition="(op &gt;= Slang::kIROp_FirstParentInst) &amp;&amp; (op &lt;= Slang::kIROp_LastParentInst)">
- <Expand>
- <LinkedListItems>
- <HeadPointer>(*((Slang::IRParentInst*) this)).children.first</HeadPointer>
- <NextPointer>next</NextPointer>
- <ValueNode>this</ValueNode>
- </LinkedListItems>
- </Expand>
- </Synthetic>
- <Synthetic Name="[uses]">
- <Expand>
- <LinkedListItems>
- <HeadPointer>firstUse</HeadPointer>
- <NextPointer>nextUse</NextPointer>
- <ValueNode>user</ValueNode>
- </LinkedListItems>
- </Expand>
- </Synthetic>
- </Expand>
- </Type>
- <Type Name="Slang::IRParentInst">
- <DisplayString>{{{op}}}</DisplayString>
- <Expand>
- <Item Name="[op]">op</Item>
- <Item Name="[type]">typeUse.usedValue</Item>
<Synthetic Name="[children]">
<Expand>
<LinkedListItems>
@@ -127,7 +102,6 @@
</LinkedListItems>
</Expand>
</Synthetic>
- <Item Name="[parent]">parent</Item>
<Synthetic Name="[uses]">
<Expand>
<LinkedListItems>
@@ -137,7 +111,7 @@
</LinkedListItems>
</Expand>
</Synthetic>
- </Expand>
+ </Expand>
</Type>
<Type Name="Slang::IRGlobalValue">
<DisplayString>{{{op} "{mangledName}"}}</DisplayString>