diff options
| author | Yong He <yonghe@outlook.com> | 2020-06-25 16:29:07 -0700 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2020-06-25 16:29:07 -0700 |
| commit | 218a39b65c86654772c3d6adf2479e7cadc85d24 (patch) | |
| tree | c636a65ff1ed8c347f10f4e9c2c6a703fd9ad8ad /source | |
| parent | 509e36b62de7578843abc2547921beadff7a3ce0 (diff) | |
remove ThisPointerDecoration, generate IRInterfaceType in one pass
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-emit-cpp.cpp | 50 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 9 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-generics.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-ir.h | 5 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 85 |
7 files changed, 90 insertions, 78 deletions
diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index f895b1119..7f743d9e0 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -1617,12 +1617,27 @@ void CPPSourceEmitter::_emitWitnessTableWrappers() { for (auto witnessTable : pendingWitnessTableDefinitions) { + auto interfaceType = cast<IRInterfaceType>(witnessTable->getOperand(0)); for (auto child : witnessTable->getChildren()) { if (auto entry = as<IRWitnessTableEntry>(child)) { if (auto funcVal = as<IRFunc>(entry->getSatisfyingVal())) { + IRInst* requirementVal = nullptr; + for (UInt i = 0; i < interfaceType->getOperandCount(); i++) + { + if (auto reqEntry = as<IRInterfaceRequirementEntry>(interfaceType->getOperand(i))) + { + if (reqEntry->getRequirementKey() == entry->getRequirementKey()) + { + requirementVal = reqEntry->getRequirementVal(); + break; + } + } + } + SLANG_ASSERT(requirementVal != nullptr); + IRFuncType* requirementFuncType = cast<IRFuncType>(requirementVal); emitType(funcVal->getResultType()); m_writer->emit(" "); m_writer->emit(_getWitnessTableWrapperFuncName(funcVal)); @@ -1630,23 +1645,20 @@ void CPPSourceEmitter::_emitWitnessTableWrappers() // Emit parameter list. { bool isFirst = true; - for (auto param : funcVal->getParams()) + SLANG_ASSERT(funcVal->getParamCount() == requirementFuncType->getParamCount()); + auto pp = funcVal->getParams().begin(); + for (UInt i = 0; i < requirementFuncType->getParamCount(); ++i, ++pp) { - if (as<IRTypeType>(param->getFullType())) + auto paramType = requirementFuncType->getParamType(i); + + if (as<IRTypeType>(paramType)) continue; if (isFirst) isFirst = false; else m_writer->emit(","); - - if (param->findDecoration<IRThisPointerDecoration>()) - { - m_writer->emit("void* "); - m_writer->emit(getName(param)); - continue; - } - emitSimpleFuncParamImpl(param); + emitParamType(paramType, getName(*pp)); } } m_writer->emit(")\n{\n"); @@ -1657,8 +1669,13 @@ void CPPSourceEmitter::_emitWitnessTableWrappers() // Emit argument list. { bool isFirst = true; - for (auto param : funcVal->getParams()) + UInt paramIndex = 0; + for (auto defParamIter = funcVal->getParams().begin(); + defParamIter!=funcVal->getParams().end(); + ++defParamIter, ++paramIndex) { + auto param = *defParamIter; + auto reqParamType = requirementFuncType->getParamType(paramIndex); if (as<IRTypeType>(param->getFullType())) continue; @@ -1667,7 +1684,8 @@ void CPPSourceEmitter::_emitWitnessTableWrappers() else m_writer->emit(", "); - if (param->findDecoration<IRThisPointerDecoration>()) + if (reqParamType->op == kIROp_RawPointerType && + param->getFullType()->op != kIROp_RawPointerType) { m_writer->emit("*static_cast<"); emitType(param->getFullType()); @@ -1779,13 +1797,7 @@ void CPPSourceEmitter::_maybeEmitWitnessTableTypeDefinition( m_writer->emit(", "); else isFirstParam = false; - auto thisDecor = funcVal->findDecoration<IRThisPointerDecoration>(); - if (thisDecor && cast<IRIntLit>(thisDecor->getOperand(0))->value.intVal == (IRIntegerValue)p) - { - m_writer->emit("void* param"); - m_writer->emit(p); - continue; - } + emitParamType(paramType, String("param") + String(p)); } m_writer->emit(");\n"); diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 94c29371a..85c489528 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -167,6 +167,7 @@ INST(Nop, nop, 0, 0) INST(StructType, struct, 0, PARENT) INST(InterfaceType, interface, 0, 0) INST(AssociatedType, associated_type, 0, 0) +INST(ThisType, this_type, 0, 0) // A TypeType-typed IRValue represents a IRType. // It is used to represent a type parameter/argument in a generics. @@ -510,14 +511,6 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(BindExistentialSlotsDecoration, bindExistentialSlots, 0, 0) - - /// A `[this_ptr]` decoration marks a function parameter that serves as `this` pointer. - /// `[this_ptr]` decoration is also used to mark an `IRFunc` as a non-static function. - /// The argument is an integer value that represents the index of the `this` parameter, - /// which is always 0. - INST(ThisPointerDecoration, this_ptr, 1, 0) - - /// A `[format(f)]` decoration specifies that the format of an image should be `f` INST(FormatDecoration, format, 1, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index fcefa8b26..f3a0688a7 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -165,8 +165,6 @@ IR_SIMPLE_DECORATION(VulkanCallablePayloadDecoration) /// vulkan hit attributes, and should have a location assigned /// to it. IR_SIMPLE_DECORATION(VulkanHitAttributesDecoration) -IR_SIMPLE_DECORATION(ThisPointerDecoration) - struct IRRequireGLSLVersionDecoration : IRDecoration { @@ -1432,6 +1430,11 @@ struct IRWitnessTable : IRInst return IRInstList<IRWitnessTableEntry>(getChildren()); } + IRInst* getConformanceType() + { + return getOperand(0); + } + IR_LEAF_ISA(WitnessTable) }; @@ -1572,6 +1575,7 @@ struct IRBuilder IRBasicType* getIntType(); IRStringType* getStringType(); IRAssociatedType* getAssociatedType(); + IRThisType* getThisType(); IRRawPointerType* getRawPointerType(); @@ -2167,11 +2171,6 @@ struct IRBuilder addDecoration(value, kIROp_LoopControlDecoration, getIntValue(getIntType(), IRIntegerValue(mode))); } - void addThisPointerDecoration(IRInst* value, int paramIndex) - { - addDecoration(value, kIROp_ThisPointerDecoration, getIntValue(getIntType(), paramIndex)); - } - void addSemanticDecoration(IRInst* value, UnownedStringSlice const& text, int index = 0) { addDecoration(value, kIROp_SemanticDecoration, getStringValue(text), getIntValue(getIntType(), index)); diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp index c374f45fa..774836e29 100644 --- a/source/slang/slang-ir-lower-generics.cpp +++ b/source/slang/slang-ir-lower-generics.cpp @@ -52,6 +52,7 @@ namespace Slang return true; switch (typeInst->op) { + case kIROp_ThisType: case kIROp_AssociatedType: case kIROp_InterfaceType: return true; diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 8cf7ab171..ef5ecb959 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -2200,6 +2200,11 @@ namespace Slang return (IRAssociatedType*)getType(kIROp_AssociatedType); } + IRThisType* IRBuilder::getThisType() + { + return (IRThisType*)getType(kIROp_ThisType); + } + IRRawPointerType* IRBuilder::getRawPointerType() { return (IRRawPointerType*)getType(kIROp_RawPointerType); diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 54658980d..dadcce386 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -1200,6 +1200,11 @@ struct IRAssociatedType : IRType IR_LEAF_ISA(AssociatedType) }; +struct IRThisType : IRType +{ + IR_LEAF_ISA(ThisType) +}; + 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 5bd983cab..ebc2e1b74 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -380,6 +380,9 @@ struct IRGenContext // might be insufficient. LoweredValInfo thisVal; + // The IRType value to lower into for `ThisType`. + IRInst* thisType = nullptr; + explicit IRGenContext(SharedIRGenContext* inShared, ASTBuilder* inAstBuilder) : shared(inShared) , astBuilder(inAstBuilder) @@ -1582,6 +1585,8 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower // // For now we punt and emit the `ThisType` of an interface `IFoo` as `IFoo`. // + if (context->thisType != nullptr) + return LoweredValInfo::simple(context->thisType); return emitDeclRef(context, type->interfaceDeclRef, getBuilder()->getTypeKind()); } @@ -5068,6 +5073,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> subContextStorage.irBuilder = &subBuilderStorage; subContextStorage.env = &subEnvStorage; + + subContextStorage.thisType = outerContext->thisType; } IRBuilder* getBuilder() { return &subBuilderStorage; } @@ -5292,12 +5299,38 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> NestedContext nestedContext(this); auto subBuilder = nestedContext.getBuilder(); auto subContext = nestedContext.getContext(); + + // Emit any generics that should wrap the actual type. + auto outerGeneric = emitOuterGenerics(subContext, decl, decl); + + // Setup subContext for proper lowering `ThisType`, associated types and + // the interface decl's self reference. + subContext->thisType = getBuilder()->getThisType(); + // Create a temporary IR value for self references, this will be replaced + // by actual interface type after we create the actual interface type. + auto temporarySelf = subBuilder->createIntrinsicInst(nullptr, kIROp_undefined, 0, nullptr); + subContext->env->mapDeclToValue[decl] = LoweredValInfo::simple(temporarySelf); + for (auto member : decl->members) + { + if (as<AssocTypeDecl>(member)) + { + subContext->env->mapDeclToValue[member] = getBuilder()->getAssociatedType(); + } + } + List<IRInterfaceRequirementEntry*> requirementEntries; for (auto requirementDecl : decl->members) { auto key = getInterfaceRequirementKey(requirementDecl); - auto entry = subBuilder->createInterfaceRequirementEntry(key, nullptr); + IRInst* requirementVal = lowerDecl(subContext, requirementDecl).val; + if (requirementVal) + { + auto reqType = requirementVal->getFullType(); + requirementVal->removeAndDeallocate(); + requirementVal = reqType; + } + auto entry = subBuilder->createInterfaceRequirementEntry(key, requirementVal); requirementEntries.add(entry); // As a special case, any type constraints placed // on an associated type will *also* need to be turned @@ -5312,11 +5345,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> getBuilder()->getWitnessTableType(lowerType(context, constraintDecl->getSup().type)))); } } + context->env->mapDeclToValue[requirementDecl] = LoweredValInfo::simple(entry); } - // Emit any generics that should wrap the actual type. - auto outerGeneric = emitOuterGenerics(subContext, decl, decl); - IRInterfaceType* irInterface = subBuilder->createInterfaceType( requirementEntries.getCount(), reinterpret_cast<IRInst**>(requirementEntries.getBuffer())); @@ -5330,8 +5361,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> addTargetIntrinsicDecorations(irInterface, decl); - - return LoweredValInfo::simple(finishOuterGenerics(subBuilder, irInterface, outerGeneric)); + auto finalVal = finishOuterGenerics(subBuilder, irInterface, outerGeneric); + // Now we can replace all self references in the requirement types to the + // actual interface type we generated. + temporarySelf->replaceUsesWith(finalVal); + temporarySelf->removeAndDeallocate(); + return LoweredValInfo::simple(finalVal); } LoweredValInfo visitEnumCaseDecl(EnumCaseDecl* decl) @@ -6133,8 +6168,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> paramTypes.getBuffer(), irResultType); - if (parameterLists.params.getCount() && parameterLists.params[0].isThisParam) - builder->addThisPointerDecoration(irFuncType, 0); return irFuncType; } @@ -6326,7 +6359,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> if (paramInfo.isThisParam) { subContext->thisVal = paramVal; - subBuilder->addThisPointerDecoration(irParam, (int)(paramTypeIndex - 1)); } } @@ -6548,44 +6580,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> genericVal->setFullType((IRType*)funcType); } - maybeAssociateToInterfaceType(decl, finalVal); - return LoweredValInfo::simple(finalVal); } - void maybeAssociateToInterfaceType(Decl* decl, IRInst* irFuncVal) - { - auto parent = decl->parentDecl; - InterfaceDecl* interfaceDecl = nullptr; - while (parent) - { - interfaceDecl = as<InterfaceDecl>(parent); - if (interfaceDecl) break; - parent = parent->parentDecl; - } - if (!interfaceDecl) - return; - auto loweredVal = context->findLoweredDecl(interfaceDecl); - if (!loweredVal) - { - return; - } - IRInst* irFuncType = irFuncVal->typeUse.get(); - auto irInterfaceType = cast<IRInterfaceType>(loweredVal->val); - auto key = getInterfaceRequirementKey(decl); - for (UInt i = 0; i < irInterfaceType->getOperandCount(); i++) - { - auto operand = cast<IRInterfaceRequirementEntry>(irInterfaceType->getOperand(i)); - if (operand->getRequirementKey() == key) - { - operand->setRequirementVal(irFuncType); - return; - } - } - SLANG_UNREACHABLE("associating interface function declaration:" - "requirement not found in the interface type."); - } - LoweredValInfo visitGenericDecl(GenericDecl * genDecl) { // TODO: Should this just always visit/lower the inner decl? |
