summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-12-11 15:17:55 -0800
committerGitHub <noreply@github.com>2018-12-11 15:17:55 -0800
commit62d3e387774255be4d507cca045ac97dabac9970 (patch)
treebe43084855adaad3a843eaf9b46c845b17465a63 /source
parent565200f0a9200cdc9a345c51096e50a745aabc1d (diff)
Decorations are instructions (#748)
* Make a test case use IR serialization * Make all IR instructions usable as parents This makes it so that every `IRInst` has the list of children that used to be on `IRParentInst` and eliminates `IRParentInst`. Most places in the code were only checking against `IRParentInst` so that they could know whether there were child instructions to iterate over. This change bloats the size of every instruction by two pointers, but we hope to be able to eliminate that overhead with a better encoding later. * Change IR decorations to be instructions. The main change here is that `IRDecoration` now inherits from `IRInst`, and `IRInst` now has a single linked list that holds both decorations *and* children. At each point where code used to loop over `getChildren()` on an `IRInst`, I checked whether it made sense to leave the operation as processing just the children, or if it should process both decorations and children. The thorniest bit was making sure the logic for inserting an instruction into a parent is correct. For the most part, once IR code is built all insertions are explicitly before/after another instruction, so the ordering can't get messed up. The sticking point is any code that does an explicit `insertAtStart` or `insertAtEnd`, but I surveyed those to make sure they are correct in context, and I also made all insertions bottleneck through one routine that does a better job of asserting the preconditions than what was there before. We may still want a "smart" insertion function at some point so that if somebody does `someDecoration->insertAtEnd(someInst)` the decoration intelligently goes to the end of the decoration list, and not the entire decorations-and-children list. All of the existing decoration types were refactored to provide accessors for their operands, rather than directly exposing fields. In most cases the operands are required to be `IRConstant` nodes of fixed types. Not all of these types need to be kept around in the new approach, but they were left in so that as much existing code as possible can be kept working. The `IRBuilder` was extended with factory functions to make the various decoration types and attach them. All the fields in concrete decorations that were using `StringRepresentation` or `Name` pointers are now using IR-level string operands which provide their value as an `UnownedStringSlice`, so logic that was working with those decoration values needed to be updated here and there. I also needed to add the logic to clone string-literal values to the IR cloning pass, since they are now being used in almost every piece of code. A new type of constant IR instruction for literal pointers was added, to handle the cases where an IR decoration needs an operand that is a raw AST-level pointer. These are even being serialized, although we obviously should not rely on them to round-trip through serialization in the future. Ideally, a follow-on change should add a cleanup pass where we remove any decorations from a module that shouldn't be allowed in the serialized code. The biggest overall cleanup is in the serialization logic, where a lot of code just disappears because it can process the raw "decorations and children" list as the logical children of an IR instruction. The only special cases left are literals (which seem like they will always need special-casing) and global values (because they have a mangled name, which we plan to move into a decoration). One other example of a simplification made possible by this change: the `IRNotePatchConstantFunc` instruction was implemented as an instruction only because it couldn't be encoded as a decoration at the time (it needed to have an operand that referenced an IR function). The IR dumping logic was also updated (which meant a change to the `ir/string-literal` test) to try to make it print out all decorations a bit more systematically now that they are encoded like other instructions. The formatting isn't quite perfect, but it is good enough to be able to read what is going on. I didn't include updates to the validation logic to ensure that decorations are being added in ways that follow the invariants, but that would be a nice thing to add next. * fixup: 64-bit issues * fixup: forward declaration issues
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>