diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-11-20 13:45:10 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-11-20 13:45:10 -0800 |
| commit | 37315c96ea48045fae60f0e1cb1a3293f3ddd962 (patch) | |
| tree | a96f139a7a2dae57f67956711be14bf773a50ec2 /source/slang/ir.cpp | |
| parent | 3dff5a53a21ab2404918e772962004767024c0f3 (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.cpp | 60 |
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. // |
