summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/bytecode.cpp101
-rw-r--r--source/slang/emit.cpp190
-rw-r--r--source/slang/ir-constexpr.cpp63
-rw-r--r--source/slang/ir-inst-defs.h54
-rw-r--r--source/slang/ir-insts.h174
-rw-r--r--source/slang/ir-legalize-types.cpp152
-rw-r--r--source/slang/ir-ssa.cpp58
-rw-r--r--source/slang/ir.cpp1152
-rw-r--r--source/slang/ir.h463
-rw-r--r--source/slang/legalize-types.h6
-rw-r--r--source/slang/lower-to-ir.cpp144
-rw-r--r--source/slang/slang.natvis122
-rw-r--r--source/slang/syntax.h1
13 files changed, 1292 insertions, 1388 deletions
diff --git a/source/slang/bytecode.cpp b/source/slang/bytecode.cpp
index 6b6e4170e..8a062faaa 100644
--- a/source/slang/bytecode.cpp
+++ b/source/slang/bytecode.cpp
@@ -103,7 +103,7 @@ struct SharedBytecodeGenerationContext
// Map from an IR value to a global entity
// that encodes it:
- Dictionary<IRValue*, BCConst> mapValueToGlobal;
+ Dictionary<IRInst*, BCConst> mapValueToGlobal;
// Types that have been emitted
List<BytecodeGenerationPtr<BCType>> bcTypes;
@@ -111,7 +111,7 @@ struct SharedBytecodeGenerationContext
// Compile-time constant values that need
// to be emitted...
- List<IRValue*> constants;
+ List<IRInst*> constants;
};
struct BytecodeGenerationContext
@@ -131,7 +131,7 @@ struct BytecodeGenerationContext
// Map an instruction to its ID for use local
// to the current context
- Dictionary<IRValue*, Int> mapInstToLocalID;
+ Dictionary<IRInst*, Int> mapInstToLocalID;
};
template<typename T>
@@ -239,7 +239,7 @@ void encodeSInt(
BCConst getGlobalValue(
BytecodeGenerationContext* context,
- IRValue* value)
+ IRInst* value)
{
{
BCConst bcConst;
@@ -281,7 +281,7 @@ BCConst getGlobalValue(
Int getLocalID(
BytecodeGenerationContext* context,
- IRValue* value)
+ IRInst* value)
{
Int localID = 0;
if( context->mapInstToLocalID.TryGetValue(value, localID) )
@@ -300,7 +300,7 @@ Int getLocalID(
void encodeOperand(
BytecodeGenerationContext* context,
- IRValue* operand)
+ IRInst* operand)
{
auto id = getLocalID(context, operand);
encodeSInt(context, id);
@@ -317,7 +317,7 @@ void encodeOperand(
encodeUInt(context, getTypeID(context, type));
}
-bool opHasResult(IRValue* inst)
+bool opHasResult(IRInst* inst)
{
auto type = inst->getDataType();
if (!type) return false;
@@ -350,13 +350,13 @@ void generateBytecodeForInst(
// encode the necessary extra info:
//
- auto argCount = inst->getArgCount();
+ auto operandCount = inst->getOperandCount();
encodeUInt(context, inst->op);
encodeOperand(context, inst->getDataType());
- encodeUInt(context, argCount);
- for( UInt aa = 0; aa < argCount; ++aa )
+ encodeUInt(context, operandCount);
+ for( UInt aa = 0; aa < operandCount; ++aa )
{
- encodeOperand(context, inst->getArg(aa));
+ encodeOperand(context, inst->getOperand(aa));
}
if (!opHasResult(inst))
@@ -446,9 +446,9 @@ void generateBytecodeForInst(
// We need to encode the type being stored, to make
// our lives easier.
- encodeOperand(context, inst->getArg(1)->getDataType());
- encodeOperand(context, inst->getArg(0));
- encodeOperand(context, inst->getArg(1));
+ encodeOperand(context, inst->getOperand(1)->getDataType());
+ encodeOperand(context, inst->getOperand(0));
+ encodeOperand(context, inst->getOperand(1));
}
break;
@@ -456,7 +456,7 @@ void generateBytecodeForInst(
{
encodeUInt(context, inst->op);
encodeOperand(context, inst->getDataType());
- encodeOperand(context, inst->getArg(0));
+ encodeOperand(context, inst->getOperand(0));
encodeOperand(context, inst);
}
break;
@@ -609,7 +609,7 @@ uint32_t getTypeID(
uint32_t getTypeIDForGlobalSymbol(
BytecodeGenerationContext* context,
- IRValue* inst)
+ IRInst* inst)
{
auto type = inst->getDataType();
if(!type)
@@ -721,15 +721,6 @@ BytecodeGenerationPtr<BCSymbol> generateBytecodeSymbolForInst(
UInt blockID = blockCounter++;
UInt paramCount = 0;
- for( auto pp = bb->getFirstParam(); pp; pp = pp->getNextParam() )
- {
- // A parameter always uses a register.
- regCounter++;
- //
- // We also want to keep a count of the parameters themselves.
- paramCount++;
- }
-
for( auto ii = bb->getFirstInst(); ii; ii = ii->getNextInst() )
{
switch( ii->op )
@@ -743,6 +734,14 @@ BytecodeGenerationPtr<BCSymbol> generateBytecodeSymbolForInst(
}
break;
+ case kIROp_Param:
+ // A parameter always uses a register.
+ regCounter++;
+ //
+ // We also want to keep a count of the parameters themselves.
+ paramCount++;
+ break;
+
case kIROp_Var:
// A `var` (`alloca`) node needs two registers:
// one to hold the actual storage, and another
@@ -772,35 +771,21 @@ BytecodeGenerationPtr<BCSymbol> generateBytecodeSymbolForInst(
{
UInt blockID = blockCounter++;
- // Loop over just the parameters first, to ensure they
- // are always the first N registers of a block.
- //
- // This means the parameters of the function itself
- // are always the first N registers in the overall list.
+ // Loop over the instruction in the block, to allocate registers
+ // for them. The parameters of a block will always be the first
+ // N instructions in the block, so they will always get the
+ // first N registers in that block. Similarly, the entry block
+ // is always the first block, so that the parameters of the function
+ // will always be the first N registers.
//
bcBlocks[blockID].params = bcRegs + regCounter;
- for( auto pp = bb->getFirstParam(); pp; pp = pp->getNextParam() )
- {
- Int localID = regCounter++;
- subContext->mapInstToLocalID.Add(pp, localID);
-
- bcRegs[localID].op = pp->op;
-#if 0
- bcRegs[localID].name = tryGenerateNameForSymbol(context, pp);
-#endif
- bcRegs[localID].previousVarIndexPlusOne = (uint32_t)localID;
- bcRegs[localID].typeID = getTypeIDForGlobalSymbol(context, pp);
- }
-
- // Now loop over the non-parameter instructions and
- // allocate actual register locations to them.
for( auto ii = bb->getFirstInst(); ii; ii = ii->getNextInst() )
{
switch(ii->op)
{
default:
- // For an ordinary instruction with a result,
- // allocate it here.
+ // For a parameter, or an ordinary instruction with
+ // a result, allocate it here.
if( opHasResult(ii) )
{
Int localID = regCounter++;
@@ -816,12 +801,12 @@ BytecodeGenerationPtr<BCSymbol> generateBytecodeSymbolForInst(
break;
case kIROp_Var:
+ // As handled in the earlier loop, we are
+ // allocating *two* locations for each `var`
+ // instruction. The first of these will be
+ // the actual pointer value, while the second
+ // will be the storage for the variable value.
{
- // As handled in the earlier loop, we are
- // allocating *two* locations for each `var`
- // instruction. The first of these will be
- // the actual pointer value, while the second
- // will be the storage for the variable value.
Int localID = regCounter;
regCounter += 2;
@@ -967,8 +952,12 @@ BytecodeGenerationPtr<BCModule> generateBytecodeForModule(
// for the module, where the registers represent the
// values being computed at the global scope.
UInt symbolCount = 0;
- for( auto gv = irModule->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : irModule->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
Int globalID = Int(symbolCount++);
// Ensure that local code inside functions can see these symbols
@@ -986,8 +975,12 @@ BytecodeGenerationPtr<BCModule> generateBytecodeForModule(
bcModule->symbolCount = (uint32_t)symbolCount;
bcModule->symbols = bcSymbols;
- for( auto gv = irModule->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : irModule->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
UInt symbolIndex = *context->mapInstToLocalID.TryGetValue(gv);
auto bcSymbol = generateBytecodeSymbolForInst(context, gv);
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index c91fa1b90..189c1c4bd 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -117,7 +117,7 @@ struct SharedEmitContext
ExtensionUsageTracker extensionUsageTracker;
UInt uniqueIDCounter = 1;
- Dictionary<IRValue*, UInt> mapIRValueToID;
+ Dictionary<IRInst*, UInt> mapIRValueToID;
Dictionary<Decl*, UInt> mapDeclToID;
HashSet<String> irDeclsVisited;
@@ -4481,7 +4481,7 @@ emitDeclImpl(decl, nullptr);
// IR-level emit logc
- UInt getID(IRValue* value)
+ UInt getID(IRInst* value)
{
auto& mapIRValueToID = context->shared->mapIRValueToID;
@@ -4548,7 +4548,7 @@ emitDeclImpl(decl, nullptr);
}
String getIRName(
- IRValue* inst)
+ IRInst* inst)
{
switch(inst->op)
{
@@ -4903,7 +4903,7 @@ emitDeclImpl(decl, nullptr);
bool shouldFoldIRInstIntoUseSites(
EmitContext* ctx,
- IRValue* inst,
+ IRInst* inst,
IREmitMode mode)
{
// Certain opcodes should always be folded in
@@ -4984,7 +4984,7 @@ emitDeclImpl(decl, nullptr);
bool isDerefBaseImplicit(
EmitContext* /*context*/,
- IRValue* inst)
+ IRInst* inst)
{
auto type = inst->getDataType();
@@ -5003,7 +5003,7 @@ emitDeclImpl(decl, nullptr);
void emitIROperand(
EmitContext* ctx,
- IRValue* inst,
+ IRInst* inst,
IREmitMode mode)
{
if( shouldFoldIRInstIntoUseSites(ctx, inst, mode) )
@@ -5028,8 +5028,8 @@ emitDeclImpl(decl, nullptr);
IRInst* inst,
IREmitMode mode)
{
- UInt argCount = inst->argCount;
- IRUse* args = inst->getArgs();
+ UInt argCount = inst->getOperandCount();
+ IRUse* args = inst->getOperands();
emit("(");
for(UInt aa = 0; aa < argCount; ++aa)
@@ -5085,7 +5085,7 @@ emitDeclImpl(decl, nullptr);
void emitIRRateQualifiers(
EmitContext* ctx,
- IRValue* value)
+ IRInst* value)
{
emitIRRateQualifiers(ctx, value->getRate());
}
@@ -5371,8 +5371,8 @@ emitDeclImpl(decl, nullptr);
IRTargetIntrinsicDecoration* targetIntrinsic,
IREmitMode mode)
{
- IRUse* args = inst->getArgs();
- UInt argCount = inst->getArgCount();
+ IRUse* args = inst->getOperands();
+ UInt argCount = inst->getOperandCount();
// First operand was the function to be called
args++;
@@ -5578,7 +5578,7 @@ emitDeclImpl(decl, nullptr);
// For a call with N arguments, the instruction will
// have N+1 operands. We will start consuming operands
// starting at the index 1.
- UInt operandCount = inst->getArgCount();
+ UInt operandCount = inst->getOperandCount();
UInt argCount = operandCount - 1;
UInt operandIndex = 1;
@@ -5619,15 +5619,15 @@ emitDeclImpl(decl, nullptr);
{
// The user is invoking a built-in subscript operator
emit("(");
- emitIROperand(ctx, inst->getArg(operandIndex++), mode);
+ emitIROperand(ctx, inst->getOperand(operandIndex++), mode);
emit(")[");
- emitIROperand(ctx, inst->getArg(operandIndex++), mode);
+ emitIROperand(ctx, inst->getOperand(operandIndex++), mode);
emit("]");
if(operandIndex < operandCount)
{
emit(" = ");
- emitIROperand(ctx, inst->getArg(operandIndex++), mode);
+ emitIROperand(ctx, inst->getOperand(operandIndex++), mode);
}
return;
}
@@ -5643,7 +5643,7 @@ emitDeclImpl(decl, nullptr);
{
// Looks like a member function call
emit("(");
- emitIROperand(ctx, inst->getArg(operandIndex), mode);
+ emitIROperand(ctx, inst->getOperand(operandIndex), mode);
emit(").");
operandIndex++;
@@ -5655,7 +5655,7 @@ emitDeclImpl(decl, nullptr);
for(; operandIndex < operandCount; ++operandIndex )
{
if(!first) emit(", ");
- emitIROperand(ctx, inst->getArg(operandIndex), mode);
+ emitIROperand(ctx, inst->getOperand(operandIndex), mode);
first = false;
}
emit(")");
@@ -5668,7 +5668,7 @@ emitDeclImpl(decl, nullptr);
{
// We want to detect any call to an intrinsic operation,
// that we can emit it directly without mangling, etc.
- auto funcValue = inst->getArg(0);
+ auto funcValue = inst->getOperand(0);
if(auto irFunc = asTargetIntrinsic(ctx, funcValue))
{
emitIntrinsicCallExpr(ctx, inst, irFunc, mode);
@@ -5677,11 +5677,11 @@ emitDeclImpl(decl, nullptr);
{
emitIROperand(ctx, funcValue, mode);
emit("(");
- UInt argCount = inst->getArgCount();
+ UInt argCount = inst->getOperandCount();
for( UInt aa = 1; aa < argCount; ++aa )
{
if(aa != 1) emit(", ");
- emitIROperand(ctx, inst->getArg(aa), mode);
+ emitIROperand(ctx, inst->getOperand(aa), mode);
}
emit(")");
}
@@ -5689,14 +5689,12 @@ emitDeclImpl(decl, nullptr);
void emitIRInstExpr(
EmitContext* ctx,
- IRValue* value,
+ IRInst* inst,
IREmitMode mode)
{
- IRInst* inst = (IRInst*) value;
-
advanceToSourceLocation(inst->sourceLoc);
- switch(value->op)
+ switch(inst->op)
{
case kIROp_IntLit:
case kIROp_FloatLit:
@@ -5708,13 +5706,13 @@ emitDeclImpl(decl, nullptr);
case kIROp_makeVector:
case kIROp_makeMatrix:
// Simple constructor call
- if( inst->getArgCount() == 1 && getTarget(ctx) == CodeGenTarget::HLSL)
+ if( inst->getOperandCount() == 1 && getTarget(ctx) == CodeGenTarget::HLSL)
{
// Need to emit as cast for HLSL
emit("(");
emitIRType(ctx, inst->getDataType());
emit(") ");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
else
{
@@ -5736,7 +5734,7 @@ emitDeclImpl(decl, nullptr);
emitIRType(ctx, inst->getDataType());
}
emit("(");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(")");
break;
@@ -5771,11 +5769,11 @@ emitDeclImpl(decl, nullptr);
}
break;
-#define CASE(OPCODE, OP) \
- case OPCODE: \
- emitIROperand(ctx, inst->getArg(0), mode); \
- emit(" " #OP " "); \
- emitIROperand(ctx, inst->getArg(1), mode); \
+#define CASE(OPCODE, OP) \
+ case OPCODE: \
+ emitIROperand(ctx, inst->getOperand(0), mode); \
+ emit(" " #OP " "); \
+ emitIROperand(ctx, inst->getOperand(1), mode); \
break
CASE(kIROp_Add, +);
@@ -5813,18 +5811,18 @@ emitDeclImpl(decl, nullptr);
&& inst->type->As<MatrixExpressionType>())
{
emit("matrixCompMult(");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(")");
}
else
{
// Default handling is to just rely on infix
// `operator*`.
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(" * ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
}
break;
@@ -5838,55 +5836,55 @@ emitDeclImpl(decl, nullptr);
{
emit("~");
}
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
break;
case kIROp_Neg:
{
emit("-");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
break;
case kIROp_BitNot:
{
emit("~");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
break;
case kIROp_Sample:
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(".Sample(");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(2), mode);
+ emitIROperand(ctx, inst->getOperand(2), mode);
emit(")");
break;
case kIROp_SampleGrad:
// argument 0 is the instruction's type
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(".SampleGrad(");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(2), mode);
+ emitIROperand(ctx, inst->getOperand(2), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(3), mode);
+ emitIROperand(ctx, inst->getOperand(3), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(4), mode);
+ emitIROperand(ctx, inst->getOperand(4), mode);
emit(")");
break;
case kIROp_Load:
// TODO: this logic will really only work for a simple variable reference...
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
break;
case kIROp_Store:
// TODO: this logic will really only work for a simple variable reference...
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(" = ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
break;
case kIROp_Call:
@@ -5897,18 +5895,18 @@ emitDeclImpl(decl, nullptr);
case kIROp_BufferLoad:
case kIROp_BufferElementRef:
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit("[");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit("]");
break;
case kIROp_BufferStore:
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit("[");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit("] = ");
- emitIROperand(ctx, inst->getArg(2), mode);
+ emitIROperand(ctx, inst->getOperand(2), mode);
break;
case kIROp_GroupMemoryBarrierWithGroupSync:
@@ -5917,9 +5915,9 @@ emitDeclImpl(decl, nullptr);
case kIROp_getElement:
case kIROp_getElementPtr:
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit("[");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit("]");
break;
@@ -5936,16 +5934,16 @@ emitDeclImpl(decl, nullptr);
// because the notion of what is a "row" vs. a "column"
// is reversed between HLSL/Slang and GLSL.
//
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(" * ");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
else
{
emit("mul(");
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(", ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(")");
}
break;
@@ -5958,7 +5956,7 @@ emitDeclImpl(decl, nullptr);
UInt elementCount = ii->getElementCount();
for (UInt ee = 0; ee < elementCount; ++ee)
{
- IRValue* irElementIndex = ii->getElementIndex(ee);
+ IRInst* irElementIndex = ii->getElementIndex(ee);
assert(irElementIndex->op == kIROp_IntLit);
IRConstant* irConst = (IRConstant*)irElementIndex;
@@ -5973,17 +5971,17 @@ emitDeclImpl(decl, nullptr);
case kIROp_specialize:
{
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
}
break;
case kIROp_Select:
{
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(" ? ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(" : ");
- emitIROperand(ctx, inst->getArg(2), mode);
+ emitIROperand(ctx, inst->getOperand(2), mode);
}
break;
@@ -5999,11 +5997,11 @@ emitDeclImpl(decl, nullptr);
// of the expression.
emit("{ ");
- UInt argCount = inst->getArgCount();
+ UInt argCount = inst->getOperandCount();
for (UInt aa = 0; aa < argCount; ++aa)
{
if (aa != 0) emit(", ");
- emitIROperand(ctx, inst->getArg(aa), mode);
+ emitIROperand(ctx, inst->getOperand(aa), mode);
}
emit(" }");
}
@@ -6081,14 +6079,14 @@ emitDeclImpl(decl, nullptr);
{
auto ii = (IRSwizzleSet*)inst;
emitIRInstResultDecl(ctx, inst);
- emitIROperand(ctx, inst->getArg(0), mode);
+ emitIROperand(ctx, inst->getOperand(0), mode);
emit(";\n");
emitIROperand(ctx, inst, mode);
emit(".");
UInt elementCount = ii->getElementCount();
for (UInt ee = 0; ee < elementCount; ++ee)
{
- IRValue* irElementIndex = ii->getElementIndex(ee);
+ IRInst* irElementIndex = ii->getElementIndex(ee);
assert(irElementIndex->op == kIROp_IntLit);
IRConstant* irConst = (IRConstant*)irElementIndex;
@@ -6099,7 +6097,7 @@ emitDeclImpl(decl, nullptr);
emit(kComponents[elementIndex]);
}
emit(" = ");
- emitIROperand(ctx, inst->getArg(1), mode);
+ emitIROperand(ctx, inst->getOperand(1), mode);
emit(";\n");
}
break;
@@ -6108,7 +6106,7 @@ emitDeclImpl(decl, nullptr);
void emitIRSemantics(
EmitContext* ctx,
- IRValue* inst)
+ IRInst* inst)
{
// Don't emit semantics if we aren't translating down to HLSL
switch (ctx->shared->target)
@@ -6150,7 +6148,7 @@ emitDeclImpl(decl, nullptr);
VarLayout* getVarLayout(
EmitContext* /*context*/,
- IRValue* var)
+ IRInst* var)
{
auto decoration = var->findDecoration<IRLayoutDecoration>();
if (!decoration)
@@ -6161,7 +6159,7 @@ emitDeclImpl(decl, nullptr);
void emitIRLayoutSemantics(
EmitContext* ctx,
- IRValue* inst,
+ IRInst* inst,
char const* uniformSemanticSpelling = "register")
{
auto layout = getVarLayout(ctx, inst);
@@ -6193,7 +6191,7 @@ emitDeclImpl(decl, nullptr);
break;
}
- IRValue* arg = args[argIndex].get();
+ IRInst* arg = args[argIndex].get();
emitIROperand(ctx, pp, IREmitMode::Default);
emit(" = ");
@@ -6294,7 +6292,7 @@ emitDeclImpl(decl, nullptr);
// Start by emitting the non-terminator instructions in the block.
auto terminator = block->getLastInst();
- assert(isTerminatorInst(terminator));
+ assert(as<IRTerminatorInst>(terminator));
for (auto inst = block->getFirstInst(); inst != terminator; inst = inst->getNextInst())
{
emitIRInst(ctx, inst, IREmitMode::Default);
@@ -6367,12 +6365,12 @@ emitDeclImpl(decl, nullptr);
auto targetBlock = t->getTargetBlock();
auto breakBlock = t->getBreakBlock();
- UInt argCount = t->getArgCount();
+ UInt argCount = t->getOperandCount();
static const UInt kFixedArgCount = 3;
emitPhiVarAssignments(
ctx,
argCount - kFixedArgCount,
- t->getArgs() + kFixedArgCount,
+ t->getOperands() + kFixedArgCount,
targetBlock);
// Set up entries on our label stack for break/continue
@@ -6514,12 +6512,12 @@ emitDeclImpl(decl, nullptr);
auto t = (IRUnconditionalBranch*)terminator;
auto targetBlock = t->getTargetBlock();
- UInt argCount = t->getArgCount();
+ UInt argCount = t->getOperandCount();
static const UInt kFixedArgCount = 1;
emitPhiVarAssignments(
ctx,
argCount - kFixedArgCount,
- t->getArgs() + kFixedArgCount,
+ t->getOperands() + kFixedArgCount,
targetBlock);
block = t->getTargetBlock();
@@ -7107,7 +7105,7 @@ emitDeclImpl(decl, nullptr);
// if it does.
IRFunc* asTargetIntrinsic(
EmitContext* ctxt,
- IRValue* value)
+ IRInst* value)
{
if(!value)
return nullptr;
@@ -7704,7 +7702,7 @@ emitDeclImpl(decl, nullptr);
auto varType = allocatedType->getValueType();
String initFuncName;
- if (varDecl->firstBlock)
+ if (varDecl->getFirstBlock())
{
// A global variable with code means it has an initializer
// associated with it. Eventually we'd like to emit that
@@ -7715,7 +7713,7 @@ emitDeclImpl(decl, nullptr);
initFuncName.append("_init");
emitIRType(ctx, varType, initFuncName);
Emit("()\n{\n");
- emitIRStmtsForBlocks(ctx, varDecl->firstBlock, nullptr, nullptr);
+ emitIRStmtsForBlocks(ctx, varDecl->getFirstBlock(), nullptr, nullptr);
Emit("}\n");
}
@@ -7788,7 +7786,7 @@ emitDeclImpl(decl, nullptr);
emitIRLayoutSemantics(ctx, varDecl);
- if (varDecl->firstBlock)
+ if (varDecl->getFirstBlock())
{
Emit(" = ");
emit(initFuncName);
@@ -7827,7 +7825,7 @@ emitDeclImpl(decl, nullptr);
emit("static const ");
emitIRType(ctx, valType, getIRName(valDecl));
- if (valDecl->firstBlock)
+ if (valDecl->getFirstBlock())
{
// There is an initializer (which we expect for
// any global constant...).
@@ -7845,10 +7843,8 @@ emitDeclImpl(decl, nullptr);
void emitIRGlobalInst(
EmitContext* ctx,
- IRGlobalValue* inst)
+ IRInst* inst)
{
- // TODO: need to be able to `switch` on the IR opcode here,
- // so there is some work to be done.
switch(inst->op)
{
case kIROp_Func:
@@ -7995,7 +7991,7 @@ emitDeclImpl(decl, nullptr);
void emitIRUsedTypesForValue(
EmitContext* ctx,
- IRValue* value)
+ IRInst* value)
{
if(!value) return;
switch( value->op )
@@ -8044,9 +8040,9 @@ emitDeclImpl(decl, nullptr);
EmitContext* ctx,
IRModule* module)
{
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
- emitIRUsedTypesForValue(ctx, gv);
+ emitIRUsedTypesForValue(ctx, ii);
}
}
@@ -8059,20 +8055,18 @@ emitDeclImpl(decl, nullptr);
// Before we emit code, we need to forward-declare
// all of our functions so that we don't have to
// sort them by dependencies.
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
- if(gv->op != kIROp_Func)
+ if(ii->op != kIROp_Func)
continue;
- auto func = (IRFunc*) gv;
+ auto func = (IRFunc*) ii;
emitIRFuncDecl(ctx, func);
}
-
-
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
- emitIRGlobalInst(ctx, gv);
+ emitIRGlobalInst(ctx, ii);
}
}
diff --git a/source/slang/ir-constexpr.cpp b/source/slang/ir-constexpr.cpp
index f5738c036..8463851ac 100644
--- a/source/slang/ir-constexpr.cpp
+++ b/source/slang/ir-constexpr.cpp
@@ -8,6 +8,9 @@ namespace Slang {
struct PropagateConstExprContext
{
+ IRModule* module;
+ IRModule* getModule() { return module; }
+
DiagnosticSink* sink;
SharedIRBuilder sharedBuilder;
@@ -35,7 +38,7 @@ bool isConstExpr(Type* type)
return false;
}
-bool isConstExpr(IRValue* value)
+bool isConstExpr(IRInst* value)
{
// Certain IR value ops are implicitly `constexpr`
//
@@ -84,7 +87,7 @@ bool opCanBeConstExpr(IROp op)
}
}
-bool opCanBeConstExpr(IRValue* value)
+bool opCanBeConstExpr(IRInst* value)
{
// TODO: realistically need to special-case `call`
// operations here, so that we check whether the
@@ -96,7 +99,7 @@ bool opCanBeConstExpr(IRValue* value)
void markConstExpr(
PropagateConstExprContext* context,
- IRValue* value)
+ IRInst* value)
{
Slang::markConstExpr(context->getSession(), value);
}
@@ -126,10 +129,10 @@ bool propagateConstExprForward(
// Are all arguments `constexpr`?
bool allArgsConstExpr = true;
- UInt argCount = ii->getArgCount();
+ UInt argCount = ii->getOperandCount();
for( UInt aa = 0; aa < argCount; ++aa )
{
- auto arg = ii->getArg(aa);
+ auto arg = ii->getOperand(aa);
if( !isConstExpr(arg) )
{
@@ -166,7 +169,7 @@ void maybeAddToWorkList(
bool maybeMarkConstExpr(
PropagateConstExprContext* context,
- IRValue* value)
+ IRInst* value)
{
if(isConstExpr(value))
return false;
@@ -204,7 +207,7 @@ bool maybeMarkConstExpr(
case kIROp_Call:
{
auto inst = (IRCall*) user;
- auto caller = inst->getParentBlock()->getParent();
+ auto caller = as<IRGlobalValueWithCode>(inst->getParent()->getParent());
maybeAddToWorkList(context, caller);
}
break;
@@ -226,7 +229,7 @@ bool propagateConstExprBackward(
IRGlobalValueWithCode* code)
{
SharedIRBuilder sharedBuilder;
- sharedBuilder.module = code->parentModule;
+ sharedBuilder.module = context->getModule();
sharedBuilder.session = sharedBuilder.module->session;
IRBuilder builder;
@@ -253,10 +256,10 @@ bool propagateConstExprBackward(
if( isConstExpr(ii) )
{
// If this instruction is `constexpr`, then its operands should be too.
- UInt argCount = ii->getArgCount();
+ UInt argCount = ii->getOperandCount();
for( UInt aa = 0; aa < argCount; ++aa )
{
- auto arg = ii->getArg(aa);
+ auto arg = ii->getOperand(aa);
if(isConstExpr(arg))
continue;
@@ -277,15 +280,15 @@ bool propagateConstExprBackward(
// constexpr from the parameters back to the arguments.
auto callInst = (IRCall*) ii;
- UInt operandCount = callInst->getArgCount();
+ UInt operandCount = callInst->getOperandCount();
UInt firstCallArg = 1;
UInt callArgCount = operandCount - firstCallArg;
- auto callee = callInst->getArg(0);
+ auto callee = callInst->getOperand(0);
while( callee->op == kIROp_specialize )
{
- callee = ((IRSpecialize*) callee)->getArg(0);
+ callee = ((IRSpecialize*) callee)->getOperand(0);
}
if( callee->op == kIROp_Func )
{
@@ -297,7 +300,7 @@ bool propagateConstExprBackward(
// If the callee has a definition, then we can read `constexpr`
// information off of the parameters of its first IR block.
- if( auto calleeFirstBlock = calleeFunc->firstBlock )
+ if( auto calleeFirstBlock = calleeFunc->getFirstBlock() )
{
UInt paramCounter = 0;
for( auto pp = calleeFirstBlock->getFirstParam(); pp; pp = pp->getNextParam() )
@@ -305,7 +308,7 @@ bool propagateConstExprBackward(
UInt paramIndex = paramCounter++;
auto param = pp;
- auto arg = callInst->getArg(firstCallArg + paramIndex);
+ auto arg = callInst->getOperand(firstCallArg + paramIndex);
if( isConstExpr(param) )
{
@@ -326,7 +329,7 @@ bool propagateConstExprBackward(
for( UInt pp = 0; pp < paramCount; ++pp )
{
auto paramType = calleeType->getParamType(pp);
- auto arg = callInst->getArg(firstCallArg + pp);
+ auto arg = callInst->getOperand(firstCallArg + pp);
if( isConstExpr(paramType) )
{
if( maybeMarkConstExpr(context, arg) )
@@ -336,14 +339,6 @@ bool propagateConstExprBackward(
}
}
}
-
- // TODO: this currently only works if the callee has a definition,
- // because that is the only case where will generate IR values for
- // its parameter list. Otherwise we'd need to pull this information
- // from the function *type* for builtins.
- if(!calleeFunc->firstBlock)
- continue;
-
}
}
}
@@ -370,9 +365,9 @@ bool propagateConstExprBackward(
continue;
UInt operandIndex = paramIndex + 1;
- SLANG_RELEASE_ASSERT(operandIndex < terminator->getArgCount());
+ SLANG_RELEASE_ASSERT(operandIndex < terminator->getOperandCount());
- auto operand = terminator->getArg(operandIndex);
+ auto operand = terminator->getOperand(operandIndex);
if( maybeMarkConstExpr(context, operand) )
{
changedThisIteration = true;
@@ -406,10 +401,10 @@ void validateConstExpr(
// For an instruction that must be `constexpr`, we need
// to ensure that its argumenst are all `constexpr`
- UInt argCount = ii->getArgCount();
+ UInt argCount = ii->getOperandCount();
for( UInt aa = 0; aa < argCount; ++aa )
{
- auto arg = ii->getArg(aa);
+ auto arg = ii->getOperand(aa);
if( !isConstExpr(arg) )
{
@@ -432,6 +427,7 @@ void propagateConstExpr(
auto session = module->session;
PropagateConstExprContext context;
+ context.module = module;
context.sink = sink;
context.sharedBuilder.module = module;
context.sharedBuilder.session = session;
@@ -460,8 +456,11 @@ void propagateConstExpr(
// We will build an initial work list with all of the global values in it.
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for( auto ii : module->getGlobalInsts() )
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
maybeAddToWorkList(&context, gv);
}
@@ -508,9 +507,9 @@ void propagateConstExpr(
// we find that they are *required* to be `constexpr`, but *cannot*
// be, for some reason.
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
- switch( gv->op )
+ switch( ii->op )
{
default:
break;
@@ -519,7 +518,7 @@ void propagateConstExpr(
case kIROp_global_var:
case kIROp_global_constant:
{
- IRGlobalValueWithCode* code = (IRGlobalValueWithCode*) gv;
+ IRGlobalValueWithCode* code = (IRGlobalValueWithCode*) ii;
validateConstExpr(&context, code);
}
break;
diff --git a/source/slang/ir-inst-defs.h b/source/slang/ir-inst-defs.h
index 9d6330eae..cac3c086e 100644
--- a/source/slang/ir-inst-defs.h
+++ b/source/slang/ir-inst-defs.h
@@ -4,6 +4,10 @@
#error Must #define `INST` before including `ir-inst-defs.h`
#endif
+#ifndef INST_RANGE
+#define INST_RANGE(BASE, FIRST, LAST) /* empty */
+#endif
+
#ifndef PSEUDO_INST
#define PSEUDO_INST(ID) /* empty */
#endif
@@ -112,13 +116,22 @@ INST(makeStruct, makeStruct, 0, 0)
INST(Call, call, 1, 0)
INST(Module, module, 0, PARENT)
-INST(Func, func, 0, PARENT)
+
INST(Block, block, 0, PARENT)
-INST(global_var, global_var, 0, 0)
-INST(global_constant, global_constant, 0, 0)
+/*IRGlobalValue*/
+
+ /*IRGlobalValueWithCode*/
+ INST(Func, func, 0, PARENT)
+ INST(global_var, global_var, 0, 0)
+ INST(global_constant, global_constant, 0, 0)
+ INST_RANGE(GlobalValueWithCode, Func, global_constant)
+
+ INST(witness_table, witness_table, 0, 0)
+
+ INST_RANGE(GlobalValue, Func, witness_table)
+
-INST(witness_table, witness_table, 0, 0)
INST(witness_table_entry, witness_table_entry, 2, 0)
INST(Param, param, 0, 0)
@@ -180,26 +193,30 @@ INST(swizzle, swizzle, 1, 0)
INST(swizzleSet, swizzleSet, 2, 0)
-INST(ReturnVal, return_val, 1, 0)
-INST(ReturnVoid, return_void, 1, 0)
+/* IRTerminatorInst */
+
+ INST(ReturnVal, return_val, 1, 0)
+ INST(ReturnVoid, return_void, 1, 0)
+
+ // unconditionalBranch <target>
+ INST(unconditionalBranch, unconditionalBranch, 1, 0)
-// unconditionalBranch <target>
-INST(unconditionalBranch, unconditionalBranch, 1, 0)
+ // loop <target> <breakLabel> <continueLabel>
+ INST(loop, loop, 3, 0)
-// loop <target> <breakLabel> <continueLabel>
-INST(loop, loop, 3, 0)
+ // conditionalBranch <condition> <trueBlock> <falseBlock>
+ INST(conditionalBranch, conditionalBranch, 3, 0)
-// conditionalBranch <condition> <trueBlock> <falseBlock>
-INST(conditionalBranch, conditionalBranch, 3, 0)
+ // ifElse <condition> <trueBlock> <falseBlock> <mergeBlock>
+ INST(ifElse, ifElse, 4, 0)
-// ifElse <condition> <trueBlock> <falseBlock> <mergeBlock>
-INST(ifElse, ifElse, 4, 0)
+ // switch <val> <break> <default> <caseVal1> <caseBlock1> ...
+ INST(switch, switch, 3, 0)
-// switch <val> <break> <default> <caseVal1> <caseBlock1> ...
-INST(switch, switch, 3, 0)
+ INST(discard, discard, 0, 0)
+ INST(unreachable, unreachable, 0, 0)
-INST(discard, discard, 0, 0)
-INST(unreachable, unreachable, 0, 0)
+INST_RANGE(TerminatorInst, ReturnVal, unreachable)
INST(Add, add, 2, 0)
INST(Sub, sub, 2, 0)
@@ -306,5 +323,6 @@ PSEUDO_INST(Or)
#undef PSEUDO_INST
#undef PARENT
+#undef INST_RANGE
#undef INST
diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h
index f41e8a506..a3fd97351 100644
--- a/source/slang/ir-insts.h
+++ b/source/slang/ir-insts.h
@@ -85,12 +85,12 @@ struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration
// An IR node to represent a reference to an AST-level
// declaration.
-struct IRDeclRef : IRValue
+struct IRDeclRef : IRInst
{
DeclRef<Decl> declRef;
virtual void dispose() override
{
- IRValue::dispose();
+ IRInst::dispose();
declRef = decltype(declRef)();
}
};
@@ -144,8 +144,8 @@ struct IRFieldExtract : IRInst
IRUse base;
IRUse field;
- IRValue* getBase() { return base.get(); }
- IRValue* getField() { return field.get(); }
+ IRInst* getBase() { return base.get(); }
+ IRInst* getField() { return field.get(); }
};
struct IRFieldAddress : IRInst
@@ -153,8 +153,8 @@ struct IRFieldAddress : IRInst
IRUse base;
IRUse field;
- IRValue* getBase() { return base.get(); }
- IRValue* getField() { return field.get(); }
+ IRInst* getBase() { return base.get(); }
+ IRInst* getField() { return field.get(); }
};
// Terminators
@@ -166,7 +166,7 @@ struct IRReturnVal : IRReturn
{
IRUse val;
- IRValue* getVal() { return val.get(); }
+ IRInst* getVal() { return val.get(); }
};
struct IRReturnVoid : IRReturn
@@ -221,7 +221,7 @@ struct IRConditionalBranch : IRTerminatorInst
IRUse trueBlock;
IRUse falseBlock;
- IRValue* getCondition() { return condition.get(); }
+ IRInst* getCondition() { return condition.get(); }
IRBlock* getTrueBlock() { return (IRBlock*)trueBlock.get(); }
IRBlock* getFalseBlock() { return (IRBlock*)falseBlock.get(); }
};
@@ -260,29 +260,29 @@ struct IRSwitch : IRTerminatorInst
IRUse breakLabel;
IRUse defaultLabel;
- IRValue* getCondition() { return condition.get(); }
+ IRInst* getCondition() { return condition.get(); }
IRBlock* getBreakLabel() { return (IRBlock*) breakLabel.get(); }
IRBlock* getDefaultLabel() { return (IRBlock*) defaultLabel.get(); }
// remaining args are: caseVal, caseLabel, ...
- UInt getCaseCount() { return (getArgCount() - 3) / 2; }
- IRValue* getCaseValue(UInt index) { return getArg(3 + index*2 + 0); }
- IRBlock* getCaseLabel(UInt index) { return (IRBlock*) getArg(3 + index*2 + 1); }
+ UInt getCaseCount() { return (getOperandCount() - 3) / 2; }
+ IRInst* getCaseValue(UInt index) { return getOperand(3 + index*2 + 0); }
+ IRBlock* getCaseLabel(UInt index) { return (IRBlock*) getOperand(3 + index*2 + 1); }
};
struct IRSwizzle : IRReturn
{
IRUse base;
- IRValue* getBase() { return base.get(); }
+ IRInst* getBase() { return base.get(); }
UInt getElementCount()
{
- return getArgCount() - 1;
+ return getOperandCount() - 1;
}
- IRValue* getElementIndex(UInt index)
+ IRInst* getElementIndex(UInt index)
{
- return getArg(index + 1);
+ return getOperand(index + 1);
}
};
@@ -291,15 +291,15 @@ struct IRSwizzleSet : IRReturn
IRUse base;
IRUse source;
- IRValue* getBase() { return base.get(); }
- IRValue* getSource() { return source.get(); }
+ IRInst* getBase() { return base.get(); }
+ IRInst* getSource() { return source.get(); }
UInt getElementCount()
{
- return getArgCount() - 2;
+ return getOperandCount() - 2;
}
- IRValue* getElementIndex(UInt index)
+ IRInst* getElementIndex(UInt index)
{
- return getArg(index + 2);
+ return getOperand(index + 2);
}
};
@@ -309,8 +309,10 @@ struct IRVar : IRInst
{
PtrType* getDataType()
{
- return (PtrType*) ((IRValue*) this)->getDataType();
+ return (PtrType*) IRInst::getDataType();
}
+
+ static bool isaImpl(IROp op) { return op == kIROp_Var; }
};
/// @brief A global variable.
@@ -323,7 +325,7 @@ struct IRGlobalVar : IRGlobalValueWithCode
{
PtrType* getDataType()
{
- return (PtrType*) ((IRValue*) this)->getDataType();
+ return (PtrType*) IRInst::getDataType();
}
};
@@ -337,7 +339,7 @@ struct IRGlobalConstant : IRGlobalValueWithCode
};
// An entry in a witness table (see below)
-struct IRWitnessTableEntry : IRUser
+struct IRWitnessTableEntry : IRInst
{
// The AST-level requirement
IRUse requirementKey;
@@ -353,9 +355,14 @@ struct IRWitnessTableEntry : IRUser
// to the IR values that satisfy those requirements.
struct IRWitnessTable : IRGlobalValue
{
+ IRInstList<IRWitnessTableEntry> getEntries()
+ {
+ return IRInstList<IRWitnessTableEntry>(getChildren());
+ }
+
RefPtr<GenericDecl> genericDecl;
DeclRef<Decl> subTypeDeclRef, supTypeDeclRef;
- IRValueList<IRWitnessTableEntry> entries;
+
virtual void dispose() override
{
IRGlobalValue::dispose();
@@ -436,76 +443,75 @@ struct IRBuilder
IRBuilderSourceLocRAII* sourceLocInfo = nullptr;
- void addInst(IRBlock* block, IRInst* inst);
void addInst(IRInst* inst);
- IRValue* getBoolValue(bool value);
- IRValue* getIntValue(IRType* type, IRIntegerValue value);
- IRValue* getFloatValue(IRType* type, IRFloatingPointValue value);
+ IRInst* getBoolValue(bool value);
+ IRInst* getIntValue(IRType* type, IRIntegerValue value);
+ IRInst* getFloatValue(IRType* type, IRFloatingPointValue value);
- IRValue* getDeclRefVal(
+ IRInst* getDeclRefVal(
DeclRefBase const& declRef);
- IRValue* getTypeVal(IRType* type); // create an IR value that represents a type
- IRValue* emitSpecializeInst(
+ IRInst* getTypeVal(IRType* type); // create an IR value that represents a type
+ IRInst* emitSpecializeInst(
IRType* type,
- IRValue* genericVal,
- IRValue* specDeclRef);
+ IRInst* genericVal,
+ IRInst* specDeclRef);
- IRValue* emitSpecializeInst(
+ IRInst* emitSpecializeInst(
IRType* type,
- IRValue* genericVal,
+ IRInst* genericVal,
DeclRef<Decl> specDeclRef);
- IRValue* emitLookupInterfaceMethodInst(
+ IRInst* emitLookupInterfaceMethodInst(
IRType* type,
- IRValue* witnessTableVal,
- IRValue* interfaceMethodVal);
+ IRInst* witnessTableVal,
+ IRInst* interfaceMethodVal);
- IRValue* emitLookupInterfaceMethodInst(
+ IRInst* emitLookupInterfaceMethodInst(
IRType* type,
DeclRef<Decl> witnessTableDeclRef,
DeclRef<Decl> interfaceMethodDeclRef);
- IRValue* emitLookupInterfaceMethodInst(
+ IRInst* emitLookupInterfaceMethodInst(
IRType* type,
- IRValue* witnessTableVal,
+ IRInst* witnessTableVal,
DeclRef<Decl> interfaceMethodDeclRef);
- IRValue* emitFindWitnessTable(
+ IRInst* emitFindWitnessTable(
DeclRef<Decl> baseTypeDeclRef,
IRType* interfaceType);
IRInst* emitCallInst(
IRType* type,
- IRValue* func,
+ IRInst* func,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRInst* emitIntrinsicInst(
IRType* type,
IROp op,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRInst* emitConstructorInst(
IRType* type,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRInst* emitMakeVector(
IRType* type,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRInst* emitMakeArray(
IRType* type,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRInst* emitMakeStruct(
IRType* type,
UInt argCount,
- IRValue* const* args);
+ IRInst* const* args);
IRUndefined* emitUndefined(IRType* type);
@@ -521,8 +527,8 @@ struct IRBuilder
IRWitnessTable* createWitnessTable();
IRWitnessTableEntry* createWitnessTableEntry(
IRWitnessTable* witnessTable,
- IRValue* requirementKey,
- IRValue* satisfyingVal);
+ IRInst* requirementKey,
+ IRInst* satisfyingVal);
IRWitnessTable* lookupWitnessTable(Name* mangledName);
void registerWitnessTable(IRWitnessTable* table);
IRBlock* createBlock();
@@ -537,60 +543,60 @@ struct IRBuilder
IRType* type);
IRInst* emitLoad(
- IRValue* ptr);
+ IRInst* ptr);
IRInst* emitStore(
- IRValue* dstPtr,
- IRValue* srcVal);
+ IRInst* dstPtr,
+ IRInst* srcVal);
IRInst* emitFieldExtract(
IRType* type,
- IRValue* base,
- IRValue* field);
+ IRInst* base,
+ IRInst* field);
IRInst* emitFieldAddress(
IRType* type,
- IRValue* basePtr,
- IRValue* field);
+ IRInst* basePtr,
+ IRInst* field);
IRInst* emitElementExtract(
IRType* type,
- IRValue* base,
- IRValue* index);
+ IRInst* base,
+ IRInst* index);
IRInst* emitElementAddress(
IRType* type,
- IRValue* basePtr,
- IRValue* index);
+ IRInst* basePtr,
+ IRInst* index);
IRInst* emitSwizzle(
IRType* type,
- IRValue* base,
+ IRInst* base,
UInt elementCount,
- IRValue* const* elementIndices);
+ IRInst* const* elementIndices);
IRInst* emitSwizzle(
IRType* type,
- IRValue* base,
+ IRInst* base,
UInt elementCount,
UInt const* elementIndices);
IRInst* emitSwizzleSet(
IRType* type,
- IRValue* base,
- IRValue* source,
+ IRInst* base,
+ IRInst* source,
UInt elementCount,
- IRValue* const* elementIndices);
+ IRInst* const* elementIndices);
IRInst* emitSwizzleSet(
IRType* type,
- IRValue* base,
- IRValue* source,
+ IRInst* base,
+ IRInst* source,
UInt elementCount,
UInt const* elementIndices);
IRInst* emitReturn(
- IRValue* val);
+ IRInst* val);
IRInst* emitReturn();
@@ -613,35 +619,35 @@ struct IRBuilder
IRBlock* continueBlock);
IRInst* emitBranch(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* falseBlock);
IRInst* emitIf(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* afterBlock);
IRInst* emitIfElse(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* falseBlock,
IRBlock* afterBlock);
IRInst* emitLoopTest(
- IRValue* val,
+ IRInst* val,
IRBlock* bodyBlock,
IRBlock* breakBlock);
IRInst* emitSwitch(
- IRValue* val,
+ IRInst* val,
IRBlock* breakLabel,
IRBlock* defaultLabel,
UInt caseArgCount,
- IRValue* const* caseArgs);
+ IRInst* const* caseArgs);
template<typename T>
- T* addDecoration(IRValue* value, IRDecorationOp op)
+ T* addDecoration(IRInst* value, IRDecorationOp op)
{
assert(getModule());
auto decorationSize = sizeof(T);
@@ -657,13 +663,13 @@ struct IRBuilder
}
template<typename T>
- T* addDecoration(IRValue* value)
+ T* addDecoration(IRInst* value)
{
return addDecoration<T>(value, IRDecorationOp(T::kDecorationOp));
}
- IRHighLevelDeclDecoration* addHighLevelDeclDecoration(IRValue* value, Decl* decl);
- IRLayoutDecoration* addLayoutDecoration(IRValue* value, Layout* layout);
+ IRHighLevelDeclDecoration* addHighLevelDeclDecoration(IRInst* value, Decl* decl);
+ IRLayoutDecoration* addLayoutDecoration(IRInst* value, Layout* layout);
};
// Helper to establish the source location that will be used
@@ -737,8 +743,8 @@ void specializeGenerics(
//
void markConstExpr(
- Session* session,
- IRValue* irValue);
+ Session* session,
+ IRInst* irValue);
//
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index 3a0edbb60..4570ecf81 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -83,22 +83,23 @@ struct IRTypeLegalizationContext
TypeLegalizationContext* typeLegalizationContext;
// When inserting new globals, put them before this one.
- IRGlobalValue* insertBeforeGlobal = nullptr;
+ IRInst* insertBeforeGlobal = nullptr;
// When inserting new parameters, put them before this one.
IRParam* insertBeforeParam = nullptr;
- Dictionary<IRValue*, LegalVal> mapValToLegalVal;
+ Dictionary<IRInst*, LegalVal> mapValToLegalVal;
IRVar* insertBeforeLocalVar = nullptr;
- // store local var instructions that have been replaced here, so we can free them
+
+ // store instructions that have been replaced here, so we can free them
// when legalization has done
- List<IRInst*> oldLocalVars;
+ List<IRInst*> replacedInstructions;
};
static void registerLegalizedValue(
IRTypeLegalizationContext* context,
- IRValue* irValue,
+ IRInst* irValue,
LegalVal const& legalVal)
{
context->mapValToLegalVal.Add(irValue, legalVal);
@@ -165,7 +166,7 @@ static RefPtr<Type> legalizeSimpleType(
// and turn it into the equivalent legalized value.
static LegalVal legalizeOperand(
IRTypeLegalizationContext* context,
- IRValue* irValue)
+ IRInst* irValue)
{
LegalVal legalVal;
if (context->mapValToLegalVal.TryGetValue(irValue, legalVal))
@@ -178,7 +179,7 @@ static LegalVal legalizeOperand(
}
static void getArgumentValues(
- List<IRValue*> & instArgs,
+ List<IRInst*> & instArgs,
LegalVal val)
{
switch (val.flavor)
@@ -226,9 +227,9 @@ static LegalVal legalizeCall(
auto retType = legalizeType(context, callInst->type);
SLANG_ASSERT(retType.flavor == LegalType::Flavor::simple);
- List<IRValue*> instArgs;
- for (auto i = 1u; i < callInst->argCount; i++)
- getArgumentValues(instArgs, legalizeOperand(context, callInst->getArg(i)));
+ List<IRInst*> instArgs;
+ for (auto i = 1u; i < callInst->getOperandCount(); i++)
+ getArgumentValues(instArgs, legalizeOperand(context, callInst->getOperand(i)));
return LegalVal::simple(context->builder->emitCallInst(
callInst->type,
@@ -479,7 +480,7 @@ static LegalVal legalizeGetElementPtr(
IRTypeLegalizationContext* context,
LegalType type,
LegalVal legalPtrOperand,
- IRValue* indexOperand)
+ IRInst* indexOperand)
{
auto builder = context->builder;
@@ -613,7 +614,7 @@ static LegalVal legalizeInst(
}
}
-RefPtr<VarLayout> findVarLayout(IRValue* value)
+RefPtr<VarLayout> findVarLayout(IRInst* value)
{
if (auto layoutDecoration = value->findDecoration<IRLayoutDecoration>())
return layoutDecoration->layout.As<VarLayout>();
@@ -667,27 +668,66 @@ static LegalVal legalizeLocalVar(
// Remove the old local var.
irLocalVar->removeFromParent();
// add old local var to list
- context->oldLocalVars.Add(irLocalVar);
+ context->replacedInstructions.Add(irLocalVar);
return newVal;
}
break;
}
}
+static LegalVal legalizeParam(
+ IRTypeLegalizationContext* context,
+ IRParam* originalParam)
+{
+ auto legalParamType = legalizeType(context, originalParam->getFullType());
+ if (legalParamType.flavor == LegalType::Flavor::simple)
+ {
+ // Simple case: things were legalized to a simple type,
+ // so we can just use the original parameter as-is.
+ originalParam->type = legalParamType.getSimple();
+ return LegalVal::simple(originalParam);
+ }
+ else
+ {
+ // Complex case: we need to insert zero or more new parameters,
+ // which will replace the old ones.
+
+ context->insertBeforeParam = originalParam;
+
+ auto newVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nullptr);
+
+ originalParam->removeFromParent();
+ context->replacedInstructions.Add(originalParam);
+ return newVal;
+ }
+}
+
+
+
static LegalVal legalizeInst(
- IRTypeLegalizationContext* context,
+ IRTypeLegalizationContext* context,
IRInst* inst)
{
- if (inst->op == kIROp_Var)
- return legalizeLocalVar(context, (IRVar*)inst);
+ // Special-case certain operations
+ switch (inst->op)
+ {
+ case kIROp_Var:
+ return legalizeLocalVar(context, cast<IRVar>(inst));
+
+ case kIROp_Param:
+ return legalizeParam(context, cast<IRParam>(inst));
+
+ default:
+ break;
+ }
// Need to legalize all the operands.
- auto argCount = inst->getArgCount();
+ auto argCount = inst->getOperandCount();
List<LegalVal> legalArgs;
bool anyComplex = false;
for (UInt aa = 0; aa < argCount; ++aa)
{
- auto oldArg = inst->getArg(aa);
+ auto oldArg = inst->getOperand(aa);
auto legalArg = legalizeOperand(context, oldArg);
legalArgs.Add(legalArg);
@@ -706,7 +746,7 @@ static LegalVal legalizeInst(
for (UInt aa = 0; aa < argCount; ++aa)
{
auto legalArg = legalArgs[aa];
- inst->setArg(aa, legalArg.getSimple());
+ inst->setOperand(aa, legalArg.getSimple());
}
inst->type = legalType.getSimple();
@@ -720,9 +760,9 @@ static LegalVal legalizeInst(
// We will set up the IR builder so that any new
// instructions generated will be placed after
- // the location of the original instruct.
+ // the location of the original instruction.
auto builder = context->builder;
- builder->curBlock = inst->getParentBlock();
+ builder->curBlock = as<IRBlock>(inst->getParent());
builder->insertBeforeInst = inst->getNextInst();
LegalVal legalVal = legalizeInst(
@@ -795,47 +835,15 @@ static void legalizeFunc(
addParamType(newFuncType, legalParamType);
}
irFunc->type = newFuncType;
- List<LegalVal> paramVals;
- List<IRValue*> oldParams;
// we use this list to store replaced local var insts.
// these old instructions will be freed when we are done.
- context->oldLocalVars.Clear();
+ context->replacedInstructions.Clear();
// Go through the blocks of the function
for (auto bb = irFunc->getFirstBlock(); bb; bb = bb->getNextBlock())
{
- // Legalize the parameters of the block, which may
- // involve increasing the number of parameters
- for (auto pp = bb->getFirstParam(); pp; pp = pp->nextParam)
- {
- auto legalParamType = legalizeType(context, pp->getFullType());
- if (legalParamType.flavor != LegalType::Flavor::simple)
- {
- context->insertBeforeParam = pp;
- context->builder->curBlock = nullptr;
-
- auto paramVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nullptr);
- paramVals.Add(paramVal);
- if (pp == bb->getFirstParam())
- {
- bb->firstParam = pp;
- while (bb->firstParam->prevParam)
- bb->firstParam = bb->firstParam->prevParam;
- }
- bb->lastParam = pp->prevParam;
- if (pp->prevParam)
- pp->prevParam->nextParam = pp->nextParam;
- if (pp->nextParam)
- pp->nextParam->prevParam = pp->prevParam;
- auto oldParam = pp;
- oldParams.Add(oldParam);
- registerLegalizedValue(context, oldParam, paramVal);
- }
-
- }
-
- // Now legalize the instructions inside the block
+ // Legalize the instructions inside the block
IRInst* nextInst = nullptr;
for (auto ii = bb->getFirstInst(); ii; ii = nextInst)
{
@@ -847,13 +855,12 @@ static void legalizeFunc(
}
}
- for (auto & op : oldParams)
+
+ // Clean up after any instructions we replaced along the way.
+ for (auto & lv : context->replacedInstructions)
{
- SLANG_ASSERT(op->firstUse == nullptr || op->firstUse->nextUse == nullptr);
- op->deallocate();
- }
- for (auto & lv : context->oldLocalVars)
lv->deallocate();
+ }
}
static LegalVal declareSimpleVar(
@@ -874,7 +881,7 @@ static LegalVal declareSimpleVar(
IRBuilder* builder = context->builder;
- IRValue* irVar = nullptr;
+ IRInst* irVar = nullptr;
LegalVal legalVarVal;
switch (op)
@@ -883,7 +890,7 @@ static LegalVal declareSimpleVar(
{
auto globalVar = builder->createGlobalVar(type);
globalVar->removeFromParent();
- globalVar->insertBefore(context->insertBeforeGlobal, builder->getModule());
+ globalVar->insertBefore(context->insertBeforeGlobal);
// The legalization of a global variable with linkage (one that has
// a mangled name), must also have an exported name, so that code
@@ -924,11 +931,7 @@ static LegalVal declareSimpleVar(
case kIROp_Param:
{
auto param = builder->emitParam(type);
- if (context->insertBeforeParam->prevParam)
- context->insertBeforeParam->prevParam->nextParam = param;
- param->prevParam = context->insertBeforeParam->prevParam;
- param->nextParam = context->insertBeforeParam;
- context->insertBeforeParam->prevParam = param;
+ param->insertBefore(context->insertBeforeParam);
irVar = param;
legalVarVal = LegalVal::simple(irVar);
@@ -1069,7 +1072,7 @@ static void legalizeGlobalVar(
default:
{
- context->insertBeforeGlobal = irGlobalVar->getNextValue();
+ context->insertBeforeGlobal = irGlobalVar->getNextInst();
LegalVarChain* varChain = nullptr;
LegalVarChain varChainStorage;
@@ -1119,7 +1122,7 @@ static void legalizeGlobalConstant(
default:
{
- context->insertBeforeGlobal = irGlobalConstant->getNextValue();
+ context->insertBeforeGlobal = irGlobalConstant->getNextInst();
IRGlobalNameInfo globalNameInfo;
globalNameInfo.globalVar = irGlobalConstant;
@@ -1174,8 +1177,17 @@ static void legalizeTypes(
IRTypeLegalizationContext* context)
{
auto module = context->module;
- for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue())
+ IRInst* next = nullptr;
+ for(auto ii = module->getGlobalInsts().getFirst(); ii; ii = next)
{
+ next = ii->getNextInst();
+
+ // TODO: Once we start having global-scope instructions that
+ // aren't `IRGlobalValue`s, we'll actually want to handle those
+ // here too.
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
legalizeGlobalValue(context, gv);
}
}
diff --git a/source/slang/ir-ssa.cpp b/source/slang/ir-ssa.cpp
index b793f5320..ef1f8c4d8 100644
--- a/source/slang/ir-ssa.cpp
+++ b/source/slang/ir-ssa.cpp
@@ -30,7 +30,7 @@ struct PhiInfo : RefObject
// If this phi ended up being removed as trivial, then
// this will be the value that we replaced it with.
- IRValue* replacement = nullptr;
+ IRInst* replacement = nullptr;
};
// Information about a basic block that we generate/use
@@ -39,7 +39,7 @@ struct SSABlockInfo : RefObject
{
// Map a promotable variable to the value to
// use for that variable
- Dictionary<IRVar*, IRValue*> valueForVar;
+ Dictionary<IRVar*, IRInst*> valueForVar;
// The underlying basic block.
IRBlock* block;
@@ -63,7 +63,7 @@ struct SSABlockInfo : RefObject
// Arguments that this block needs to pass along
// to the phi nodes defined by is sucessor
- List<IRValue*> successorArgs;
+ List<IRInst*> successorArgs;
};
// State for constructing SSA form for a global value
@@ -176,7 +176,7 @@ void identifyPromotableVars(
IRVar* asPromotableVar(
ConstructSSAContext* context,
- IRValue* value)
+ IRInst* value)
{
if (value->op != kIROp_Var)
return nullptr;
@@ -194,7 +194,7 @@ IRVar* asPromotableVar(
// that value will be used. If not, this all
// may recursively work its way up through
// the predecessors of the block.
-IRValue* readVar(
+IRInst* readVar(
ConstructSSAContext* context,
SSABlockInfo* blockInfo,
IRVar* var);
@@ -226,7 +226,7 @@ PhiInfo* addPhi(
return phiInfo;
}
-IRValue* tryRemoveTrivialPhi(
+IRInst* tryRemoveTrivialPhi(
ConstructSSAContext* context,
PhiInfo* phiInfo)
{
@@ -236,7 +236,7 @@ IRValue* tryRemoveTrivialPhi(
// to the phi are either the same, or are equal
// to the phi itself.
- IRValue* same = nullptr;
+ IRInst* same = nullptr;
for (auto u : phiInfo->operands)
{
auto usedVal = u.get();
@@ -319,7 +319,7 @@ IRValue* tryRemoveTrivialPhi(
return same;
}
-IRValue* addPhiOperands(
+IRInst* addPhiOperands(
ConstructSSAContext* context,
SSABlockInfo* blockInfo,
PhiInfo* phiInfo)
@@ -328,7 +328,7 @@ IRValue* addPhiOperands(
auto block = blockInfo->block;
- List<IRValue*> operandValues;
+ List<IRInst*> operandValues;
for (auto predBlock : block->getPredecessors())
{
// Precondition: if we have multiple predecessors, then
@@ -362,7 +362,7 @@ void writeVar(
ConstructSSAContext* /*context*/,
SSABlockInfo* blockInfo,
IRVar* var,
- IRValue* val)
+ IRInst* val)
{
blockInfo->valueForVar[var] = val;
}
@@ -403,12 +403,12 @@ void maybeSealBlock(
blockInfo->isSealed = true;
}
-IRValue* readVarRec(
+IRInst* readVarRec(
ConstructSSAContext* context,
SSABlockInfo* blockInfo,
IRVar* var)
{
- IRValue* val = nullptr;
+ IRInst* val = nullptr;
if (!blockInfo->isSealed)
{
// If block isn't sealed, we need to
@@ -499,7 +499,7 @@ IRValue* readVarRec(
}
-IRValue* readVar(
+IRInst* readVar(
ConstructSSAContext* context,
SSABlockInfo* blockInfo,
IRVar* var)
@@ -507,7 +507,7 @@ IRValue* readVar(
// In the easy case, there will be a preceeding
// store in the same block, so we can use
// that local value.
- IRValue* val = nullptr;
+ IRInst* val = nullptr;
if (blockInfo->valueForVar.TryGetValue(var, val))
{
// Hooray, we found a value to use, and we
@@ -617,7 +617,7 @@ void processBlock(
}
}
- blockInfo->builder.insertBeforeInst = block->lastInst;
+ blockInfo->builder.insertBeforeInst = block->getLastChild();
// Once we are done with all of the instructions
// in a block, we can mark it as "filled," which
@@ -757,7 +757,7 @@ void constructSSA(ConstructSSAContext* context)
// and stores of promotable variables with simple values.
auto globalVal = context->globalVal;
- for (auto bb = globalVal->firstBlock; bb; bb = bb->nextBlock)
+ for(auto bb : globalVal->getBlocks())
{
auto blockInfo = new SSABlockInfo();
blockInfo->block = bb;
@@ -765,11 +765,11 @@ void constructSSA(ConstructSSAContext* context)
blockInfo->builder.sharedBuilder = &context->sharedBuilder;
blockInfo->builder.curBlock = bb;
blockInfo->builder.curFunc = globalVal;
- blockInfo->builder.insertBeforeInst = bb->lastInst;
+ blockInfo->builder.insertBeforeInst = bb->getLastInst();
context->blockInfos.Add(bb, blockInfo);
}
- for (auto bb = globalVal->firstBlock; bb; bb = bb->nextBlock)
+ for(auto bb : globalVal->getBlocks())
{
auto blockInfo = * context->blockInfos.TryGetValue(bb);
processBlock(context, bb, blockInfo);
@@ -778,7 +778,7 @@ void constructSSA(ConstructSSAContext* context)
// We need to transfer the logical arguments to our phi nodes
// from the phi nodes back to the predecessor blocks that will
// pass them in.
- for (auto bb = globalVal->firstBlock; bb; bb = bb->nextBlock)
+ for(auto bb : globalVal->getBlocks())
{
auto blockInfo = *context->blockInfos.TryGetValue(bb);
@@ -799,7 +799,7 @@ void constructSSA(ConstructSSAContext* context)
UInt predIndex = predCounter++;
auto predInfo = *context->blockInfos.TryGetValue(pp);
- IRValue* operandVal = phiInfo->operands[predIndex].get();
+ IRInst* operandVal = phiInfo->operands[predIndex].get();
phiInfo->operands[predIndex].clear();
@@ -810,7 +810,7 @@ void constructSSA(ConstructSSAContext* context)
// Some blocks may now need to pass along arguments to their sucessor,
// which have been stored into the `SSABlockInfo::successorArgs` field.
- for (auto bb = globalVal->firstBlock; bb; bb = bb->nextBlock)
+ for(auto bb : globalVal->getBlocks())
{
auto blockInfo = * context->blockInfos.TryGetValue(bb);
@@ -827,18 +827,18 @@ void constructSSA(ConstructSSAContext* context)
// We need to replace the terminator instruction with one that
// has additional arguments.
- IRTerminatorInst* oldTerminator = (IRTerminatorInst*) bb->getLastInst();
- assert(isTerminatorInst(oldTerminator));
+ IRTerminatorInst* oldTerminator = bb->getTerminator();
+ assert(oldTerminator);
blockInfo->builder.insertBeforeInst = nullptr;
- auto oldArgCount = oldTerminator->argCount;
+ auto oldArgCount = oldTerminator->getOperandCount();
auto newArgCount = oldArgCount + addedArgCount;
- List<IRValue*> newArgs;
+ List<IRInst*> newArgs;
for (UInt aa = 0; aa < oldArgCount; ++aa)
{
- newArgs.Add(oldTerminator->getArg(aa));
+ newArgs.Add(oldTerminator->getOperand(aa));
}
for (UInt aa = 0; aa < addedArgCount; ++aa)
{
@@ -884,7 +884,7 @@ void constructSSA(IRModule* module, IRGlobalValueWithCode* globalVal)
constructSSA(&context);
}
-void constructSSA(IRModule* module, IRGlobalValue* globalVal)
+void constructSSA(IRModule* module, IRInst* globalVal)
{
switch (globalVal->op)
{
@@ -900,9 +900,9 @@ void constructSSA(IRModule* module, IRGlobalValue* globalVal)
void constructSSA(IRModule* module)
{
- for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue())
+ for(auto ii : module->getGlobalInsts())
{
- constructSSA(module, gv);
+ constructSSA(module, ii);
}
}
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 8dc158b6c..b4d19c0d5 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -82,7 +82,7 @@ namespace Slang
#endif
}
- void IRUse::init(IRUser* u, IRValue* v)
+ void IRUse::init(IRInst* u, IRInst* v)
{
clear();
@@ -104,7 +104,7 @@ namespace Slang
debugValidate();
}
- void IRUse::set(IRValue* uv)
+ void IRUse::set(IRInst* uv)
{
init(user, uv);
}
@@ -138,7 +138,7 @@ namespace Slang
//
- IRUse* IRUser::getArgs()
+ IRUse* IRInst::getOperands()
{
// We assume that *all* instructions are laid out
// in memory such that their arguments come right
@@ -150,7 +150,7 @@ namespace Slang
return (IRUse*)(this + 1);
}
- IRDecoration* IRValue::findDecorationImpl(IRDecorationOp decorationOp)
+ IRDecoration* IRInst::findDecorationImpl(IRDecorationOp decorationOp)
{
for( auto dd = firstDecoration; dd; dd = dd->next )
{
@@ -160,20 +160,37 @@ namespace Slang
return nullptr;
}
+ // IRParam
+
+ IRParam* IRParam::getNextParam()
+ {
+ return as<IRParam>(getNextInst());
+ }
+
// IRBlock
+ IRParam* IRBlock::getLastParam()
+ {
+ IRParam* param = getFirstParam();
+ if (!param) return nullptr;
+
+ while (auto nextParam = param->getNextParam())
+ param = nextParam;
+
+ return param;
+ }
+
void IRBlock::addParam(IRParam* param)
{
- if (auto lp = lastParam)
+ auto lastParam = getLastParam();
+ if (lastParam)
{
- lp->nextParam = param;
- param->prevParam = lp;
+ param->insertAfter(lastParam);
}
else
{
- firstParam = param;
+ param->insertAtStart(this);
}
- lastParam = param;
}
// The predecessors of a block should all show up as users
@@ -191,7 +208,7 @@ namespace Slang
// If the block somehow isn't terminated, then
// there is no way to read its successors, so
// we return an empty list.
- if (!terminator || !isTerminatorInst(terminator))
+ if (!terminator || !as<IRTerminatorInst>(terminator))
return IRBlock::SuccessorList(nullptr, nullptr);
// Otherwise, based on the opcode of the terminator
@@ -200,7 +217,7 @@ namespace Slang
IRUse* end = nullptr;
UInt stride = 1;
- auto args = terminator->getArgs();
+ auto operands = terminator->getOperands();
switch (terminator->op)
{
case kIROp_ReturnVal:
@@ -212,21 +229,25 @@ namespace Slang
case kIROp_unconditionalBranch:
case kIROp_loop:
// unconditonalBranch <block>
- begin = args + 0;
+ begin = operands + 0;
end = begin + 1;
break;
case kIROp_conditionalBranch:
case kIROp_ifElse:
// conditionalBranch <condition> <trueBlock> <falseBlock>
- begin = args + 1;
+ begin = operands + 1;
end = begin + 2;
break;
case kIROp_switch:
// switch <val> <break> <default> <caseVal1> <caseBlock1> ...
- begin = args + 4;
- end = args + terminator->getArgCount() + 1;
+ begin = operands + 4;
+
+ // TODO: this ends up point one *after* the "one after the end"
+ // location, so we should really change the representation
+ // so that we don't need to form this pointer...
+ end = operands + terminator->getOperandCount() + 1;
stride = 2;
break;
@@ -238,47 +259,6 @@ namespace Slang
return IRBlock::SuccessorList(begin, end, stride);
}
- void IRBlock::insertAfter(IRBlock* other)
- {
- assert(other);
- insertAfter(other, other->parentFunc);
- }
-
- void IRBlock::insertAfter(IRBlock* other, IRGlobalValueWithCode* func)
- {
- assert(other || func);
-
- if (!other) other = func->lastBlock;
- if (!func) func = other->parentFunc;
-
- assert(func);
-
- auto pp = other;
- auto nn = other ? other->nextBlock : nullptr;
-
- if (pp)
- {
- pp->nextBlock = this;
- }
- else
- {
- func->firstBlock = this;
- }
-
- if (nn)
- {
- nn->prevBlock = this;
- }
- else
- {
- func->lastBlock = this;
- }
-
- this->prevBlock = pp;
- this->nextBlock = nn;
- this->parentFunc = func;
- }
-
static IRUse* adjustPredecessorUse(IRUse* use)
{
// We will search until we either find a
@@ -410,18 +390,7 @@ namespace Slang
void IRGlobalValueWithCode::addBlock(IRBlock* block)
{
- block->parentFunc = this;
-
- if (auto lb = lastBlock)
- {
- lb->nextBlock = block;
- block->prevBlock = lb;
- }
- else
- {
- firstBlock = block;
- }
- lastBlock = block;
+ block->insertAtEnd(this);
}
//
@@ -454,52 +423,6 @@ namespace Slang
//
- void IRValueListBase::addImpl(IRValue* parent, IRChildValue* val)
- {
- val->parent = parent;
- val->prev = last;
- val->next = nullptr;
-
- if (last)
- {
- last->next = val;
- }
- else
- {
- first = val;
- }
-
- last = val;
- }
-
-
- //
-
- // Add an instruction to a specific parent
- void IRBuilder::addInst(IRBlock* pblock, IRInst* inst)
- {
- inst->parent = pblock;
-
- if (!pblock->firstInst)
- {
- inst->prev = nullptr;
- inst->next = nullptr;
-
- pblock->firstInst = inst;
- pblock->lastInst = inst;
- }
- else
- {
- auto prev = pblock->lastInst;
-
- inst->prev = prev;
- inst->next = nullptr;
-
- prev->next = inst;
- pblock->lastInst = inst;
- }
- }
-
// Add an instruction into the current scope
void IRBuilder::addInst(
IRInst* inst)
@@ -509,17 +432,19 @@ namespace Slang
inst->insertBefore(insertBeforeInst);
return;
}
-
- auto parent = curBlock;
- if (!parent)
- return;
-
- addInst(parent, inst);
+ else if (curBlock)
+ {
+ inst->insertAtEnd(curBlock);
+ }
+ else
+ {
+ // Don't append the instruction anywhere
+ }
}
static void maybeSetSourceLoc(
IRBuilder* builder,
- IRValue* value)
+ IRInst* value)
{
if(!builder)
return;
@@ -566,20 +491,21 @@ namespace Slang
// argument for all instructions).
template<typename T>
static T* createInstImpl(
+ IRModule* module,
IRBuilder* builder,
UInt size,
IROp op,
IRType* type,
UInt fixedArgCount,
- IRValue* const* fixedArgs,
+ IRInst* const* fixedArgs,
UInt varArgCount = 0,
- IRValue* const* varArgs = nullptr)
+ IRInst* const* varArgs = nullptr)
{
- assert(builder->getModule());
- T* inst = (T*)builder->getModule()->memoryPool.allocZero(size);
+ assert(module);
+ T* inst = (T*)module->memoryPool.allocZero(size);
new(inst)T();
- inst->argCount = (uint32_t)(fixedArgCount + varArgCount);
+ inst->operandCount = (uint32_t)(fixedArgCount + varArgCount);
inst->op = op;
@@ -587,7 +513,7 @@ namespace Slang
maybeSetSourceLoc(builder, inst);
- auto operand = inst->getArgs();
+ auto operand = inst->getOperands();
for( UInt aa = 0; aa < fixedArgCount; ++aa )
{
@@ -606,17 +532,40 @@ namespace Slang
}
operand++;
}
- builder->getModule()->irObjectsToFree.Add(inst);
+ module->irObjectsToFree.Add(inst);
return inst;
}
template<typename T>
+ static T* createInstImpl(
+ IRBuilder* builder,
+ UInt size,
+ IROp op,
+ IRType* type,
+ UInt fixedArgCount,
+ IRInst* const* fixedArgs,
+ UInt varArgCount = 0,
+ IRInst* const* varArgs = nullptr)
+ {
+ return createInstImpl<T>(
+ builder->getModule(),
+ builder,
+ size,
+ op,
+ type,
+ fixedArgCount,
+ fixedArgs,
+ varArgCount,
+ varArgs);
+ }
+
+ template<typename T>
static T* createInst(
IRBuilder* builder,
IROp op,
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
return createInstImpl<T>(
builder,
@@ -647,7 +596,7 @@ namespace Slang
IRBuilder* builder,
IROp op,
IRType* type,
- IRValue* arg)
+ IRInst* arg)
{
return createInstImpl<T>(
builder,
@@ -663,10 +612,10 @@ namespace Slang
IRBuilder* builder,
IROp op,
IRType* type,
- IRValue* arg1,
- IRValue* arg2)
+ IRInst* arg1,
+ IRInst* arg2)
{
- IRValue* args[] = { arg1, arg2 };
+ IRInst* args[] = { arg1, arg2 };
return createInstImpl<T>(
builder,
sizeof(T),
@@ -682,7 +631,7 @@ namespace Slang
IROp op,
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
return createInstImpl<T>(
builder,
@@ -699,9 +648,9 @@ namespace Slang
IROp op,
IRType* type,
UInt fixedArgCount,
- IRValue* const* fixedArgs,
+ IRInst* const* fixedArgs,
UInt varArgCount,
- IRValue* const* varArgs)
+ IRInst* const* varArgs)
{
return createInstImpl<T>(
builder,
@@ -719,11 +668,11 @@ namespace Slang
IRBuilder* builder,
IROp op,
IRType* type,
- IRValue* arg1,
+ IRInst* arg1,
UInt varArgCount,
- IRValue* const* varArgs)
+ IRInst* const* varArgs)
{
- IRValue* fixedArgs[] = { arg1 };
+ IRInst* fixedArgs[] = { arg1 };
UInt fixedArgCount = sizeof(fixedArgs) / sizeof(fixedArgs[0]);
return createInstImpl<T>(
@@ -742,11 +691,11 @@ namespace Slang
{
if(left.inst->op != right.inst->op) return false;
if(left.inst->parent != right.inst->parent) return false;
- if(left.inst->argCount != right.inst->argCount) return false;
+ if(left.inst->operandCount != right.inst->operandCount) return false;
- auto argCount = left.inst->argCount;
- auto leftArgs = left.inst->getArgs();
- auto rightArgs = right.inst->getArgs();
+ auto argCount = left.inst->operandCount;
+ auto leftArgs = left.inst->getOperands();
+ auto rightArgs = right.inst->getOperands();
for( UInt aa = 0; aa < argCount; ++aa )
{
if(leftArgs[aa].get() != rightArgs[aa].get())
@@ -760,10 +709,10 @@ namespace Slang
{
auto code = Slang::GetHashCode(inst->op);
code = combineHash(code, Slang::GetHashCode(inst->parent));
- code = combineHash(code, Slang::GetHashCode(inst->argCount));
+ code = combineHash(code, Slang::GetHashCode(inst->getOperandCount()));
- auto argCount = inst->argCount;
- auto args = inst->getArgs();
+ auto argCount = inst->getOperandCount();
+ auto args = inst->getOperands();
for( UInt aa = 0; aa < argCount; ++aa )
{
code = combineHash(code, Slang::GetHashCode(args[aa].get()));
@@ -838,7 +787,7 @@ namespace Slang
//
- IRValue* IRBuilder::getBoolValue(bool inValue)
+ IRInst* IRBuilder::getBoolValue(bool inValue)
{
IRIntegerValue value = inValue;
return findOrEmitConstant(
@@ -849,7 +798,7 @@ namespace Slang
&value);
}
- IRValue* IRBuilder::getIntValue(IRType* type, IRIntegerValue value)
+ IRInst* IRBuilder::getIntValue(IRType* type, IRIntegerValue value)
{
return findOrEmitConstant(
this,
@@ -859,7 +808,7 @@ namespace Slang
&value);
}
- IRValue* IRBuilder::getFloatValue(IRType* type, IRFloatingPointValue value)
+ IRInst* IRBuilder::getFloatValue(IRType* type, IRFloatingPointValue value)
{
return findOrEmitConstant(
this,
@@ -881,7 +830,7 @@ namespace Slang
return inst;
}
- IRValue* IRBuilder::getDeclRefVal(
+ IRInst* IRBuilder::getDeclRefVal(
DeclRefBase const& declRef)
{
// TODO: we should cache these...
@@ -893,9 +842,9 @@ namespace Slang
return irValue;
}
- IRValue * IRBuilder::getTypeVal(IRType * type)
+ IRInst* IRBuilder::getTypeVal(IRType * type)
{
- auto irValue = createValue<IRValue>(
+ auto irValue = createValue<IRInst>(
this,
kIROp_TypeType,
nullptr);
@@ -905,10 +854,10 @@ namespace Slang
return irValue;
}
- IRValue* IRBuilder::emitSpecializeInst(
+ IRInst* IRBuilder::emitSpecializeInst(
Type* type,
- IRValue* genericVal,
- IRValue* specDeclRef)
+ IRInst* genericVal,
+ IRInst* specDeclRef)
{
auto inst = createInst<IRSpecialize>(
this,
@@ -920,9 +869,9 @@ namespace Slang
return inst;
}
- IRValue* IRBuilder::emitSpecializeInst(
+ IRInst* IRBuilder::emitSpecializeInst(
Type* type,
- IRValue* genericVal,
+ IRInst* genericVal,
DeclRef<Decl> specDeclRef)
{
auto specDeclRefVal = getDeclRefVal(specDeclRef);
@@ -936,10 +885,10 @@ namespace Slang
return inst;
}
- IRValue* IRBuilder::emitLookupInterfaceMethodInst(
- IRType* type,
- IRValue* witnessTableVal,
- IRValue* interfaceMethodVal)
+ IRInst* IRBuilder::emitLookupInterfaceMethodInst(
+ IRType* type,
+ IRInst* witnessTableVal,
+ IRInst* interfaceMethodVal)
{
auto inst = createInst<IRLookupWitnessMethod>(
this,
@@ -951,7 +900,7 @@ namespace Slang
return inst;
}
- IRValue* IRBuilder::emitLookupInterfaceMethodInst(
+ IRInst* IRBuilder::emitLookupInterfaceMethodInst(
IRType* type,
DeclRef<Decl> witnessTableDeclRef,
DeclRef<Decl> interfaceMethodDeclRef)
@@ -963,9 +912,9 @@ namespace Slang
return emitLookupInterfaceMethodInst(type, witnessTableVal, interfaceMethodVal);
}
- IRValue* IRBuilder::emitLookupInterfaceMethodInst(
+ IRInst* IRBuilder::emitLookupInterfaceMethodInst(
IRType* type,
- IRValue* witnessTableVal,
+ IRInst* witnessTableVal,
DeclRef<Decl> interfaceMethodDeclRef)
{
DeclRef<Decl> removeSubstDeclRef = interfaceMethodDeclRef;
@@ -974,7 +923,7 @@ namespace Slang
return emitLookupInterfaceMethodInst(type, witnessTableVal, interfaceMethodVal);
}
- IRValue* IRBuilder::emitFindWitnessTable(
+ IRInst* IRBuilder::emitFindWitnessTable(
DeclRef<Decl> baseTypeDeclRef,
IRType* interfaceType)
{
@@ -992,9 +941,9 @@ namespace Slang
IRInst* IRBuilder::emitCallInst(
IRType* type,
- IRValue* pFunc,
+ IRInst* pFunc,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto inst = createInstWithTrailingArgs<IRCall>(
this,
@@ -1012,7 +961,7 @@ namespace Slang
IRType* type,
IROp op,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto inst = createInstWithTrailingArgs<IRInst>(
this,
@@ -1027,7 +976,7 @@ namespace Slang
IRInst* IRBuilder::emitConstructorInst(
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto inst = createInstWithTrailingArgs<IRInst>(
this,
@@ -1042,7 +991,7 @@ namespace Slang
IRInst* IRBuilder::emitMakeVector(
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
return emitIntrinsicInst(type, kIROp_makeVector, argCount, args);
}
@@ -1050,7 +999,7 @@ namespace Slang
IRInst* IRBuilder::emitMakeArray(
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
return emitIntrinsicInst(type, kIROp_makeArray, argCount, args);
}
@@ -1058,7 +1007,7 @@ namespace Slang
IRInst* IRBuilder::emitMakeStruct(
IRType* type,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
return emitIntrinsicInst(type, kIROp_makeStruct, argCount, args);
}
@@ -1067,148 +1016,28 @@ namespace Slang
{
auto module = new IRModule();
module->session = getSession();
- return module;
- }
-
- void IRGlobalValue::insertBefore(IRGlobalValue* other)
- {
- assert(other);
- insertBefore(other, other->parentModule);
- }
-
- void IRGlobalValue::insertBefore(IRGlobalValue* other, IRModule* module)
- {
- assert(other || module);
-
- if(!other) other = module->firstGlobalValue;
- if(!module) module = other->parentModule;
- assert(module);
-
- auto nn = other;
- auto pp = other ? other->prevGlobalValue : nullptr;
-
- if(pp)
- {
- pp->nextGlobalValue = this;
- }
- else
- {
- module->firstGlobalValue = this;
- }
-
- if(nn)
- {
- nn->prevGlobalValue = this;
- }
- else
- {
- module->lastGlobalValue = this;
- }
-
- this->prevGlobalValue = pp;
- this->nextGlobalValue = nn;
- this->parentModule = module;
- }
-
- void IRGlobalValue::insertAtStart(IRModule* module)
- {
- insertBefore(module->firstGlobalValue, module);
- }
-
- void IRGlobalValue::insertAfter(IRGlobalValue* other)
- {
- assert(other);
- insertAfter(other, other->parentModule);
- }
-
- void IRGlobalValue::insertAfter(IRGlobalValue* other, IRModule* module)
- {
- assert(other || module);
-
- if(!other) other = module->lastGlobalValue;
- if(!module) module = other->parentModule;
-
- assert(module);
-
- auto pp = other;
- auto nn = other ? other->nextGlobalValue : nullptr;
-
- if(pp)
- {
- pp->nextGlobalValue = this;
- }
- else
- {
- module->firstGlobalValue = this;
- }
-
- if(nn)
- {
- nn->prevGlobalValue = this;
- }
- else
- {
- module->lastGlobalValue = this;
- }
-
- this->prevGlobalValue = pp;
- this->nextGlobalValue = nn;
- this->parentModule = module;
- }
-
- void IRGlobalValue::insertAtEnd(IRModule* module)
- {
- assert(module);
- insertAfter(module->lastGlobalValue, module);
- }
-
- void IRGlobalValue::removeFromParent()
- {
- auto module = parentModule;
- if(!module)
- return;
-
- auto pp = this->prevGlobalValue;
- auto nn = this->nextGlobalValue;
-
- if(pp)
- {
- pp->nextGlobalValue = nn;
- }
- else
- {
- module->firstGlobalValue = nn;
- }
-
- if( nn )
- {
- nn->prevGlobalValue = pp;
- }
- else
- {
- module->lastGlobalValue = pp;
- }
- }
+ auto moduleInst = createInstImpl<IRModuleInst>(
+ module,
+ this,
+ sizeof(IRModuleInst),
+ kIROp_Module,
+ nullptr,
+ 0,
+ nullptr);
+ module->moduleInst = moduleInst;
- void IRGlobalValue::moveToEnd()
- {
- auto module = parentModule;
- removeFromParent();
- insertAtEnd(module);
+ return module;
}
-
-
void addGlobalValue(
- IRModule* module,
+ IRModule* module,
IRGlobalValue* value)
{
if(!module)
return;
- value->parentModule = module;
- value->insertAfter(module->lastGlobalValue, module);
+ value->insertAtEnd(module->moduleInst);
}
IRFunc* IRBuilder::createFunc()
@@ -1259,8 +1088,8 @@ namespace Slang
IRWitnessTableEntry* IRBuilder::createWitnessTableEntry(
IRWitnessTable* witnessTable,
- IRValue* requirementKey,
- IRValue* satisfyingVal)
+ IRInst* requirementKey,
+ IRInst* satisfyingVal)
{
IRWitnessTableEntry* entry = createInst<IRWitnessTableEntry>(
this,
@@ -1271,7 +1100,7 @@ namespace Slang
if (witnessTable)
{
- witnessTable->entries.add(witnessTable, entry);
+ entry->insertAtEnd(witnessTable);
}
return entry;
@@ -1347,7 +1176,7 @@ namespace Slang
}
IRInst* IRBuilder::emitLoad(
- IRValue* ptr)
+ IRInst* ptr)
{
// Note: a `load` operation does not consider the rate
// (if any) attached to its operand (see the use of `getDataType`
@@ -1394,8 +1223,8 @@ namespace Slang
}
IRInst* IRBuilder::emitStore(
- IRValue* dstPtr,
- IRValue* srcVal)
+ IRInst* dstPtr,
+ IRInst* srcVal)
{
auto inst = createInst<IRStore>(
this,
@@ -1409,9 +1238,9 @@ namespace Slang
}
IRInst* IRBuilder::emitFieldExtract(
- IRType* type,
- IRValue* base,
- IRValue* field)
+ IRType* type,
+ IRInst* base,
+ IRInst* field)
{
auto inst = createInst<IRFieldExtract>(
this,
@@ -1425,9 +1254,9 @@ namespace Slang
}
IRInst* IRBuilder::emitFieldAddress(
- IRType* type,
- IRValue* base,
- IRValue* field)
+ IRType* type,
+ IRInst* base,
+ IRInst* field)
{
auto inst = createInst<IRFieldAddress>(
this,
@@ -1441,9 +1270,9 @@ namespace Slang
}
IRInst* IRBuilder::emitElementExtract(
- IRType* type,
- IRValue* base,
- IRValue* index)
+ IRType* type,
+ IRInst* base,
+ IRInst* index)
{
auto inst = createInst<IRFieldAddress>(
this,
@@ -1458,8 +1287,8 @@ namespace Slang
IRInst* IRBuilder::emitElementAddress(
IRType* type,
- IRValue* basePtr,
- IRValue* index)
+ IRInst* basePtr,
+ IRInst* index)
{
auto inst = createInst<IRFieldAddress>(
this,
@@ -1474,9 +1303,9 @@ namespace Slang
IRInst* IRBuilder::emitSwizzle(
IRType* type,
- IRValue* base,
+ IRInst* base,
UInt elementCount,
- IRValue* const* elementIndices)
+ IRInst* const* elementIndices)
{
auto inst = createInstWithTrailingArgs<IRSwizzle>(
this,
@@ -1492,13 +1321,13 @@ namespace Slang
IRInst* IRBuilder::emitSwizzle(
IRType* type,
- IRValue* base,
+ IRInst* base,
UInt elementCount,
UInt const* elementIndices)
{
auto intType = getSession()->getBuiltinType(BaseType::Int);
- IRValue* irElementIndices[4];
+ IRInst* irElementIndices[4];
for (UInt ii = 0; ii < elementCount; ++ii)
{
irElementIndices[ii] = getIntValue(intType, elementIndices[ii]);
@@ -1510,12 +1339,12 @@ namespace Slang
IRInst* IRBuilder::emitSwizzleSet(
IRType* type,
- IRValue* base,
- IRValue* source,
+ IRInst* base,
+ IRInst* source,
UInt elementCount,
- IRValue* const* elementIndices)
+ IRInst* const* elementIndices)
{
- IRValue* fixedArgs[] = { base, source };
+ IRInst* fixedArgs[] = { base, source };
UInt fixedArgCount = sizeof(fixedArgs) / sizeof(fixedArgs[0]);
auto inst = createInstWithTrailingArgs<IRSwizzleSet>(
@@ -1533,14 +1362,14 @@ namespace Slang
IRInst* IRBuilder::emitSwizzleSet(
IRType* type,
- IRValue* base,
- IRValue* source,
+ IRInst* base,
+ IRInst* source,
UInt elementCount,
UInt const* elementIndices)
{
auto intType = getSession()->getBuiltinType(BaseType::Int);
- IRValue* irElementIndices[4];
+ IRInst* irElementIndices[4];
for (UInt ii = 0; ii < elementCount; ++ii)
{
irElementIndices[ii] = getIntValue(intType, elementIndices[ii]);
@@ -1550,7 +1379,7 @@ namespace Slang
}
IRInst* IRBuilder::emitReturn(
- IRValue* val)
+ IRInst* val)
{
auto inst = createInst<IRReturnVal>(
this,
@@ -1621,7 +1450,7 @@ namespace Slang
IRBlock* breakBlock,
IRBlock* continueBlock)
{
- IRValue* args[] = { target, breakBlock, continueBlock };
+ IRInst* args[] = { target, breakBlock, continueBlock };
UInt argCount = sizeof(args) / sizeof(args[0]);
auto inst = createInst<IRLoop>(
@@ -1635,11 +1464,11 @@ namespace Slang
}
IRInst* IRBuilder::emitBranch(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* falseBlock)
{
- IRValue* args[] = { val, trueBlock, falseBlock };
+ IRInst* args[] = { val, trueBlock, falseBlock };
UInt argCount = sizeof(args) / sizeof(args[0]);
auto inst = createInst<IRConditionalBranch>(
@@ -1653,12 +1482,12 @@ namespace Slang
}
IRInst* IRBuilder::emitIfElse(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* falseBlock,
IRBlock* afterBlock)
{
- IRValue* args[] = { val, trueBlock, falseBlock, afterBlock };
+ IRInst* args[] = { val, trueBlock, falseBlock, afterBlock };
UInt argCount = sizeof(args) / sizeof(args[0]);
auto inst = createInst<IRIfElse>(
@@ -1672,7 +1501,7 @@ namespace Slang
}
IRInst* IRBuilder::emitIf(
- IRValue* val,
+ IRInst* val,
IRBlock* trueBlock,
IRBlock* afterBlock)
{
@@ -1680,7 +1509,7 @@ namespace Slang
}
IRInst* IRBuilder::emitLoopTest(
- IRValue* val,
+ IRInst* val,
IRBlock* bodyBlock,
IRBlock* breakBlock)
{
@@ -1688,13 +1517,13 @@ namespace Slang
}
IRInst* IRBuilder::emitSwitch(
- IRValue* val,
+ IRInst* val,
IRBlock* breakLabel,
IRBlock* defaultLabel,
UInt caseArgCount,
- IRValue* const* caseArgs)
+ IRInst* const* caseArgs)
{
- IRValue* fixedArgs[] = { val, breakLabel, defaultLabel };
+ IRInst* fixedArgs[] = { val, breakLabel, defaultLabel };
UInt fixedArgCount = sizeof(fixedArgs) / sizeof(fixedArgs[0]);
auto inst = createInstWithTrailingArgs<IRSwitch>(
@@ -1709,14 +1538,14 @@ namespace Slang
return inst;
}
- IRHighLevelDeclDecoration* IRBuilder::addHighLevelDeclDecoration(IRValue* inst, Decl* decl)
+ IRHighLevelDeclDecoration* IRBuilder::addHighLevelDeclDecoration(IRInst* inst, Decl* decl)
{
auto decoration = addDecoration<IRHighLevelDeclDecoration>(inst, kIRDecorationOp_HighLevelDecl);
decoration->decl = decl;
return decoration;
}
- IRLayoutDecoration* IRBuilder::addLayoutDecoration(IRValue* inst, Layout* layout)
+ IRLayoutDecoration* IRBuilder::addLayoutDecoration(IRInst* inst, Layout* layout)
{
auto decoration = addDecoration<IRLayoutDecoration>(inst);
decoration->layout = layout;
@@ -1732,7 +1561,7 @@ namespace Slang
int indent = 0;
UInt idCounter = 1;
- Dictionary<IRValue*, UInt> mapValueToID;
+ Dictionary<IRInst*, UInt> mapValueToID;
};
static void dump(
@@ -1778,11 +1607,11 @@ namespace Slang
}
}
- bool opHasResult(IRValue* inst);
+ bool opHasResult(IRInst* inst);
static UInt getID(
IRDumpContext* context,
- IRValue* value)
+ IRInst* value)
{
UInt id = 0;
if (context->mapValueToID.TryGetValue(value, id))
@@ -1799,7 +1628,7 @@ namespace Slang
static void dumpID(
IRDumpContext* context,
- IRValue* inst)
+ IRInst* inst)
{
if (!inst)
{
@@ -1847,7 +1676,7 @@ namespace Slang
static void dumpOperand(
IRDumpContext* context,
- IRValue* inst)
+ IRInst* inst)
{
// TODO: we should have a dedicated value for the `undef` case
if (!inst)
@@ -2107,16 +1936,6 @@ namespace Slang
IRDumpContext* context,
IRInst* inst);
- static void dumpChildrenRaw(
- IRDumpContext* context,
- IRBlock* block)
- {
- for (auto ii = block->firstInst; ii; ii = ii->getNextInst())
- {
- dumpInst(context, ii);
- }
- }
-
static void dumpBlock(
IRDumpContext* context,
IRBlock* block)
@@ -2125,19 +1944,30 @@ namespace Slang
dump(context, "block ");
dumpID(context, block);
- if( block->getFirstParam() )
+ IRInst* inst = block->getFirstInst();
+
+ // First walk through any `param` instructions,
+ // so that we can format them nicely
+ if (auto firstParam = as<IRParam>(inst))
{
dump(context, "(\n");
context->indent += 2;
- for (auto pp = block->getFirstParam(); pp; pp = pp->getNextParam())
+
+ for(;;)
{
- if (pp != block->getFirstParam())
+ auto param = as<IRParam>(inst);
+ if (!param)
+ break;
+
+ if (param != firstParam)
dump(context, ",\n");
+ inst = inst->getNextInst();
+
dumpIndent(context);
dump(context, "param ");
- dumpID(context, pp);
- dumpInstTypeClause(context, pp->getFullType());
+ dumpID(context, param);
+ dumpInstTypeClause(context, param->getFullType());
}
context->indent -= 2;
dump(context, ")");
@@ -2145,191 +1975,10 @@ namespace Slang
dump(context, ":\n");
context->indent++;
- dumpChildrenRaw(context, block);
- }
-#if 0
- static void dumpChildrenRaw(
- IRDumpContext* context,
- IRFunc* func)
- {
- for (auto bb = func->getFirstBlock(); bb; bb = bb->getNextBlock())
- {
- dumpBlock(context, bb);
- }
- }
-
- static void dumpChildren(
- IRDumpContext* context,
- IRFunc* func)
- {
- dumpIndent(context);
- dump(context, "{\n");
- context->indent++;
- dumpChildrenRaw(context, func);
- context->indent--;
- dumpIndent(context);
- dump(context, "}\n");
- }
-#endif
- static void dumpInst(
- IRDumpContext* context,
- IRInst* inst)
- {
- if (!inst)
- {
- dumpIndent(context);
- dump(context, "<null>");
- return;
- }
-
- auto op = inst->op;
-
- // There are several ops we want to special-case here,
- // so that they will be more pleasant to look at.
- //
-#if 0
- switch (op)
- {
- case kIROp_Module:
- dumpIndent(context);
- dump(context, "module\n");
- dumpChildren(context, inst);
- return;
-
- case kIROp_Func:
- {
- IRFunc* func = (IRFunc*)inst;
- dump(context, "\n");
- dumpIndent(context);
- dump(context, "func ");
- dumpID(context, func);
- dumpInstTypeClause(context, func->getType());
- dump(context, "\n");
-
- dumpIndent(context);
- dump(context, "{\n");
- context->indent++;
-
- for (auto bb = func->getFirstBlock(); bb; bb = bb->getNextBlock())
- {
- if (bb != func->getFirstBlock())
- dump(context, "\n");
- dumpInst(context, bb);
- }
-
- context->indent--;
- dump(context, "}\n");
- }
- return;
-
- case kIROp_TypeType:
- case kIROp_Param:
- case kIROp_IntLit:
- case kIROp_FloatLit:
- case kIROp_boolConst:
- // Don't dump here
- return;
-
- case kIROp_Block:
- {
- IRBlock* block = (IRBlock*)inst;
-
- context->indent--;
- dump(context, "block ");
- dumpID(context, block);
-
- if( block->getFirstParam() )
- {
- dump(context, "(");
- context->indent++;
- for (auto pp = block->getFirstParam(); pp; pp = pp->getNextParam())
- {
- if (pp != block->getFirstParam())
- dump(context, ",\n");
-
- dumpIndent(context);
- dump(context, "param ");
- dumpID(context, pp);
- dumpInstTypeClause(context, pp->getType());
- }
- context->indent--;
- dump(context, ")\n");
- }
- dump(context, ":\n");
- context->indent++;
-
- dumpChildrenRaw(context, block);
- }
- return;
-
- default:
- break;
- }
-#endif
-
-#if 0
- // We also want to special-case based on the *type*
- // of the instruction
- auto type = inst->getType();
- if (type && type->op == kIROp_TypeType)
- {
- // We probably don't want to print most types
- // when producing "friendly" output.
- switch (type->op)
- {
- case kIROp_StructType:
- break;
-
- default:
- return;
- }
- }
-#endif
-
-
- // Okay, we have a seemingly "ordinary" op now
- dumpIndent(context);
-
- auto opInfo = &kIROpInfos[op];
- auto type = inst->getFullType();
- auto dataType = inst->getDataType();
-
- if (!dataType)
+ for(; inst; inst = inst->getNextInst())
{
- // No result, okay...
+ dumpInst(context, inst);
}
- else
- {
- auto basicType = dataType->As<BasicExpressionType>();
- if (basicType && basicType->baseType == BaseType::Void)
- {
- // No result, okay...
- }
- else
- {
- dump(context, "let ");
- dumpID(context, inst);
- dumpInstTypeClause(context, type);
- dump(context, "\t= ");
- }
- }
-
- dump(context, opInfo->name);
-
- uint32_t argCount = inst->argCount;
- dump(context, "(");
- for (uint32_t ii = 0; ii < argCount; ++ii)
- {
- if (ii != 0)
- dump(context, ", ");
-
- auto argVal = inst->getArgs()[ii].get();
-
- dumpOperand(context, argVal);
- }
- dump(context, ")");
-
- dump(context, "\n");
}
void dumpGenericSignature(
@@ -2506,50 +2155,109 @@ namespace Slang
dump(context, "\n{\n");
context->indent++;
- for (auto entry : witnessTable->entries)
+ for (auto ii : witnessTable->getChildren())
{
- dumpIRWitnessTableEntry(context, entry);
+ dumpInst(context, ii);
}
context->indent--;
dump(context, "}\n");
}
- void dumpIRGlobalValue(
+ static void dumpInst(
IRDumpContext* context,
- IRGlobalValue* value)
+ IRInst* inst)
{
- switch (value->op)
+ if (!inst)
+ {
+ dumpIndent(context);
+ dump(context, "<null>");
+ return;
+ }
+
+ auto op = inst->op;
+
+ // There are several ops we want to special-case here,
+ // so that they will be more pleasant to look at.
+ //
+ switch (op)
{
case kIROp_Func:
- dumpIRFunc(context, (IRFunc*)value);
- break;
+ dumpIRFunc(context, (IRFunc*)inst);
+ return;
case kIROp_global_var:
- dumpIRGlobalVar(context, (IRGlobalVar*)value);
- break;
+ dumpIRGlobalVar(context, (IRGlobalVar*)inst);
+ return;
case kIROp_global_constant:
- dumpIRGlobalConstant(context, (IRGlobalConstant*)value);
- break;
+ dumpIRGlobalConstant(context, (IRGlobalConstant*)inst);
+ return;
case kIROp_witness_table:
- dumpIRWitnessTable(context, (IRWitnessTable*)value);
- break;
+ dumpIRWitnessTable(context, (IRWitnessTable*)inst);
+ return;
+
+ case kIROp_witness_table_entry:
+ dumpIRWitnessTableEntry(context, (IRWitnessTableEntry*)inst);
+ return;
default:
- dump(context, "???\n");
break;
}
+
+ // Okay, we have a seemingly "ordinary" op now
+ dumpIndent(context);
+
+ auto opInfo = &kIROpInfos[op];
+ auto type = inst->getFullType();
+ auto dataType = inst->getDataType();
+
+ if (!dataType)
+ {
+ // No result, okay...
+ }
+ else
+ {
+ auto basicType = dataType->As<BasicExpressionType>();
+ if (basicType && basicType->baseType == BaseType::Void)
+ {
+ // No result, okay...
+ }
+ else
+ {
+ dump(context, "let ");
+ dumpID(context, inst);
+ dumpInstTypeClause(context, type);
+ dump(context, "\t= ");
+ }
+ }
+
+ dump(context, opInfo->name);
+
+ UInt argCount = inst->getOperandCount();
+ dump(context, "(");
+ for (UInt ii = 0; ii < argCount; ++ii)
+ {
+ if (ii != 0)
+ dump(context, ", ");
+
+ auto argVal = inst->getOperand(ii);
+
+ dumpOperand(context, argVal);
+ }
+ dump(context, ")");
+
+ dump(context, "\n");
}
void dumpIRModule(
IRDumpContext* context,
IRModule* module)
{
- for( auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
- dumpIRGlobalValue(context, gv);
+ dumpInst(context, ii);
}
}
@@ -2570,7 +2278,7 @@ namespace Slang
context.builder = &sb;
context.indent = 0;
- dumpIRGlobalValue(&context, globalVal);
+ dumpInst(&context, globalVal);
fprintf(stderr, "%s\n", sb.Buffer());
fflush(stderr);
@@ -2595,7 +2303,7 @@ namespace Slang
//
//
- Type* IRValue::getRate()
+ Type* IRInst::getRate()
{
if(auto rateQualifiedType = type->As<RateQualifiedType>())
return rateQualifiedType->rate;
@@ -2603,7 +2311,7 @@ namespace Slang
return nullptr;
}
- Type* IRValue::getDataType()
+ Type* IRInst::getDataType()
{
if(auto rateQualifiedType = type->As<RateQualifiedType>())
return rateQualifiedType->valueType;
@@ -2611,7 +2319,7 @@ namespace Slang
return type;
}
- void IRValue::replaceUsesWith(IRValue* other)
+ void IRInst::replaceUsesWith(IRInst* other)
{
// We will walk through the list of uses for the current
// instruction, and make them point to the other inst.
@@ -2635,11 +2343,11 @@ namespace Slang
// Try to move to the next use, but bail
// out if we are at the last one.
- IRUse* next = uu->nextUse;
- if( !next )
+ IRUse* nn = uu->nextUse;
+ if( !nn )
break;
- uu = next;
+ uu = nn;
}
// We are at the last use (and there must
@@ -2673,19 +2381,13 @@ namespace Slang
ff->debugValidate();
}
- void IRValue::deallocate()
+ void IRInst::deallocate()
{
-#if 0
- // I'm going to intentionally leak here,
- // just to test that this is the source
- // of my heap-corruption crashes.
-#else
// Run destructor to be sure...
- this->~IRValue();
-#endif
+ this->~IRInst();
}
- void IRValue::dispose()
+ void IRInst::dispose()
{
IRObject::dispose();
type = decltype(type)();
@@ -2695,60 +2397,146 @@ namespace Slang
// as `other`, right before it.
void IRInst::insertBefore(IRInst* other)
{
+ assert(other);
+ insertBefore(other, other->parent);
+ }
+
+ void IRInst::insertAtStart(IRParentInst* newParent)
+ {
+ assert(newParent);
+ insertBefore(newParent->children.first, newParent);
+ }
+
+ void IRInst::moveToStart()
+ {
+ auto p = parent;
+ removeFromParent();
+ insertAtStart(p);
+ }
+
+ void IRInst::insertBefore(IRInst* other, IRParentInst* newParent)
+ {
// Make sure this instruction has been removed from any previous parent
this->removeFromParent();
- auto bb = other->getParentBlock();
- assert(bb);
+ assert(other || newParent);
+ if (!other) other = newParent->children.first;
+ if (!newParent) newParent = other->parent;
+ assert(newParent);
+
+ auto nn = other;
+ auto pp = other ? other->getPrevInst() : nullptr;
- auto pp = other->getPrevInst();
if( pp )
{
pp->next = this;
}
else
{
- bb->firstInst = this;
+ newParent->children.first = this;
+ }
+
+ if (nn)
+ {
+ nn->prev = this;
+ }
+ else
+ {
+ newParent->children.last = this;
}
this->prev = pp;
- this->next = other;
- this->parent = bb;
+ this->next = nn;
+ this->parent = newParent;
+ }
+
+ void IRInst::insertAfter(IRInst* other)
+ {
+ assert(other);
+ insertAfter(other, other->parent);
+ }
+
+ void IRInst::insertAtEnd(IRParentInst* newParent)
+ {
+ assert(newParent);
+ insertAfter(newParent->children.last, newParent);
+ }
+
+ void IRInst::moveToEnd()
+ {
+ auto p = parent;
+ removeFromParent();
+ insertAtEnd(p);
+ }
+
+ void IRInst::insertAfter(IRInst* other, IRParentInst* newParent)
+ {
+ // Make sure this instruction has been removed from any previous parent
+ this->removeFromParent();
+
+ assert(other || newParent);
+ if (!other) other = newParent->children.last;
+ if (!newParent) newParent = other->parent;
+ 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;
+ }
- other->prev = 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()
{
+ auto oldParent = getParent();
+
// If we don't currently have a parent, then
// we are doing fine.
- if(!getParentBlock())
+ if(!oldParent)
return;
- auto bb = getParentBlock();
auto pp = getPrevInst();
auto nn = getNextInst();
if(pp)
{
- SLANG_ASSERT(pp->getParentBlock() == bb);
+ SLANG_ASSERT(pp->getParent() == oldParent);
pp->next = nn;
}
else
{
- bb->firstInst = nn;
+ oldParent->children.first = nn;
}
if(nn)
{
- SLANG_ASSERT(nn->getParentBlock() == bb);
+ SLANG_ASSERT(nn->getParent() == oldParent);
nn->prev = pp;
}
else
{
- bb->lastInst = pp;
+ oldParent->children.last = pp;
}
prev = nullptr;
@@ -2758,9 +2546,9 @@ namespace Slang
void IRInst::removeArguments()
{
- for( UInt aa = 0; aa < argCount; ++aa )
+ for( UInt aa = 0; aa < operandCount; ++aa )
{
- IRUse& use = getArgs()[aa];
+ IRUse& use = getOperands()[aa];
use.clear();
}
}
@@ -2824,10 +2612,10 @@ namespace Slang
// no value (null pointer)
none,
- // A simple `IRValue*` that represents the actual value
+ // A simple `IRInst*` that represents the actual value
value,
- // An `IRValue*` that represents the address of the actual value
+ // An `IRInst*` that represents the address of the actual value
address,
// A `TupleValImpl` that represents zero or more `ScalarizedVal`s
@@ -2840,7 +2628,7 @@ namespace Slang
};
// Create a value representing a simple value
- static ScalarizedVal value(IRValue* irValue)
+ static ScalarizedVal value(IRInst* irValue)
{
ScalarizedVal result;
result.flavor = Flavor::value;
@@ -2850,7 +2638,7 @@ namespace Slang
// Create a value representing an address
- static ScalarizedVal address(IRValue* irValue)
+ static ScalarizedVal address(IRInst* irValue)
{
ScalarizedVal result;
result.flavor = Flavor::address;
@@ -2875,7 +2663,7 @@ namespace Slang
}
Flavor flavor = Flavor::none;
- IRValue* irValue = nullptr;
+ IRInst* irValue = nullptr;
RefPtr<ScalarizedValImpl> impl;
};
@@ -3457,7 +3245,7 @@ namespace Slang
ScalarizedVal adaptType(
IRBuilder* builder,
- IRValue* val,
+ IRInst* val,
Type* toType,
Type* /*fromType*/)
{
@@ -3585,7 +3373,7 @@ namespace Slang
IRBuilder* builder,
Type* elementType,
ScalarizedVal val,
- IRValue* indexVal)
+ IRInst* indexVal)
{
switch( val.flavor )
{
@@ -3667,11 +3455,11 @@ namespace Slang
index));
}
- IRValue* materializeValue(
+ IRInst* materializeValue(
IRBuilder* builder,
ScalarizedVal const& val);
- IRValue* materializeTupleValue(
+ IRInst* materializeTupleValue(
IRBuilder* builder,
ScalarizedVal val)
{
@@ -3689,7 +3477,7 @@ namespace Slang
// We will extract a value for each array element, and
// then use these to construct our result.
- List<IRValue*> arrayElementVals;
+ List<IRInst*> arrayElementVals;
UInt arrayElementCount = (UInt) GetIntVal(arrayType->ArrayLength);
for( UInt ii = 0; ii < arrayElementCount; ++ii )
@@ -3720,7 +3508,7 @@ namespace Slang
//
// TODO: this should be using a `makeStruct` instruction.
- List<IRValue*> elementVals;
+ List<IRInst*> elementVals;
for( UInt ee = 0; ee < elementCount; ++ee )
{
auto elementVal = materializeValue(builder, tupleVal->elements[ee].val);
@@ -3734,7 +3522,7 @@ namespace Slang
}
}
- IRValue* materializeValue(
+ IRInst* materializeValue(
IRBuilder* builder,
ScalarizedVal const& val)
{
@@ -3776,7 +3564,7 @@ namespace Slang
}
IRTargetIntrinsicDecoration* findTargetIntrinsicDecoration(
- IRValue* val,
+ IRInst* val,
String const& targetName)
{
for( auto dd = val->firstDecoration; dd; dd = dd->next )
@@ -3794,6 +3582,7 @@ namespace Slang
void legalizeEntryPointForGLSL(
Session* session,
+ IRModule* module,
IRFunc* func,
EntryPointLayout* entryPointLayout,
DiagnosticSink* sink,
@@ -3805,8 +3594,6 @@ namespace Slang
context.sink = sink;
context.extensionUsageTracker = extensionUsageTracker;
- auto module = func->parentModule;
-
// We require that the entry-point function has no uses,
// because otherwise we'd invalidate the signature
// at all existing call sites.
@@ -3881,7 +3668,7 @@ namespace Slang
continue;
IRReturnVal* returnInst = (IRReturnVal*) ii;
- IRValue* returnValue = returnInst->getVal();
+ IRInst* returnValue = returnInst->getVal();
// Make sure we add these instructions to the right block
builder.curBlock = bb;
@@ -3978,10 +3765,10 @@ namespace Slang
continue;
// Is it calling the append operation?
- auto callee = ii->getArg(0);
+ auto callee = ii->getOperand(0);
while( callee->op == kIROp_specialize )
{
- callee = ((IRSpecialize*) callee)->getArg(0);
+ callee = ((IRSpecialize*) callee)->getOperand(0);
}
if(callee->op != kIROp_Func)
continue;
@@ -4003,7 +3790,7 @@ namespace Slang
builder.curBlock = bb;
builder.insertBeforeInst = ii;
- assign(&builder, globalOutputVal, ScalarizedVal::value(ii->getArg(2)));
+ assign(&builder, globalOutputVal, ScalarizedVal::value(ii->getOperand(2)));
}
}
@@ -4092,7 +3879,7 @@ namespace Slang
// references to the variable(s). We are going to do that
// somewhat naively, by simply materializing the
// variables at the start.
- IRValue* materialized = materializeValue(&builder, globalValue);
+ IRInst* materialized = materializeValue(&builder, globalValue);
pp->replaceUsesWith(materialized);
}
@@ -4107,14 +3894,13 @@ namespace Slang
//
// We can safely go through and destroy the parameters
// themselves, and then clear out the parameter list.
+
for( auto pp = firstBlock->getFirstParam(); pp; )
{
auto next = pp->getNextParam();
pp->deallocate();
pp = next;
}
- firstBlock->firstParam = nullptr;
- firstBlock->lastParam = nullptr;
}
// Finally, we need to patch up the type of the entry point,
@@ -4163,7 +3949,7 @@ namespace Slang
// A map from values in the original IR module
// to their equivalent in the cloned module.
- typedef Dictionary<IRValue*, IRValue*> ClonedValueDictionary;
+ typedef Dictionary<IRInst*, IRInst*> ClonedValueDictionary;
ClonedValueDictionary clonedValues;
SharedIRBuilder sharedBuilderStorage;
@@ -4199,7 +3985,7 @@ namespace Slang
// A callback to be used when a value that is not registerd in `clonedValues`
// is needed during cloning. This gives the subtype a chance to intercept
// the operation and clone (or not) as needed.
- virtual IRValue* maybeCloneValue(IRValue* originalVal)
+ virtual IRInst* maybeCloneValue(IRInst* originalVal)
{
return originalVal;
}
@@ -4225,8 +4011,8 @@ namespace Slang
void registerClonedValue(
IRSpecContextBase* context,
- IRValue* clonedValue,
- IRValue* originalValue)
+ IRInst* clonedValue,
+ IRInst* originalValue)
{
if(!originalValue)
return;
@@ -4249,12 +4035,12 @@ namespace Slang
// Information on values to use when registering a cloned value
struct IROriginalValuesForClone
{
- IRValue* originalVal = nullptr;
+ IRInst* originalVal = nullptr;
IRSpecSymbol* sym = nullptr;
IROriginalValuesForClone() {}
- IROriginalValuesForClone(IRValue* originalValue)
+ IROriginalValuesForClone(IRInst* originalValue)
: originalVal(originalValue)
{}
@@ -4265,7 +4051,7 @@ namespace Slang
void registerClonedValue(
IRSpecContextBase* context,
- IRValue* clonedValue,
+ IRInst* clonedValue,
IROriginalValuesForClone const& originalValues)
{
registerClonedValue(context, clonedValue, originalValues.originalVal);
@@ -4277,8 +4063,8 @@ namespace Slang
void cloneDecorations(
IRSpecContextBase* context,
- IRValue* clonedValue,
- IRValue* originalValue)
+ IRInst* clonedValue,
+ IRInst* originalValue)
{
for (auto dd = originalValue->firstDecoration; dd; dd = dd->next)
{
@@ -4322,7 +4108,7 @@ namespace Slang
struct IRSpecContext : IRSpecContextBase
{
// Override the "maybe clone" logic so that we always clone
- virtual IRValue* maybeCloneValue(IRValue* originalVal) override;
+ virtual IRInst* maybeCloneValue(IRInst* originalVal) override;
// Override teh "maybe clone" logic so that we carefully
// clone any IR proxy values inside substitutions
@@ -4349,7 +4135,7 @@ namespace Slang
}
- IRValue* IRSpecContext::maybeCloneValue(IRValue* originalValue)
+ IRInst* IRSpecContext::maybeCloneValue(IRInst* originalValue)
{
switch (originalValue->op)
{
@@ -4425,7 +4211,7 @@ namespace Slang
break;
case kIROp_TypeType:
{
- IRValue* od = (IRValue*)originalValue;
+ IRInst* od = (IRInst*)originalValue;
int ioDiff = 0;
auto newType = od->type->SubstituteImpl(subst, &ioDiff);
return builder->getTypeVal(newType.As<Type>());
@@ -4437,9 +4223,9 @@ namespace Slang
}
}
- IRValue* cloneValue(
+ IRInst* cloneValue(
IRSpecContextBase* context,
- IRValue* originalValue);
+ IRInst* originalValue);
RefPtr<Val> cloneSubstitutionArg(
IRSpecContext* context,
@@ -4526,11 +4312,11 @@ namespace Slang
return newDeclRef;
}
- IRValue* cloneValue(
+ IRInst* cloneValue(
IRSpecContextBase* context,
- IRValue* originalValue)
+ IRInst* originalValue)
{
- IRValue* clonedValue = nullptr;
+ IRInst* clonedValue = nullptr;
if (context->getClonedValues().TryGetValue(originalValue, clonedValue))
{
return clonedValue;
@@ -4539,12 +4325,16 @@ namespace Slang
return context->maybeCloneValue(originalValue);
}
- IRValue* maybeCloneValueWithMangledName(
+ IRInst* maybeCloneValueWithMangledName(
IRSpecContextBase* context,
IRGlobalValue* originalValue)
{
- for (auto gv = context->shared->module->firstGlobalValue; gv; gv = gv->nextGlobalValue)
+ for(auto ii : context->shared->module->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
if (gv->mangledName == originalValue->mangledName)
return gv;
}
@@ -4567,7 +4357,7 @@ namespace Slang
// The common case is that we just need to construct a cloned
// instruction with the right number of operands, intialize
// it, and then add it to the sequence.
- UInt argCount = originalInst->getArgCount();
+ UInt argCount = originalInst->getOperandCount();
IRInst* clonedInst = createInstWithTrailingArgs<IRInst>(
builder, originalInst->op,
context->maybeCloneType(originalInst->type),
@@ -4578,14 +4368,14 @@ namespace Slang
context->builder = builder;
for (UInt aa = 0; aa < argCount; ++aa)
{
- IRValue* originalArg = originalInst->getArg(aa);
- IRValue* clonedArg;
+ IRInst* originalArg = originalInst->getOperand(aa);
+ IRInst* clonedArg;
if (originalArg->op == kIROp_witness_table)
clonedArg = cloneGlobalValueWithMangledName((IRSpecContext*)context,
((IRGlobalValue*)originalArg)->mangledName, (IRGlobalValue*)originalArg);
else
clonedArg = cloneValue(context, originalArg);
- clonedInst->getArgs()[aa].init(clonedInst, clonedArg);
+ clonedInst->getOperands()[aa].init(clonedInst, clonedArg);
}
builder->addInst(clonedInst);
context->builder = oldBuilder;
@@ -4681,7 +4471,7 @@ namespace Slang
cloneDecorations(context, clonedTable, originalTable);
// Clone the entries in the witness table as well
- for( auto originalEntry : originalTable->entries )
+ for(auto originalEntry : originalTable->getEntries() )
{
auto clonedKey = cloneValue(context, originalEntry->requirementKey.get());
@@ -4729,6 +4519,7 @@ namespace Slang
clonedValue->addBlock(clonedBlock);
registerClonedValue(context, clonedBlock, originalBlock);
+#if 0
// We can go ahead and clone parameters here, while we are at it.
builder->curBlock = clonedBlock;
for (auto originalParam = originalBlock->getFirstParam();
@@ -4741,6 +4532,7 @@ namespace Slang
cloneDecorations(context, clonedParam, originalParam);
registerClonedValue(context, clonedParam, originalParam);
}
+#endif
}
// Okay, now we are in a good position to start cloning
@@ -4788,7 +4580,7 @@ namespace Slang
//
// TODO: This isn't really a good requirement to place on the IR...
clonedFunc->removeFromParent();
- clonedFunc->insertAtEnd(context->getModule());
+ clonedFunc->insertAtEnd(context->getModule()->getModuleInst());
}
IRFunc* specializeIRForEntryPoint(
@@ -4933,12 +4725,10 @@ namespace Slang
switch (val->op)
{
case kIROp_witness_table:
- return ((IRWitnessTable*)val)->entries.first != nullptr;
-
case kIROp_global_var:
case kIROp_global_constant:
case kIROp_Func:
- return ((IRGlobalValueWithCode*)val)->firstBlock != nullptr;
+ return ((IRParentInst*)val)->getFirstChild() != nullptr;
default:
return false;
@@ -5058,7 +4848,7 @@ namespace Slang
{
// Check if we've already cloned this value, for the case where
// an original value has already been established.
- IRValue* clonedVal = nullptr;
+ IRInst* clonedVal = nullptr;
if( originalVal && context->getClonedValues().TryGetValue(originalVal, clonedVal) )
{
return (IRGlobalValue*) clonedVal;
@@ -5168,8 +4958,11 @@ namespace Slang
if (!originalModule)
return;
- for (auto gv = originalModule->firstGlobalValue; gv; gv = gv->nextGlobalValue)
+ for(auto ii : originalModule->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
insertGlobalValueSymbol(sharedContext, gv);
}
}
@@ -5385,6 +5178,7 @@ namespace Slang
{
legalizeEntryPointForGLSL(
session,
+ context->getModule(),
irEntryPoint,
entryPointLayout,
&compileRequest->mSink,
@@ -5402,14 +5196,14 @@ namespace Slang
IRSharedSpecContext* getShared() { return shared; }
// Override the "maybe clone" logic so that we always clone
- virtual IRValue* maybeCloneValue(IRValue* originalVal) override;
+ virtual IRInst* maybeCloneValue(IRInst* originalVal) override;
virtual RefPtr<Type> maybeCloneType(Type* originalType) override;
virtual RefPtr<Val> maybeCloneVal(Val* val) override;
};
// Convert a type-level value into an IR-level equivalent.
- IRValue* getIRValue(
+ IRInst* getIRValue(
IRGenericSpecContext* context,
Val* val)
{
@@ -5467,7 +5261,7 @@ namespace Slang
}
}
- IRValue* getSubstValue(
+ IRInst* getSubstValue(
IRGenericSpecContext* context,
DeclRef<Decl> declRef)
{
@@ -5538,7 +5332,7 @@ namespace Slang
}
}
- IRValue* IRGenericSpecContext::maybeCloneValue(IRValue* originalVal)
+ IRInst* IRGenericSpecContext::maybeCloneValue(IRInst* originalVal)
{
switch( originalVal->op )
{
@@ -5692,8 +5486,12 @@ namespace Slang
if (!dstTable)
{
auto module = sharedContext->module;
- for (auto gv = module->getFirstGlobalValue(); gv; gv = gv->getNextValue())
+ for(auto ii : module->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
if (getText(gv->mangledName) == specializedMangledName)
return (IRWitnessTable*)gv;
}
@@ -5718,7 +5516,7 @@ namespace Slang
// Specialization of witness tables should trigger cascading specializations
// of involved functions.
- for (auto entry : specTable->entries)
+ for (auto entry : specTable->getEntries())
{
if (entry->satisfyingVal.get()->op == kIROp_Func)
{
@@ -5761,8 +5559,12 @@ namespace Slang
// avoid it by building a dictionary ahead of time,
// as is being done for the `IRSpecContext` used above.
// We can probalby use the same basic context, actually.
- for (auto gv = sharedContext->module->getFirstGlobalValue(); gv; gv = gv->getNextValue())
+ for(auto ii : sharedContext->module->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
if (gv->mangledName == specMangledNameObj)
return (IRFunc*) gv;
}
@@ -5823,12 +5625,12 @@ namespace Slang
// Find the value in the given witness table that
// satisfies the given requirement (or return
// null if not found).
- IRValue* findWitnessVal(
+ IRInst* findWitnessVal(
IRWitnessTable* witnessTable,
DeclRef<Decl> const& requirementDeclRef)
{
// For now we will do a dumb linear search
- for( auto entry : witnessTable->entries )
+ for( auto entry : witnessTable->getEntries() )
{
// We expect the key on the entry to be a decl-ref,
// but lets go ahead and check, just to be sure.
@@ -5889,10 +5691,12 @@ namespace Slang
// function.
//
// We start by building up a work list of non-generic functions.
- for( auto gv = module->getFirstGlobalValue();
- gv;
- gv = gv->getNextValue() )
+ for(auto ii : module->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
// Is it a function? If not, skip.
if(gv->op != kIROp_Func)
continue;
@@ -5907,10 +5711,12 @@ namespace Slang
// Build dictionary for witness tables
Dictionary<Name*, IRWitnessTable*> witnessTables;
- for (auto gv = module->getFirstGlobalValue();
- gv;
- gv = gv->getNextValue())
+ for(auto ii : module->getGlobalInsts())
{
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
if (gv->op == kIROp_witness_table)
witnessTables.AddIfNotExists(gv->mangledName, (IRWitnessTable*)gv);
}
@@ -6115,20 +5921,18 @@ namespace Slang
if (subtypeWitness->sub->EqualsVal(paramSubst->actualType))
{
auto witnessTableName = getMangledNameForConformanceWitness(subtypeWitness->sub, subtypeWitness->sup);
- auto findWitnessTableByName = [&](String name)
+ auto findWitnessTableByName = [&](String name) -> IRGlobalValue*
{
- auto globalVar = originalIRModule->getFirstGlobalValue();
- IRGlobalValue * rs = nullptr;
- while (globalVar)
+ for (auto ii : originalIRModule->getGlobalInsts())
{
- if (getText(globalVar->mangledName) == name)
- {
- rs = globalVar;
- break;
- }
- globalVar = globalVar->getNextValue();
+ auto gv = as<IRGlobalValue>(ii);
+ if (!gv)
+ continue;
+
+ if (getText(gv->mangledName) == name)
+ return gv;
}
- return rs;
+ return nullptr;
};
auto table = findWitnessTableByName(witnessTableName);
if (!table)
@@ -6170,7 +5974,7 @@ namespace Slang
void markConstExpr(
Session* session,
- IRValue* irValue)
+ IRInst* irValue)
{
// We will take an IR value with type `T`,
// and turn it into one with type `@ConstExpr T`.
diff --git a/source/slang/ir.h b/source/slang/ir.h
index 8f350827a..95a7a97d1 100644
--- a/source/slang/ir.h
+++ b/source/slang/ir.h
@@ -25,8 +25,6 @@ struct IRFunc;
struct IRGlobalValueWithCode;
struct IRInst;
struct IRModule;
-struct IRUser;
-struct IRValue;
typedef unsigned int IROpFlags;
enum : IROpFlags
@@ -57,6 +55,13 @@ enum IROp : int16_t
#include "ir-inst-defs.h"
+#define INST(ID, MNEMONIC, ARG_COUNT, FLAGS) /* empty */
+#define INST_RANGE(BASE, FIRST, LAST) \
+ kIROp_First##BASE = kIROp_##FIRST, \
+ kIROp_Last##BASE = kIROp_##LAST,
+
+#include "ir-inst-defs.h"
+
kIROp_Invalid = -1,
};
@@ -83,18 +88,18 @@ IROpInfo getIROpInfo(IROp op);
// A use of another value/inst within an IR operation
struct IRUse
{
- IRValue* get() { return usedValue; }
- IRUser* getUser() { return user; }
+ IRInst* get() { return usedValue; }
+ IRInst* getUser() { return user; }
- void init(IRUser* user, IRValue* usedValue);
- void set(IRValue* usedValue);
+ void init(IRInst* user, IRInst* usedValue);
+ void set(IRInst* usedValue);
void clear();
- // The value that is being used
- IRValue* usedValue = nullptr;
+ // The instruction that is being used
+ IRInst* usedValue = nullptr;
- // The value that is doing the using.
- IRUser* user = nullptr;
+ // The instruction that is doing the using.
+ IRInst* user = nullptr;
// The next use of the same value
IRUse* nextUse = nullptr;
@@ -145,22 +150,30 @@ struct IRDecoration : public IRObject
typedef Type IRType;
struct IRBlock;
+struct IRParentInst;
-// Base class for values in the IR
-struct IRValue : public IRObject
+// Every value in the IR is an instruction (even things
+// like literal values).
+//
+struct IRInst : public IRObject
{
// The operation that this value represents
IROp op;
- // The type of the result value of this instruction,
- // or `null` to indicate that the instruction has
- // no value.
- RefPtr<Type> type;
+ // The total number of operands of this instruction.
+ //
+ // TODO: We shouldn't need to allocate this on
+ // all instructions. Instead we should have
+ // instructions that need "vararg" support to
+ // allocate this field ahead of the `this`
+ // pointer.
+ uint32_t operandCount = 0;
- Type* getFullType() { return type; }
+ UInt getOperandCount()
+ {
+ return operandCount;
+ }
- Type* getRate();
- Type* getDataType();
// Source location information for this value, if any
SourceLoc sourceLoc;
@@ -180,154 +193,196 @@ struct IRValue : public IRObject
IRUse* firstUse = nullptr;
+ // The parent of this instruction.
+ IRParentInst* parent;
+
+ IRParentInst* getParent() { return parent; }
+
+ // The next and previous instructions with the same parent
+ IRInst* next;
+ IRInst* prev;
+
+ IRInst* getNextInst() { return next; }
+ IRInst* getPrevInst() { return prev; }
+
+ // The type of the result value of this instruction,
+ // or `null` to indicate that the instruction has
+ // no value.
+ RefPtr<Type> type;
+
+ Type* getFullType() { return type; }
+
+ Type* getRate();
+ Type* getDataType();
+
+ // After the type, we have data that is specific to
+ // the subtype of `IRInst`. In most cases, this is
+ // just a series of `IRUse` values representing
+ // operands of the instruction.
+
+ IRUse* getOperands();
+
+ IRInst* getOperand(UInt index)
+ {
+ return getOperands()[index].get();
+ }
+
+ void setOperand(UInt index, IRInst* value)
+ {
+ getOperands()[index].set(value);
+ }
+
+
+ //
+
// Replace all uses of this value with `other`, so
// that this value will now have no uses.
- void replaceUsesWith(IRValue* other);
+ void replaceUsesWith(IRInst* other);
// Free a value (which needs to have been removed
// from its parent, had its uses eliminated, etc.)
void deallocate();
+ // Clean up any non-pool resources used by this instruction
virtual void dispose() override;
-};
-// Values that are contained in a doubly-linked
-// list inside of some parent.
-//
-// TODO: consider merging this into `IRValue` so
-// that *all* values have a parent.
-struct IRChildValue : IRValue
-{
- // The parent of this value.
- IRValue* parent;
+ // Insert this instruction into the same basic block
+ // as `other`, right before/after it.
+ void insertBefore(IRInst* other);
+ void insertAfter(IRInst* other);
+
+ // Insert as first/last child of given parent
+ void insertAtStart(IRParentInst* parent);
+ void insertAtEnd(IRParentInst* 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();
+
+ // Remove this instruction from its parent block,
+ // and then destroy it (it had better have no uses!)
+ void removeAndDeallocate();
+
+ // Clear out the arguments of this instruction,
+ // so that we don't appear on the list of uses
+ // for those values.
+ void removeArguments();
- // The next and previous values in the same
- // list on teh same parent.
- IRChildValue* next;
- IRChildValue* prev;
};
-// Helper for storing linked lists of child values.
-struct IRValueListBase
+// `dynamic_cast` equivalent
+template<typename T>
+T* as(IRInst* inst, T* /* */ = nullptr)
{
- IRChildValue* first = 0;
- IRChildValue* last = 0;
+ if (inst && T::isaImpl(inst->op))
+ return (T*) inst;
+ return nullptr;
+}
-protected:
- void addImpl(IRValue* parent, IRChildValue* val);
-};
+// `static_cast` equivalent, with debug validation
template<typename T>
-struct IRValueList : IRValueListBase
+T* cast(IRInst* inst, T* /* */ = nullptr)
{
- T* getFirst() { return (T*)first; }
- T* getLast() { return (T*)last; }
+ SLANG_ASSERT(!inst || as<T>(inst));
+ return (T*)inst;
+}
+
+
+// A double-linked list of instruction
+struct IRInstListBase
+{
+ IRInstListBase()
+ {}
+
+ IRInstListBase(IRInst* first, IRInst* last)
+ : first(first)
+ , last(last)
+ {}
+
- void add(IRValue* parent, T* val)
- {
- addImpl(parent, val);
- }
+
+ IRInst* first = 0;
+ IRInst* last = 0;
+
+ IRInst* getFirst() { return first; }
+ IRInst* getLast() { return last; }
struct Iterator
{
- T* val;
+ IRInst* inst;
- Iterator() : val(0) {}
- Iterator(T* val) : val(val) {}
+ Iterator() : inst(nullptr) {}
+ Iterator(IRInst* inst) : inst(inst) {}
void operator++()
{
- if (val)
+ if (inst)
{
- val = (T*)val->next;
+ inst = inst->next;
}
}
- T* operator*()
+ IRInst* operator*()
{
- return val;
+ return inst;
}
bool operator!=(Iterator const& i)
{
- return val != i.val;
+ return inst != i.inst;
}
};
- Iterator begin() { return Iterator(getFirst()); }
- Iterator end() { return Iterator(nullptr); }
+ Iterator begin() { return Iterator(first); }
+ Iterator end() { return Iterator(last ? last->next : nullptr); }
};
-// Values that can use other values. These always
-// have their operands "tail allocated" after
-// the fields of this type, so derived types must
-// either:
-//
-// - Add no new fields, or
-// - Add only fields that represent the `IRUse` operands
-// - Add a fixed number of `IRUse` operand fields and
-// then any additional data after them.
-//
-struct IRUser : IRChildValue
+// 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
{
- // The total number of arguments of this instruction.
- //
- // TODO: We shouldn't need to allocate this on
- // all instructions. Instead we should have
- // instructions that need "vararg" support to
- // allocate this field ahead of the `this`
- // pointer.
- uint32_t argCount = 0;
+ IRInstList() {}
- UInt getArgCount()
- {
- return argCount;
- }
+ IRInstList(T* first, T* last)
+ : IRInstListBase(first, last)
+ {}
- IRUse* getArgs();
+ explicit IRInstList(IRInstListBase const& list)
+ : IRInstListBase(list)
+ {}
- IRValue* getArg(UInt index)
- {
- return getArgs()[index].get();
- }
+ T* getFirst() { return (T*) first; }
+ T* getLast() { return (T*) last; }
- void setArg(UInt index, IRValue* value)
+ struct Iterator : public IRInstListBase::Iterator
{
- getArgs()[index].set(value);
- }
-};
-
-// Instructions are values that are children of a basic block,
-// and can actually be executed.
-struct IRInst : IRUser
-{
- IRBlock* getParentBlock() { return (IRBlock*)parent; }
+ Iterator() {}
+ Iterator(IRInst* inst) : IRInstListBase::Iterator(inst) {}
- IRInst* getPrevInst() { return (IRInst*)prev; }
- IRInst* getNextInst() { return (IRInst*)next; }
-
-
- // Insert this instruction into the same basic block
- // as `other`, right before it.
- void insertBefore(IRInst* other);
-
- // Remove this instruction from its parent block,
- // but don't delete it, or replace uses.
- void removeFromParent();
-
- // Remove this instruction from its parent block,
- // and then destroy it (it had better have no uses!)
- void removeAndDeallocate();
+ T* operator*()
+ {
+ return (T*) inst;
+ }
+ };
- // Clear out the arguments of this instruction,
- // so that we don't appear on the list of uses
- // for those values.
- void removeArguments();
+ Iterator begin() { return Iterator(first); }
+ Iterator end() { return Iterator(last ? last->next : nullptr); }
};
typedef int64_t IRIntegerValue;
typedef double IRFloatingPointValue;
-struct IRConstant : IRValue
+struct IRConstant : IRInst
{
union
{
@@ -341,10 +396,12 @@ struct IRConstant : IRValue
// A instruction that ends a basic block (usually because of control flow)
struct IRTerminatorInst : IRInst
-{};
-
-bool isTerminatorInst(IROp op);
-bool isTerminatorInst(IRInst* inst);
+{
+ static bool isaImpl(IROp op)
+ {
+ return (op >= kIROp_FirstTerminatorInst) && (op <= kIROp_LastTerminatorInst);
+ }
+};
// A function parameter is owned by a basic block, and represents
// either an incoming function parameter (in the entry block), or
@@ -354,15 +411,26 @@ bool isTerminatorInst(IRInst* inst);
// In each case, the basic idea is that a block is a "label with
// arguments."
//
-// Note: an `IRParam` is an `IRUser` *just* so that we can use
-// it as the user of other values during SSA generation.
-struct IRParam : IRUser
+struct IRParam : IRInst
+{
+ IRParam* getNextParam();
+ IRParam* getPrevParam();
+
+ static bool isaImpl(IROp op) { return op == kIROp_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
{
- IRParam* nextParam;
- IRParam* prevParam;
+ // The instructions stored under this parent
+ IRInstListBase children;
- IRParam* getNextParam() { return nextParam; }
- IRParam* getPrevParam() { return prevParam; }
+ IRInst* getFirstChild() { return children.first; }
+ IRInst* getLastChild() { return children.last; }
+ IRInstListBase getChildren() { return children; }
};
// A basic block is a parent instruction that adds the constraint
@@ -370,42 +438,63 @@ struct IRParam : IRUser
// no function declarations, or nested blocks). We also expect
// that the previous/next instruction are always a basic block.
//
-struct IRBlock : IRValue
+struct IRBlock : IRParentInst
{
// Linked list of the instructions contained in this block
//
- // Note that in a valid program, every block must end with
- // a "terminator" instruction, so these should be non-NULL,
- // and `lastInst` should actually be an `IRTerminatorInst`.
- IRInst* firstInst;
- IRInst* lastInst;
+ IRInstListBase getChildren() { return children; }
+ IRInst* getFirstInst() { return children.first; }
+ IRInst* getLastInst() { return children.last; }
- IRInst* getFirstInst() { return firstInst; }
- IRInst* getLastInst() { return lastInst; }
-
- // Links for the list of basic blocks in the parent function
- IRBlock* prevBlock;
- IRBlock* nextBlock;
-
- IRBlock* getPrevBlock() { return prevBlock; }
- IRBlock* getNextBlock() { return nextBlock; }
-
- // Linked list of parameters of this block
- IRParam* firstParam;
- IRParam* lastParam;
+ // 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()); }
+
+ // 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()); }
+ IRBlock* getNextBlock() { return cast<IRBlock>(getNextInst()); }
+
+ // The parameters of a block are represented by `IRParam`
+ // instructions at the start of the block. These play
+ // the role of function parameters for the entry block
+ // of a function, and of phi nodes in other blocks.
+ IRParam* getFirstParam() { return as<IRParam>(getFirstInst()); }
+ IRParam* getLastParam();
+ IRInstList<IRParam> getParams()
+ {
+ return IRInstList<IRParam>(
+ getFirstParam(),
+ getLastParam());
+ }
- IRParam* getFirstParam() { return firstParam; }
- IRParam* getLastParam() { return lastParam; }
void addParam(IRParam* param);
- // The parent function that contains this block
- IRGlobalValueWithCode* parentFunc;
-
- IRGlobalValueWithCode* getParent() { return parentFunc; }
-
- void insertAfter(IRBlock* other);
- void insertAfter(IRBlock* other, IRGlobalValueWithCode* func);
-
+ // The parent of a basic block is assumed to be a
+ // value with code (e.g., a function, global variable
+ // with initializer, etc.).
+ IRGlobalValueWithCode* getParent() { return cast<IRGlobalValueWithCode>(IRInst::getParent()); }
+
+ // The predecessor and successor lists of a block are needed
+ // when we want to work with the control flow graph (CFG) of
+ // a function. Rather than store these explicitly (and thus
+ // need to update them when transformations might change the
+ // CFG), we compute predecessors and successors in an
+ // implicit fashion using the use-def information for a
+ // block itself.
+ //
+ // To a first approximation, the predecessors of a block
+ // are the blocks where the IR value of the block is used.
+ // Similarly, the successors of a block are all values used
+ // by the terminator instruction of the block.
+ // The `getPredecessors()` and `getSuccessors()` functions
+ // make this more precise.
+ //
struct PredecessorList
{
PredecessorList(IRUse* begin) : b(begin) {}
@@ -465,6 +554,10 @@ struct IRBlock : IRValue
PredecessorList getPredecessors();
SuccessorList getSuccessors();
+
+ //
+
+ static bool isaImpl(IROp op) { return op == kIROp_Block; }
};
// For right now, we will represent the type of
@@ -474,21 +567,17 @@ struct IRBlock : IRValue
// TODO: need to do this better.
typedef FuncType IRFuncType;
-struct IRGlobalValue : IRValue
+// 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
{
- IRModule* parentModule;
-
// The mangled name, for a symbol that should have linkage,
// or which might have multiple declarations.
Name* mangledName = nullptr;
-
- IRGlobalValue* nextGlobalValue;
- IRGlobalValue* prevGlobalValue;
-
- IRGlobalValue* getNextValue() { return nextGlobalValue; }
- IRGlobalValue* getPrevValue() { return prevGlobalValue; }
-
+#if 0
+ // TODO: these all belong on `IRInst`
void insertBefore(IRGlobalValue* other);
void insertBefore(IRGlobalValue* other, IRModule* module);
void insertAtStart(IRModule* module);
@@ -500,18 +589,26 @@ struct IRGlobalValue : IRValue
void removeFromParent();
void moveToEnd();
+#endif
+
+ static bool isaImpl(IROp op)
+ {
+ return (op >= kIROp_FirstGlobalValue) && (op <= kIROp_LastGlobalValue);
+ }
};
/// @brief A global value that potentially holds executable code.
///
struct IRGlobalValueWithCode : IRGlobalValue
{
- // The list of basic blocks in this function
- IRBlock* firstBlock = nullptr;
- IRBlock* lastBlock = nullptr;
-
- IRBlock* getFirstBlock() { return firstBlock; }
- IRBlock* getLastBlock() { return lastBlock; }
+ // The children of a value with code will be the basic
+ // blocks of its definition.
+ IRBlock* getFirstBlock() { return cast<IRBlock>(getFirstChild()); }
+ IRBlock* getLastBlock() { return cast<IRBlock>(getLastChild()); }
+ IRInstList<IRBlock> getBlocks()
+ {
+ return IRInstList<IRBlock>(getChildren());
+ }
// Add a block to the end of this function.
void addBlock(IRBlock* block);
@@ -557,7 +654,18 @@ struct IRFunc : IRGlobalValueWithCode
}
};
-// A module is a parent to functions, global variables, types, etc.
+// 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
+{
+ // Pointer back to the non-instruction object that represents
+ // the module, so that we can get back to it in algorithms
+ // that need it.
+ IRModule* module;
+
+ IRInstListBase getGlobalInsts() { return getChildren(); }
+};
+
struct IRModule : RefObject
{
// The compilation session in use.
@@ -565,13 +673,10 @@ struct IRModule : RefObject
MemoryPool memoryPool;
List<IRObject*> irObjectsToFree; // list of ir objects to run destructor upon destruction
- // A list of all the functions and other
- // global values declared in this module.
- IRGlobalValue* firstGlobalValue = nullptr;
- IRGlobalValue* lastGlobalValue = nullptr;
+ IRModuleInst* moduleInst;
+ IRModuleInst* getModuleInst() { return moduleInst; }
- IRGlobalValue* getFirstGlobalValue() { return firstGlobalValue; }
- IRGlobalValue* getlastGlobalValue() { return lastGlobalValue; }
+ IRInstListBase getGlobalInsts() { return getModuleInst()->getChildren(); }
~IRModule()
{
diff --git a/source/slang/legalize-types.h b/source/slang/legalize-types.h
index 0799e804d..8958c683d 100644
--- a/source/slang/legalize-types.h
+++ b/source/slang/legalize-types.h
@@ -278,9 +278,9 @@ struct LegalVal
Flavor flavor = Flavor::none;
RefPtr<RefObject> obj;
- IRValue* irValue = nullptr;
+ IRInst* irValue = nullptr;
- static LegalVal simple(IRValue* irValue)
+ static LegalVal simple(IRInst* irValue)
{
LegalVal result;
result.flavor = Flavor::simple;
@@ -288,7 +288,7 @@ struct LegalVal
return result;
}
- IRValue* getSimple()
+ IRInst* getSimple()
{
assert(flavor == Flavor::simple);
return irValue;
diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp
index fde52d2e3..9508bb86d 100644
--- a/source/slang/lower-to-ir.cpp
+++ b/source/slang/lower-to-ir.cpp
@@ -82,7 +82,7 @@ struct BoundSubscriptInfo : ExtendedValueInfo
{
DeclRef<SubscriptDecl> declRef;
RefPtr<Type> type;
- List<IRValue*> args;
+ List<IRInst*> args;
};
// Some cases of `ExtendedValueInfo` need to
@@ -129,7 +129,7 @@ struct LoweredValInfo
union
{
- IRValue* val;
+ IRInst* val;
ExtendedValueInfo* ext;
};
Flavor flavor;
@@ -140,7 +140,7 @@ struct LoweredValInfo
val = nullptr;
}
- static LoweredValInfo simple(IRValue* v)
+ static LoweredValInfo simple(IRInst* v)
{
LoweredValInfo info;
info.flavor = Flavor::Simple;
@@ -148,7 +148,7 @@ struct LoweredValInfo
return info;
}
- static LoweredValInfo ptr(IRValue* v)
+ static LoweredValInfo ptr(IRInst* v)
{
LoweredValInfo info;
info.flavor = Flavor::Ptr;
@@ -334,7 +334,7 @@ LoweredValInfo maybeEmitSpecializeInst(IRGenContext* context,
);
-IRValue* getSimpleVal(IRGenContext* context, LoweredValInfo lowered);
+IRInst* getSimpleVal(IRGenContext* context, LoweredValInfo lowered);
IROp getIntrinsicOp(
Decl* decl,
@@ -361,7 +361,7 @@ LoweredValInfo emitCallToVal(
IRType* type,
LoweredValInfo funcVal,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto builder = context->irBuilder;
switch (funcVal.flavor)
@@ -379,7 +379,7 @@ LoweredValInfo emitCompoundAssignOp(
IRType* type,
IROp op,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto builder = context->irBuilder;
SLANG_UNREFERENCED_PARAMETER(argCount);
@@ -389,7 +389,7 @@ LoweredValInfo emitCompoundAssignOp(
auto leftVal = builder->emitLoad(leftPtr);
- IRValue* innerArgs[] = { leftVal, rightVal };
+ IRInst* innerArgs[] = { leftVal, rightVal };
auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
builder->emitStore(leftPtr, innerOp);
@@ -397,7 +397,7 @@ LoweredValInfo emitCompoundAssignOp(
return LoweredValInfo::ptr(leftPtr);
}
-IRValue* getOneValOfType(
+IRInst* getOneValOfType(
IRGenContext* context,
IRType* type)
{
@@ -429,7 +429,7 @@ LoweredValInfo emitPreOp(
IRType* type,
IROp op,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto builder = context->irBuilder;
SLANG_UNREFERENCED_PARAMETER(argCount);
@@ -438,9 +438,9 @@ LoweredValInfo emitPreOp(
auto preVal = builder->emitLoad(argPtr);
- IRValue* oneVal = getOneValOfType(context, type);
+ IRInst* oneVal = getOneValOfType(context, type);
- IRValue* innerArgs[] = { preVal, oneVal };
+ IRInst* innerArgs[] = { preVal, oneVal };
auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
builder->emitStore(argPtr, innerOp);
@@ -453,7 +453,7 @@ LoweredValInfo emitPostOp(
IRType* type,
IROp op,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto builder = context->irBuilder;
SLANG_UNREFERENCED_PARAMETER(argCount);
@@ -462,9 +462,9 @@ LoweredValInfo emitPostOp(
auto preVal = builder->emitLoad(argPtr);
- IRValue* oneVal = getOneValOfType(context, type);
+ IRInst* oneVal = getOneValOfType(context, type);
- IRValue* innerArgs[] = { preVal, oneVal };
+ IRInst* innerArgs[] = { preVal, oneVal };
auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
builder->emitStore(argPtr, innerOp);
@@ -472,7 +472,7 @@ LoweredValInfo emitPostOp(
return LoweredValInfo::ptr(argPtr);
}
-IRValue* findWitnessTable(
+IRInst* findWitnessTable(
IRGenContext* context,
DeclRef<Decl> declRef);
@@ -494,7 +494,7 @@ LoweredValInfo emitWitnessTableRef(
exprType = mbrExpr->BaseExpression->type;
auto declRefType = exprType->GetCanonicalType()->AsDeclRefType();
SLANG_ASSERT(declRefType);
- IRValue* witnessTableVal = nullptr;
+ IRInst* witnessTableVal = nullptr;
DeclRef<Decl> srcDeclRef = declRefType->declRef;
if (!declRefType->declRef.As<AssocTypeDecl>())
{
@@ -579,7 +579,7 @@ LoweredValInfo emitCallToDeclRef(
DeclRef<Decl> funcDeclRef,
Expr* funcExpr,
UInt argCount,
- IRValue* const* args)
+ IRInst* const* args)
{
auto builder = context->irBuilder;
@@ -743,7 +743,7 @@ LoweredValInfo emitCallToDeclRef(
IRType* type,
DeclRef<Decl> funcDeclRef,
Expr* funcExpr,
- List<IRValue*> const& args)
+ List<IRInst*> const& args)
{
return emitCallToDeclRef(context, type, funcDeclRef, funcExpr, args.Count(), args.Buffer());
}
@@ -760,7 +760,7 @@ LoweredValInfo extractField(
{
default:
{
- IRValue* irBase = getSimpleVal(context, base);
+ IRInst* irBase = getSimpleVal(context, base);
return LoweredValInfo::simple(
builder->emitFieldExtract(
fieldType,
@@ -790,7 +790,7 @@ LoweredValInfo extractField(
// We are "extracting" a field from an lvalue address,
// which means we should just compute an lvalue
// representing the field address.
- IRValue* irBasePtr = base.val;
+ IRInst* irBasePtr = base.val;
return LoweredValInfo::ptr(
builder->emitFieldAddress(
context->getSession()->getPtrType(fieldType),
@@ -876,7 +876,7 @@ top:
}
-IRValue* getSimpleVal(IRGenContext* context, LoweredValInfo lowered)
+IRInst* getSimpleVal(IRGenContext* context, LoweredValInfo lowered)
{
auto builder = context->irBuilder;
@@ -944,7 +944,7 @@ LoweredValInfo lowerVal(
IRGenContext* context,
Val* val);
-IRValue* lowerSimpleVal(
+IRInst* lowerSimpleVal(
IRGenContext* context,
Val* val)
{
@@ -1061,7 +1061,7 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
return LoweredTypeInfo(type);
}
- void addGenericArgs(List<IRValue*>* ioArgs, DeclRefBase declRef)
+ void addGenericArgs(List<IRInst*>* ioArgs, DeclRefBase declRef)
{
auto subs = declRef.substitutions.genericSubstitutions;
while(subs)
@@ -1148,7 +1148,7 @@ LoweredValInfo createVar(
void addArgs(
IRGenContext* context,
- List<IRValue*>* ioArgs,
+ List<IRInst*>* ioArgs,
LoweredValInfo argInfo)
{
auto& args = *ioArgs;
@@ -1262,7 +1262,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
// in order for a dereference to make senese, so we just
// need to extract the value type from that pointer here.
//
- IRValue* loweredBaseVal = getSimpleVal(context, loweredBase);
+ IRInst* loweredBaseVal = getSimpleVal(context, loweredBase);
RefPtr<Type> loweredBaseType = loweredBaseVal->getDataType();
if (loweredBaseType->As<PointerLikeType>()
@@ -1296,7 +1296,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
{
// Allocate a temporary of the given type
RefPtr<Type> type = lowerSimpleType(context, expr->type);
- List<IRValue*> args;
+ List<IRInst*> args;
UInt argCount = expr->args.Count();
@@ -1417,7 +1417,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
// to the list of argument values for a call.
void addDirectCallArgs(
InvokeExpr* expr,
- List<IRValue*>* ioArgs)
+ List<IRInst*>* ioArgs)
{
for( auto arg : expr->Arguments )
{
@@ -1444,7 +1444,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
void addDirectCallArgs(
InvokeExpr* expr,
DeclRef<CallableDecl> funcDeclRef,
- List<IRValue*>* ioArgs,
+ List<IRInst*>* ioArgs,
List<OutArgumentFixup>* ioFixups)
{
UInt argCount = expr->Arguments.Count();
@@ -1530,7 +1530,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
void addDirectCallArgs(
InvokeExpr* expr,
DeclRef<Decl> funcDeclRef,
- List<IRValue*>* ioArgs,
+ List<IRInst*>* ioArgs,
List<OutArgumentFixup>* ioFixups)
{
if (auto callableDeclRef = funcDeclRef.As<CallableDecl>())
@@ -1546,7 +1546,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
void addFuncBaseArgs(
LoweredValInfo funcVal,
- List<IRValue*>* ioArgs)
+ List<IRInst*>* ioArgs)
{
switch (funcVal.flavor)
{
@@ -1651,7 +1651,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
// Along the way, we may end up collecting additional
// arguments that will be part of the call.
- List<IRValue*> irArgs;
+ List<IRInst*> irArgs;
// We will also collect "fixup" actions that need
// to be performed after teh call, in order to
@@ -1715,7 +1715,7 @@ struct ExprLoweringVisitorBase : ExprVisitor<Derived, LoweredValInfo>
LoweredValInfo subscriptValue(
LoweredTypeInfo type,
LoweredValInfo baseVal,
- IRValue* indexVal)
+ IRInst* indexVal)
{
auto builder = getBuilder();
switch (baseVal.flavor)
@@ -1823,7 +1823,7 @@ struct RValueExprLoweringVisitor : ExprLoweringVisitorBase<RValueExprLoweringVis
auto irIntType = getIntType(context);
UInt elementCount = (UInt)expr->elementCount;
- IRValue* irElementIndices[4];
+ IRInst* irElementIndices[4];
for (UInt ii = 0; ii < elementCount; ++ii)
{
irElementIndices[ii] = builder->getIntValue(
@@ -1932,12 +1932,12 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
auto builder = getBuilder();
auto prevBlock = builder->curBlock;
- auto parentFunc = prevBlock ? prevBlock->parentFunc : builder->curFunc;
+ auto parentFunc = prevBlock ? prevBlock->getParent() : builder->curFunc;
// If the previous block doesn't already have
// a terminator instruction, then be sure to
// emit a branch to the new block.
- if (prevBlock && !isTerminatorInst(prevBlock->lastInst))
+ if (prevBlock && !prevBlock->getTerminator())
{
builder->emitBranch(block);
}
@@ -2326,7 +2326,7 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
// The collected (value, label) pairs for
// all the `case` statements.
- List<IRValue*> cases;
+ List<IRInst*> cases;
};
// We need a label to use for a `case` or `default` statement,
@@ -2504,7 +2504,7 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
// that we can find it for nested statements.
context->shared->breakLabels.Add(stmt, breakLabel);
- builder->curFunc = initialBlock->parentFunc;
+ builder->curFunc = initialBlock->getParent();
builder->curBlock = nullptr;
// Iterate over the body of the statement, looking
@@ -2528,8 +2528,7 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor>
if(builder->curBlock != initialBlock)
{
// Is the block already terminated?
- auto lastInst = builder->curBlock->lastInst;
- if(!lastInst || !isTerminatorInst(lastInst))
+ if(!builder->curBlock->getTerminator())
{
// Not terminated, so add one.
builder->emitBreak(breakLabel);
@@ -2580,7 +2579,7 @@ static LoweredValInfo maybeMoveMutableTemp(
default:
{
- IRValue* irVal = getSimpleVal(context, val);
+ IRInst* irVal = getSimpleVal(context, val);
auto type = irVal->getDataType();
auto var = createVar(context, type);
@@ -2656,8 +2655,8 @@ top:
auto loweredBase = swizzleInfo->base;
// Load from the base value:
- IRValue* irLeftVal = getSimpleVal(context, loweredBase);
- IRValue* irRightVal = getSimpleVal(context, right);
+ IRInst* irLeftVal = getSimpleVal(context, loweredBase);
+ IRInst* irRightVal = getSimpleVal(context, right);
// Now apply the swizzle
IRInst* irSwizzled = builder->emitSwizzleSet(
@@ -2819,7 +2818,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
cpyTable->mangledName = cpyMangledName;
context->irBuilder->createWitnessTableEntry(witnessTable,
context->irBuilder->getDeclRefVal(subInheritanceDeclRef), cpyTable);
- cpyTable->entries = witnessTable->entries;
+
+ // HACK: we are re-using the entries in a pre-existing table here,
+ // which is not how things are supposed to work.
+ cpyTable->children = witnessTable->children;
+
witnessTablesDictionary.Add(cpyTable->mangledName, cpyTable);
walkInheritanceHierarchyAndCreateWitnessTableCopies(witnessTable, subType, subInheritanceDeclRef.getDecl());
}
@@ -2888,7 +2891,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
auto satisfyingMemberDeclRef = entry.Value;
auto irRequirement = context->irBuilder->getDeclRefVal(requiredMemberDeclRef);
- IRValue* irSatisfyingVal = nullptr;
+ IRInst* irSatisfyingVal = nullptr;
if (satisfyingMemberDeclRef.As<GenericTypeConstraintDecl>())
irSatisfyingVal = context->irBuilder->getDeclRefVal(satisfyingMemberDeclRef);
else
@@ -3127,7 +3130,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
}
// TODO: we currently store a Decl* in the witness table, which causes this function
- // being invoked to translate the witness table entry into an IRValue.
+ // being invoked to translate the witness table entry into an IRInst.
// We should really allow a witness table entry to represent a type and not having to
// construct the type here. The current implementation will not work when the struct type
// is defined in a generic parent (we lose the environmental substitutions).
@@ -3787,7 +3790,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// We need to carefully add a terminator instruction to the end
// of the body, in case the user didn't do so.
- if (!isTerminatorInst(subContext->irBuilder->curBlock->lastInst))
+ if (!subContext->irBuilder->curBlock->getTerminator())
{
if (irResultType->Equals(context->getSession()->getVoidType()))
{
@@ -3940,11 +3943,11 @@ LoweredValInfo ensureDecl(
return result;
}
-IRValue* findWitnessTable(
+IRInst* findWitnessTable(
IRGenContext* context,
DeclRef<Decl> declRef)
{
- IRValue* irVal = getSimpleVal(context, emitDeclRef(context, declRef));
+ IRInst* irVal = getSimpleVal(context, emitDeclRef(context, declRef));
if (!irVal)
{
SLANG_UNEXPECTED("expected a witness table");
@@ -3986,7 +3989,7 @@ RefPtr<Val> lowerSubstitutionArg(
auto irWitnessTable = findWitnessTable(context, declaredSubtypeWitness->declRef);
// We have an IR-level value, but we need to embed it into an AST-level
- // type, so we will use a proxy `Val` that wraps up an `IRValue` as
+ // type, so we will use a proxy `Val` that wraps up an `IRInst` as
// an AST-level value.
//
// TODO: This proxy value currently doesn't enter into use-def chaining,
@@ -4174,47 +4177,6 @@ static void lowerEntryPointToIR(
lowerType(context, arg);
}
-#if 0
-IRModule* lowerEntryPointToIR(
- EntryPointRequest* entryPoint,
- ProgramLayout* programLayout,
- CodeGenTarget target)
-{
- SharedIRGenContext sharedContextStorage;
- SharedIRGenContext* sharedContext = &sharedContextStorage;
-
- sharedContext->entryPoint = entryPoint;
- sharedContext->programLayout = programLayout;
- sharedContext->target = target;
-
- IRGenContext contextStorage;
- IRGenContext* context = &contextStorage;
-
- context->shared = sharedContext;
-
- SharedIRBuilder sharedBuilderStorage;
- SharedIRBuilder* sharedBuilder = &sharedBuilderStorage;
- sharedBuilder->module = nullptr;
- sharedBuilder->session = entryPoint->compileRequest->mSession;
-
- IRBuilder builderStorage;
- IRBuilder* builder = &builderStorage;
- builder->shared = sharedBuilder;
-
- IRModule* module = builder->createModule();
- sharedBuilder->module = module;
-
- context->irBuilder = builder;
-
- auto entryPointLayout = findEntryPointLayout(sharedContext, entryPoint);
-
- lowerEntryPointToIR(context, entryPoint, entryPointLayout);
-
- return module;
-
-}
-#endif
-
IRModule* generateIRForTranslationUnit(
TranslationUnitRequest* translationUnit)
{
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 93979f473..1dd3b5ef5 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -77,83 +77,95 @@
<Item Name="[Val]">satisfyingVal</Item>
</Expand>
</Type>
- <Type Name="Slang::IRValue">
+ <Type Name="Slang::IRInst">
<DisplayString>{{{op}}}</DisplayString>
<Expand>
- <Item Name="[OpCode]">op</Item>
- <Item Name="[Type]">type</Item>
- <Item Name="[IRInst]">(Slang::IRInst*)this</Item>
- <ExpandedItem Condition="op==kIROp_decl_ref">(Slang::IRDeclRef*)this</ExpandedItem>
- <ExpandedItem Condition="op==kIROp_Func">(Slang::IRFunc*)this</ExpandedItem>
- <ExpandedItem Condition="op==kIROp_Block">(Slang::IRBlock*)this</ExpandedItem>
- <ExpandedItem Condition="op==kIROp_witness_table">(Slang::IRWitnessTable*)this</ExpandedItem>
- <ExpandedItem Condition="op==kIROp_witness_table_entry">(Slang::IRWitnessTableEntry*)this</ExpandedItem>
- <Item Name="====Uses====">"-------"</Item>
- <LinkedListItems>
- <HeadPointer>firstUse</HeadPointer>
- <NextPointer>nextUse</NextPointer>
- <ValueNode>user</ValueNode>
- </LinkedListItems>
-
+ <Item Name="[op]">op</Item>
+ <Item Name="[type]">type</Item>
+ <Synthetic Name="[operands]">
+ <DisplayString>{{count = {operandCount}}}</DisplayString>
+ <Expand>
+ <Item Name="[count]">operandCount</Item>
+ <ArrayItems>
+ <Size>operandCount</Size>
+ <ValuePointer>(IRUse*)(this + 1)</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Synthetic>
+ <Synthetic Name="[uses]">
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>firstUse</HeadPointer>
+ <NextPointer>nextUse</NextPointer>
+ <ValueNode>user</ValueNode>
+ </LinkedListItems>
+ </Expand>
+ </Synthetic>
</Expand>
</Type>
- <Type Name="Slang::IRUser">
+ <Type Name="Slang::IRParentInst">
<DisplayString>{{{op}}}</DisplayString>
<Expand>
- <Item Name="[OpCode]">op</Item>
- <Item Name="[ArgCount]">argCount</Item>
- <ArrayItems>
- <Size>argCount</Size>
- <ValuePointer>(IRUse*)(this + 1)</ValuePointer>
- </ArrayItems>
- </Expand>
- </Type>
- <Type Name="Slang::IRBlock">
- <Expand>
- <LinkedListItems>
- <HeadPointer>firstInst</HeadPointer>
- <NextPointer>(Slang::IRInst*)next</NextPointer>
- <ValueNode>this</ValueNode>
- </LinkedListItems>
+ <Item Name="[op]">op</Item>
+ <Item Name="[type]">type</Item>
+ <Synthetic Name="[children]">
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>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::IRFunc">
- <DisplayString>{{{mangledName}}}</DisplayString>
+ <Type Name="Slang::IRGlobalValue">
+ <DisplayString>{{{op} "{mangledName}"}}</DisplayString>
<Expand>
- <Item Name="[Name]">mangledName</Item>
- <Item Name="[ResultType]">(*(IRFuncType*)(type.pointer)).resultType</Item>
- <Item Name="[ParameterTypes]">(*(IRFuncType*)(type.pointer)).paramTypes</Item>
- <Item Name="[FirstBlock]">firstBlock</Item>
- <Item Name="[SpecLevel]">specializedGenericLevel</Item>
- <Item Name="genericDecls">genericDecls</Item>
+ <Item Name="[op]">op</Item>
+ <Item Name="[type]">type</Item>
+ <Synthetic Name="[children]">
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>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::IRDeclRef">
<DisplayString>{{IRDeclRef {declRef}}}</DisplayString>
<Expand>
- <Item Name="[OpCode]">op</Item>
+ <Item Name="[op]">op</Item>
+ <Item Name="[type]">type</Item>
<ExpandedItem>declRef</ExpandedItem>
</Expand>
</Type>
<Type Name="Slang::IRUse">
<DisplayString>{{IRUse {usedValue}}}</DisplayString>
<Expand>
- <Item Name="[NextUse]">nextUse</Item>
<ExpandedItem>usedValue</ExpandedItem>
</Expand>
</Type>
- <Type Name="Slang::IRModule">
- <Expand>
- <Item Name="session">session</Item>
- <LinkedListItems>
- <HeadPointer>firstGlobalValue</HeadPointer>
- <NextPointer>nextGlobalValue</NextPointer>
- <ValueNode>this</ValueNode>
- </LinkedListItems>
- </Expand>
- </Type>
- <Type Name="Slang::IRGlobalValue">
- <DisplayString>{{IRGlobalValue {op} {mangledName}}}</DisplayString>
- </Type>
</AutoVisualizer> \ No newline at end of file
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index 32f57ce4c..0dbdd8238 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -12,7 +12,6 @@
namespace Slang
{
- struct IRValue;
class Name;
class Session;
class Substitutions;