summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-lower-existential.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-03-26 17:35:24 -0700
committerGitHub <noreply@github.com>2024-03-26 17:35:24 -0700
commitdfdf243f07c977fa59b1a5968ce053bf590f8120 (patch)
tree6121218f9e4d664722ed6192ca08f7c0e3c1d45b /source/slang/slang-ir-lower-existential.cpp
parent0877d1a3e9d69fdbf4087581df96954e56e4dd97 (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.cpp44
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)