summaryrefslogtreecommitdiffstats
path: root/source/slang/ir.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-11-20 13:45:10 -0800
committerGitHub <noreply@github.com>2017-11-20 13:45:10 -0800
commit37315c96ea48045fae60f0e1cb1a3293f3ddd962 (patch)
treea96f139a7a2dae57f67956711be14bf773a50ec2 /source/slang/ir.cpp
parent3dff5a53a21ab2404918e772962004767024c0f3 (diff)
IR: support global variable with initializers (#294)
The big change here is that the ability to contain basic blocks with instructions in them has been hoisted from `IRFunc` into a new base type `IRGlobalValueWithCode` shared with `IRGlobalVar`. The basic blocks of a global variable define initialization logic for it; they can be looked at like a function that returns the initial value. Places in the IR that used to assume functions contain all the code need to be updated, but so far I only handled the cloning step. The emit logic currently handles an initializer for a global variable by outputting its logic as a separate function, and then having the variable call that function to initialize itself. This should be cleaned up over time so that we generate an ordinary expression whenever possible. I also made the emit logic correctly label any global variable without a layout (that is, any that don't represent a shader parameter) as `static` so that the downstream HLSL compiler sees them as variables rather than parameters.
Diffstat (limited to 'source/slang/ir.cpp')
-rw-r--r--source/slang/ir.cpp60
1 files changed, 41 insertions, 19 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 2d3127a61..0f34d5585 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -131,7 +131,7 @@ namespace Slang
return entryBlock->getFirstParam();
}
- void IRFunc::addBlock(IRBlock* block)
+ void IRGlobalValueWithCode::addBlock(IRBlock* block)
{
block->parentFunc = this;
@@ -3317,6 +3317,11 @@ namespace Slang
}
}
+ void cloneGlobalValueWithCodeCommon(
+ IRSpecContextBase* context,
+ IRGlobalValueWithCode* clonedValue,
+ IRGlobalValueWithCode* originalValue);
+
IRGlobalVar* cloneGlobalVar(IRSpecContext* context, IRGlobalVar* originalVar)
{
auto clonedVar = context->builder->createGlobalVar(context->maybeCloneType(originalVar->getType()->getValueType()));
@@ -3333,8 +3338,12 @@ namespace Slang
context->builder->addLayoutDecoration(clonedVar, layout);
}
- // TODO: once we support initializers on global variables,
- // we'll need to handle cloning it here.
+ // Clone any code in the body of the variable, since this
+ // represents the initializer.
+ cloneGlobalValueWithCodeCommon(
+ context,
+ clonedVar,
+ originalVar);
return clonedVar;
}
@@ -3363,34 +3372,28 @@ namespace Slang
return clonedTable;
}
- void cloneFunctionCommon(
- IRSpecContextBase* context,
- IRFunc* clonedFunc,
- IRFunc* originalFunc)
+ void cloneGlobalValueWithCodeCommon(
+ IRSpecContextBase* context,
+ IRGlobalValueWithCode* clonedValue,
+ IRGlobalValueWithCode* originalValue)
{
- // First clone all the simple properties.
- clonedFunc->mangledName = originalFunc->mangledName;
- clonedFunc->genericDecl = originalFunc->genericDecl;
- clonedFunc->type = context->maybeCloneType(originalFunc->type);
-
- cloneDecorations(context, clonedFunc, originalFunc);
-
// Next we are going to clone the actual code.
IRBuilder builderStorage = *context->builder;
IRBuilder* builder = &builderStorage;
- builder->curFunc = clonedFunc;
+ builder->curFunc = clonedValue;
+
// We will walk through the blocks of the function, and clone each of them.
//
// We need to create the cloned blocks first, and then walk through them,
// because blocks might be forward referenced (this is not possible
// for other cases of instructions).
- for (auto originalBlock = originalFunc->getFirstBlock();
+ for (auto originalBlock = originalValue->getFirstBlock();
originalBlock;
originalBlock = originalBlock->getNextBlock())
{
IRBlock* clonedBlock = builder->createBlock();
- clonedFunc->addBlock(clonedBlock);
+ clonedValue->addBlock(clonedBlock);
registerClonedValue(context, clonedBlock, originalBlock);
// We can go ahead and clone parameters here, while we are at it.
@@ -3409,8 +3412,8 @@ namespace Slang
// Okay, now we are in a good position to start cloning
// the instructions inside the blocks.
{
- IRBlock* ob = originalFunc->getFirstBlock();
- IRBlock* cb = clonedFunc->getFirstBlock();
+ IRBlock* ob = originalValue->getFirstBlock();
+ IRBlock* cb = clonedValue->getFirstBlock();
while (ob)
{
assert(cb);
@@ -3426,6 +3429,25 @@ namespace Slang
}
}
+ }
+
+ void cloneFunctionCommon(
+ IRSpecContextBase* context,
+ IRFunc* clonedFunc,
+ IRFunc* originalFunc)
+ {
+ // First clone all the simple properties.
+ clonedFunc->mangledName = originalFunc->mangledName;
+ clonedFunc->genericDecl = originalFunc->genericDecl;
+ clonedFunc->type = context->maybeCloneType(originalFunc->type);
+
+ cloneDecorations(context, clonedFunc, originalFunc);
+
+ cloneGlobalValueWithCodeCommon(
+ context,
+ clonedFunc,
+ originalFunc);
+
// Shuffle the function to the end of the list, because
// it needs to follow its dependencies.
//