diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2019-01-28 14:20:44 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-28 14:20:44 -0800 |
| commit | 3c3513ab501277333d1062ad2737ac4a60dac6f7 (patch) | |
| tree | b9769ba0c13165e885eca37c19011199ee7f57ab /source/slang/ir-existential.cpp | |
| parent | f2579a60a3de45d5f48f1e1433ba736647988e8e (diff) | |
Support function parameters of existential (interface) type (#802)
* Support function parameters of existential (interface) type
The basic idea here is that you can define a function that takes an interface-type parameter:
```hlsl
interface IThing { void doSOmething(); }
void coolFunction(IThing thing) { ... thing.doSomething() ... }
```
and call it with a concrete value that implements the given interface:
```hlsl
struct Stuff : IThing { void doSomething() { /* secret sauce */ } }
...
Stuff stuff;
coolFunction(stuff);
```
The compiler implementation will specialize `coolFunction` based on the concrete type that was actually passed in, resulting in output code along the lines of:
```hlsl
struct Stuff { ... }
void Stuff_doSomething(Stuff this) { /* secret sauce */ }
void coolFunction_Stuff(Stuff thing) { ... Stuff_doSomething(thing); }
```
In terms of implementation the new specialization approach has been integrated into the existing pass for generic specialization (which has been refactored significantly along the way), because generic specialization can open up opportunities for existential/interface simplification and vice versa, so there is no fixed interleaving of the two passes that can clean up everything.
The new logic therefore subsumes the old code for simplifying existential types (which only worked on local variables) in `ir-existential.{h,cpp}`. The local simplification rules from that implementation have become part of the core specialization pass instead, so that they can open up further transformation opportunities enabled by existential-type simplifications.
This code in place right now only handles the basic case of a function parameter that directly uses an interface type, and not one that wraps up an interface type in an array, structure, etc. Additional simplifications need to be introduced to deal with those cases as well.
* fixup: typos
Diffstat (limited to 'source/slang/ir-existential.cpp')
| -rw-r--r-- | source/slang/ir-existential.cpp | 114 |
1 files changed, 0 insertions, 114 deletions
diff --git a/source/slang/ir-existential.cpp b/source/slang/ir-existential.cpp deleted file mode 100644 index af15472bf..000000000 --- a/source/slang/ir-existential.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// ir-existential.cpp -#include "ir-existential.h" - -#include "ir.h" -#include "ir-insts.h" - -namespace Slang { - -struct ExistentialTypeSimplificationContext -{ - List<IRInst*> instsToRemove; - -}; - -void simplifyExistentialTypesRec( - ExistentialTypeSimplificationContext* context, - IRInst* inst) -{ - switch( inst->op ) - { - default: - break; - - case kIROp_ExtractExistentialValue: - { - auto arg = inst->getOperand(0); - if( auto makeExistential = as<IRMakeExistential>(arg) ) - { - auto value = makeExistential->getWrappedValue(); - inst->replaceUsesWith(value); - context->instsToRemove.Add(inst); - } - } - break; - - case kIROp_ExtractExistentialType: - { - auto arg = inst->getOperand(0); - if( auto makeExistential = as<IRMakeExistential>(arg) ) - { - auto value = makeExistential->getWrappedValue(); - inst->replaceUsesWith(value->getFullType()); - context->instsToRemove.Add(inst); - } - } - break; - - case kIROp_ExtractExistentialWitnessTable: - { - auto arg = inst->getOperand(0); - if( auto makeExistential = as<IRMakeExistential>(arg) ) - { - auto witnessTable = makeExistential->getWitnessTable(); - inst->replaceUsesWith(witnessTable); - context->instsToRemove.Add(inst); - } - } - break; - } - - for( auto childInst : inst->getChildren() ) - { - simplifyExistentialTypesRec(context, childInst); - } -} - -void removeUnusedExistentialsRec( - ExistentialTypeSimplificationContext* context, - IRInst* inst) -{ - switch( inst->op ) - { - default: - break; - - case kIROp_MakeExistential: - { - if( !inst->hasUses() ) - { - context->instsToRemove.Add(inst); - } - } - break; - } - - for( auto childInst : inst->getChildren() ) - { - removeUnusedExistentialsRec(context, childInst); - } -} - -void simplifyExistentialTypes( - IRModule* module) -{ - { - ExistentialTypeSimplificationContext context; - simplifyExistentialTypesRec(&context, module->getModuleInst()); - for( auto inst : context.instsToRemove ) - { - inst->removeAndDeallocate(); - } - } - - { - ExistentialTypeSimplificationContext context; - removeUnusedExistentialsRec(&context, module->getModuleInst()); - for( auto inst : context.instsToRemove ) - { - inst->removeAndDeallocate(); - } - } -} - -} // namespace Slang |
