diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-26 17:35:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-26 17:35:24 -0700 |
| commit | dfdf243f07c977fa59b1a5968ce053bf590f8120 (patch) | |
| tree | 6121218f9e4d664722ed6192ca08f7c0e3c1d45b /source/slang/slang-ir-lower-existential.cpp | |
| parent | 0877d1a3e9d69fdbf4087581df96954e56e4dd97 (diff) | |
Support mutable existential parameters. (#3836)
* Support mutable existential parameters.
* Update test.
Diffstat (limited to 'source/slang/slang-ir-lower-existential.cpp')
| -rw-r--r-- | source/slang/slang-ir-lower-existential.cpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp index 7bae856c6..13f46e914 100644 --- a/source/slang/slang-ir-lower-existential.cpp +++ b/source/slang/slang-ir-lower-existential.cpp @@ -133,9 +133,49 @@ namespace Slang processExtractExistentialElement(inst, 1); } - void processExtractExistentialType(IRExtractExistentialType* inst) + void processExtractExistentialType(IRExtractExistentialType* extractInst) { - processExtractExistentialElement(inst, 0); + IRBuilder builderStorage(sharedContext->module); + auto builder = &builderStorage; + builder->setInsertBefore(extractInst); + + IRInst* element = nullptr; + IRInst* anyValueType = nullptr; + if (isComInterfaceType(extractInst->getOperand(0)->getDataType())) + { + // If this is an COM interface, the elements (witness table/rtti) are just the interface value itself. + element = extractInst->getOperand(0); + } + else + { + element = extractTupleElement(builder, extractInst->getOperand(0), 0); + if (auto tupleType = as<IRTupleType>(extractInst->getOperand(0)->getDataType())) + { + anyValueType = tupleType->getOperand(2); + } + } + + // If this instruction is used as a type, we need to replace it with the lowered type, + // which should be an AnyValueType. + // If it is used as a value, then we can replace it with the extracted element. + auto isTypeUse = [](IRUse* use) -> bool + { + auto user = use->getUser(); + if (as<IRType>(user)) + return true; + if (use == &use->getUser()->typeUse) + return true; + return false; + }; + traverseUses(extractInst, [&](IRUse* use) + { + if (anyValueType && isTypeUse(use)) + { + builder->replaceOperand(use, anyValueType); + return; + } + builder->replaceOperand(use, element); + }); } void processGetValueFromBoundInterface(IRGetValueFromBoundInterface* inst) |
