diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2025-09-23 11:06:44 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-23 11:06:44 -0500 |
| commit | 21c663605330d629e9022314a4720b86b017f295 (patch) | |
| tree | fcbfadeddd8f1d68f1034f89288c960b6ba7294a /source/slang/slang-ir-specialize.cpp | |
| parent | 7740f7905fdebebdbe22011787d432b385f4cd9d (diff) | |
Lookup refactor (#8467)
Close #8201.
This PR unify the lowering logic for LookupDeclRef of an interface
requirement. We will always lower this AST node to a
LookupWitness IR. The key of this IR is the special witnessTableType
`ThisTypeWitness`, this witness Table is simply a wrapper for an
interface type. Our current specialization pass doesn't handle this kind
of LookupWitness IR at all, so we will also add the specialization of
this_type IR as well.
Diffstat (limited to 'source/slang/slang-ir-specialize.cpp')
| -rw-r--r-- | source/slang/slang-ir-specialize.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp index ed96b23c1..bc7bcab12 100644 --- a/source/slang/slang-ir-specialize.cpp +++ b/source/slang/slang-ir-specialize.cpp @@ -845,10 +845,31 @@ struct SpecializationContext // the result of a `specialize` instruction or other // operation that will yield such a table. // + // Since we unify the frontend such that all LookupDeclRef node + // on a interface requirement will always be lowered to lookup + // witness, it creats an exception that IRThisTypeWitness, a non-concrete + // witness table, also need to be specialized. Otherwise, there is + // no logic in the later passes can handle it. However, we know for + // sure that the IRThisTypeWitness is only used to wrap an interface + // type, therefore, it must be only used to exact the interface requirement. auto witnessTable = as<IRWitnessTable>(lookupInst->getWitnessTable()); + IRInterfaceType* interfaceType = nullptr; if (!witnessTable) { - return false; + if (auto thisTypeWitness = as<IRThisTypeWitness>(lookupInst->getWitnessTable())) + { + if (auto witnessTableType = + as<IRWitnessTableTypeBase>(thisTypeWitness->getDataType())) + { + if (!areAllOperandsFullySpecialized(witnessTableType)) + return false; + + interfaceType = as<IRInterfaceType>(witnessTableType->getConformanceType()); + } + } + + if (!interfaceType) + return false; } // Because we have a concrete witness table, we can @@ -856,7 +877,26 @@ struct SpecializationContext // the given interface requirement. // auto requirementKey = lookupInst->getRequirementKey(); - auto satisfyingVal = findWitnessVal(witnessTable, requirementKey); + IRInst* satisfyingVal = nullptr; + + if (witnessTable) + satisfyingVal = findWitnessVal(witnessTable, requirementKey); + else + { + // If we are specializing ThisTypeWitness, the result of the specialization + // could be a WitnessTabelType, in such case, in order to not break the generality + // the specialziation (we don't specialize WitnessTableType here), we will wrap it + // into another ThisTypeWitnes and handle it later. + satisfyingVal = findInterfaceRequirement(interfaceType, requirementKey); + if (auto witnessTableType = as<IRWitnessTableType>(satisfyingVal)) + { + auto newInterfaceType = as<IRInterfaceType>(witnessTableType->getConformanceType()); + IRBuilder builderStorage(module); + IRBuilder* builder = &builderStorage; + builder->setInsertBefore(lookupInst); + satisfyingVal = builder->createThisTypeWitness(newInterfaceType); + } + } // We expect to always find a satisfying value, but // we will go ahead and code defensively so that @@ -915,6 +955,7 @@ struct SpecializationContext } return nullptr; } + template<typename TDict> void _readSpecializationDictionaryImpl(TDict& dict, IRInst* dictInst) { |
