summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-specialize.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-09-04 10:18:44 -0700
committerGitHub <noreply@github.com>2020-09-04 10:18:44 -0700
commit8f962894fd38edb47d782d303ac9ff87b3a3bb6a (patch)
tree449d0d58ca7d90a11759372c9dc82650a565f96a /source/slang/slang-ir-specialize.cpp
parent5e10f1b4f0654515af1fcb29e8d1f35e691c8aa3 (diff)
Allow mixing unspecialized and specialized existential parameters. (#1533)
* Allow mixing unspecialized and specialized existential parameters. * Fixes.
Diffstat (limited to 'source/slang/slang-ir-specialize.cpp')
-rw-r--r--source/slang/slang-ir-specialize.cpp33
1 files changed, 32 insertions, 1 deletions
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp
index 3acb34c87..75b2beeec 100644
--- a/source/slang/slang-ir-specialize.cpp
+++ b/source/slang/slang-ir-specialize.cpp
@@ -611,6 +611,33 @@ struct SpecializationContext
return nullptr;
}
+ void maybeInsertGetExistentialValue(IRInst* inst)
+ {
+ // If inst has `ExistentialBox` type, we need to make sure
+ // all uses are through `GetValueFromExistentialBox`.
+ if (auto existentialBoxType = as<IRExistentialBoxType>(inst->getDataType()))
+ {
+ ShortList<IRUse*> usesToReplace;
+ for (auto use = inst->firstUse; use; use = use->nextUse)
+ {
+ if (use->getUser()->op != kIROp_GetValueFromExistentialBox)
+ usesToReplace.add(use);
+ }
+ for (auto use : usesToReplace)
+ {
+ auto user = use->getUser();
+ IRBuilder builderStorage;
+ auto builder = &builderStorage;
+ builder->sharedBuilder = &sharedBuilderStorage;
+ builder->setInsertBefore(user);
+ auto getValueInst = builder->emitGetValueFromExistentialBox(
+ builder->getPtrType(existentialBoxType->getValueType()), inst);
+ use->set(getValueInst);
+ addToWorkList(getValueInst);
+ }
+ }
+ }
+
// All of the machinery for generic specialization
// has been defined above, so we will now walk
// through the flow of the overall specialization pass.
@@ -678,6 +705,10 @@ struct SpecializationContext
workListSet.Remove(inst);
cleanInsts.Add(inst);
+ // If inst represents a value of ExistentialBox type, all its uses
+ // must be through a `GetValueFromExistentialBox` inst.
+ maybeInsertGetExistentialValue(inst);
+
// For each instruction we process, we want to perform
// a few steps.
//
@@ -1640,7 +1671,7 @@ struct SpecializationContext
if(slotOperandCount <= 1) return;
auto concreteType = (IRType*) type->getExistentialArg(0);
- auto newVal = builder.getPtrType(kIROp_ExistentialBoxType, concreteType);
+ auto newVal = builder.getExistentialBoxType(concreteType, baseInterfaceType);
addUsersToWorkList(type);
type->replaceUsesWith(newVal);