diff options
| author | Yong He <yonghe@outlook.com> | 2023-11-07 19:03:52 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-07 19:03:52 -0800 |
| commit | 0f2578d7b3e75c0e5ef724ffe610d004fb116a03 (patch) | |
| tree | d8bbe837a35377a64508b0c34c34feb6da43e02e /source | |
| parent | 421941993d169c943f2c364bfe9c48b603339fd1 (diff) | |
Add `IRThisTypeWitness` to stand in for witness lookups inside an interface definition. (#3316)
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 12 | ||||
| -rw-r--r-- | source/slang/slang-ir.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 43 |
5 files changed, 49 insertions, 21 deletions
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 026b8b110..e32f0d084 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -261,6 +261,9 @@ INST(StructKey, key, 0, GLOBAL) INST(GlobalGenericParam, global_generic_param, 0, GLOBAL) INST(WitnessTable, witness_table, 0, 0) +// A placeholder witness that ThisType implements the enclosing interface. +// Used only in interface definitions. +INST(ThisTypeWitness, thisTypeWitness, 1, 0) INST(GlobalHashedStringLiterals, global_hashed_string_literals, 0, 0) INST(Module, module, 0, PARENT) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index be6228f2d..a2662d53f 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -3703,6 +3703,8 @@ public: IRInst* requirementKey, IRInst* satisfyingVal); + IRInst* createThisTypeWitness(IRType* interfaceType); + IRInterfaceRequirementEntry* createInterfaceRequirementEntry( IRInst* requirementKey, IRInst* requirementVal); diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 2f603ac17..c40a62941 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -4381,6 +4381,17 @@ namespace Slang return entry; } + IRInst* IRBuilder::createThisTypeWitness(IRType* interfaceType) + { + IRInst* witness = createInst<IRThisTypeWitness>( + this, + kIROp_ThisTypeWitness, + getWitnessTableType(interfaceType)); + addGlobalValue(this, witness); + return witness; + } + + IRStructType* IRBuilder::createStructType() { IRStructType* structType = createInst<IRStructType>( @@ -7691,6 +7702,7 @@ namespace Slang case kIROp_GlobalParam: case kIROp_StructKey: case kIROp_GlobalGenericParam: + case kIROp_ThisTypeWitness: case kIROp_WitnessTable: case kIROp_WitnessTableEntry: case kIROp_InterfaceRequirementEntry: diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index cb744d4da..8d7cad0b4 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -1802,6 +1802,16 @@ struct IRThisType : IRType } }; +struct IRThisTypeWitness : IRInst +{ + IR_LEAF_ISA(ThisTypeWitness) + + IRInst* getConstraintType() + { + return getOperand(0); + } +}; + struct IRInterfaceRequirementEntry : IRInst { IRInst* getRequirementKey() { return getOperand(0); } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 8851195b3..b2c0dbb18 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1659,17 +1659,7 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower // produce transitive witnesses in shapes that will cuase us // problems here. // - if (!baseWitnessTable) - { - // If we don't have a valid baseWitnessTable, - // This can happen when we are looking up an associatedtype defined in the base interface from - // a derived interface that inherits the base interface. - // For now, we just emit a null witness. - // In the future, we may want to consider lower `ThisTypeConstraint` into IR as something like - // `IRThisTypeWitness`, and emit an explicit lookup through that witness instead. - SLANG_RELEASE_ASSERT(as<ThisType>(val->getSub())); - return LoweredValInfo(); - } + SLANG_RELEASE_ASSERT(baseWitnessTable); if (auto declaredMidToSup = as<DeclaredSubtypeWitness>(val->getMidToSup())) { @@ -1925,7 +1915,9 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower // add them as operands of the IR type. SubstitutionSet(type->getDeclRef()).forEachSubstitutionArg([&](Val* arg) { - operands.add(lowerVal(context, arg).val); + auto argVal = lowerVal(context, arg).val; + SLANG_ASSERT(argVal); + operands.add(argVal); }); return getBuilder()->getType( op, @@ -7810,9 +7802,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> context->astBuilder, createDefaultSpecializedDeclRef(subContext, nullptr, decl->getThisTypeDecl())); subContext->thisType = thisType; - - // TODO: Need to add an appropriate stand-in witness here. - subContext->thisTypeWitness = nullptr; + // Create a stand-in witness that represents `ThisType` conforms to the interface. + subContext->thisTypeWitness = subBuilder->createThisTypeWitness((IRType*)finalVal); // Lower associated types first, so they can be referred to when lowering functions. for (auto assocTypeDecl : decl->getMembersOfType<AssocTypeDecl>()) @@ -9712,6 +9703,15 @@ static void _addFlattenedTupleArgs( } } +bool isAbstractWitnessTable(IRInst* inst) +{ + if (as<IRThisTypeWitness>(inst)) + return true; + if (auto lookup = as<IRLookupWitnessMethod>(inst)) + return isAbstractWitnessTable(lookup->getWitnessTable()); + return false; +} + LoweredValInfo emitDeclRef( IRGenContext* context, Decl* decl, @@ -9853,25 +9853,26 @@ LoweredValInfo emitDeclRef( // witness table for the concrete type that conforms to `ISomething<Foo>`. // auto irWitnessTable = lowerSimpleVal(context, thisTypeSubst->getWitness()); - if (!irWitnessTable) + if (isAbstractWitnessTable(irWitnessTable)) { - // If `thisTypeSubst` doesn't lower into an IRWitnessTable, + // If `thisTypeSubst` doesn't lower into a concrete IRWitnessTable, // this is a lookup of an interface requirement // defined in some base interface from an interface type. // For now we just lower that decl as if it is referenced // from the same interface directly, e.g. a reference to // IBase.AssocType from IDerived:IBase will be lowered as // IRAssocType(IBase). - // We may want to consider extend our IR representation to - // have a `IRThisTypeWitness` object, so we can lower this case - // into an explicit lookup from `IRThisTypeWitness`, - // just like any other cases. + // We may want to consider unifying our IR representation to + // represent associated types with lookupWitness inst even inside + // interface definitions. return emitDeclRef( context, createDefaultSpecializedDeclRef(context, nullptr, decl), context->irBuilder->getTypeKind()); } + SLANG_RELEASE_ASSERT(irWitnessTable); + // // The key to use for looking up the interface member is // derived from the declaration. |
