diff options
| author | Yong He <yonghe@outlook.com> | 2021-10-21 15:51:18 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-21 15:51:18 -0700 |
| commit | 9304c2d04c9bfbae33cc328d404b24aba375aa4f (patch) | |
| tree | 88473d2ca0b03341f84bca17b359ae45c4becfaa /source | |
| parent | 66e319e34b99eff0a8d27be524ab4a831437ac1b (diff) | |
Diagnostic for no type conformance + bug fix. (#1985)
* Diagnostic for no type conformance + bug fix.
* Fixes.
* Fix.
* Include heterogeneous example only with --enable-experimental-projects premake flag
Co-authored-by: Yong He <yhe@nvidia.com>
Co-authored-by: jsmall-nvidia <jsmall@nvidia.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-generics-lowering-context.h | 24 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-generics.cpp | 32 | ||||
| -rw-r--r-- | source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp | 46 |
4 files changed, 74 insertions, 30 deletions
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 2add5792b..897aa9f6f 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -545,6 +545,8 @@ DIAGNOSTIC(51090, Error, cannotGenerateCodeForExternComponentType, "cannot gener DIAGNOSTIC(51091, Error, typeCannotBePlacedInATexture, "type '$0' cannot be placed in a texture.") DIAGNOSTIC(51092, Error, stageDoesntHaveInputWorld, "'$0' doesn't appear to have any input world") +DIAGNOSTIC(50100, Error, noTypeConformancesFoundForInterface, "No type conformances are found for interface '$0'. Code generation for current target requires at least one implementation type present in the linkage.") + DIAGNOSTIC(52000, Error, multiLevelBreakUnsupported, "control flow appears to require multi-level `break`, which Slang does not yet support") DIAGNOSTIC(52001, Warning, dxilNotFound, "dxil shared library not found, so 'dxc' output cannot be signed! Shader code will not be runnable in non-development environments.") diff --git a/source/slang/slang-ir-generics-lowering-context.h b/source/slang/slang-ir-generics-lowering-context.h index 78dd068b8..c875566b0 100644 --- a/source/slang/slang-ir-generics-lowering-context.h +++ b/source/slang/slang-ir-generics-lowering-context.h @@ -103,4 +103,28 @@ namespace Slang // Ptr(RTTIType). bool isTypeValue(IRInst* typeInst); + template<typename TFunc> + void workOnModule(SharedGenericsLoweringContext* sharedContext, const TFunc& func) + { + SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage; + sharedBuilder->module = sharedContext->module; + sharedBuilder->session = sharedContext->module->session; + + sharedContext->addToWorkList(sharedContext->module->getModuleInst()); + + while (sharedContext->workList.getCount() != 0) + { + IRInst* inst = sharedContext->workList.getLast(); + + sharedContext->workList.removeLast(); + sharedContext->workListSet.Remove(inst); + + func(inst); + + for (auto child = inst->getLastChild(); child; child = child->getPrevInst()) + { + sharedContext->addToWorkList(child); + } + } + } } diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp index 241827561..95046787a 100644 --- a/source/slang/slang-ir-lower-generics.cpp +++ b/source/slang/slang-ir-lower-generics.cpp @@ -117,6 +117,36 @@ namespace Slang cleanUpInterfaceTypes(sharedContext); } + void checkTypeConformanceExists(SharedGenericsLoweringContext* context) + { + HashSet<IRInst*> implementedInterfaces; + + // Add all interface type that are implemented by at least one type to a set. + for (auto inst : context->module->getGlobalInsts()) + { + if (inst->getOp() == kIROp_WitnessTable) + { + auto interfaceType = cast<IRWitnessTableType>(inst->getDataType())->getConformanceType(); + implementedInterfaces.Add(interfaceType); + } + } + // Check if an interface type has any implementations. + workOnModule(context, [&](IRInst* inst) + { + if (auto lookupWitnessMethod = as<IRLookupWitnessMethod>(inst)) + { + auto witnessTableType = lookupWitnessMethod->getWitnessTable()->getDataType(); + auto interfaceType = cast<IRWitnessTableType>(witnessTableType)->getConformanceType(); + if (!implementedInterfaces.Contains(interfaceType)) + { + context->sink->diagnose(interfaceType->sourceLoc, Diagnostics::noTypeConformancesFoundForInterface, interfaceType); + // Add to set to prevent duplicate diagnostic messages. + implementedInterfaces.Add(interfaceType); + } + } + }); + } + void lowerGenerics( TargetRequest* targetReq, IRModule* module, @@ -127,6 +157,8 @@ namespace Slang sharedContext.module = module; sharedContext.sink = sink; + checkTypeConformanceExists(&sharedContext); + // Replace all `makeExistential` insts with `makeExistentialWithRTTI` // before making any other changes. This is necessary because a parameter of // generic type will be lowered into `AnyValueType`, and after that we can no longer diff --git a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp index 059531107..e2d321ed4 100644 --- a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp +++ b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp @@ -157,44 +157,30 @@ struct AssociatedTypeLookupSpecializationContext { if (inst->getRTTIOperand()->getDataType()->getOp() == kIROp_WitnessTableIDType) { + // If the operand is a witness table id, just return the operand. inst->replaceUsesWith(inst->getRTTIOperand()); inst->removeAndDeallocate(); } - } - - template<typename TFunc> - void workOnModule(const TFunc& func) - { - SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage; - sharedBuilder->module = sharedContext->module; - sharedBuilder->session = sharedContext->module->session; - - sharedContext->addToWorkList(sharedContext->module->getModuleInst()); - - while (sharedContext->workList.getCount() != 0) + else if (inst->getRTTIOperand()->getDataType()->getOp() == kIROp_VectorType) { - IRInst* inst = sharedContext->workList.getLast(); - - sharedContext->workList.removeLast(); - sharedContext->workListSet.Remove(inst); - - func(inst); - if (inst->getOp() == kIROp_lookup_interface_method) - { - processLookupInterfaceMethodInst(cast<IRLookupWitnessMethod>(inst)); - } - - for (auto child = inst->getLastChild(); child; child = child->getPrevInst()) - { - sharedContext->addToWorkList(child); - } + // If the operand is a witness table, it is already replaced with a uint2 + // at this point, where the first element in the uint2 is the id of the + // witneess table. + auto vectorType = inst->getRTTIOperand()->getDataType(); + IRBuilder builder; + builder.sharedBuilder = &sharedContext->sharedBuilderStorage; + builder.setInsertBefore(inst); + UInt index = 0; + auto id = builder.emitSwizzle(as<IRVectorType>(vectorType)->getElementType(), inst->getRTTIOperand(), 1, &index); + inst->replaceUsesWith(id); + inst->removeAndDeallocate(); } } void processModule() { // Replace all `lookup_interface_method():IRWitnessTable` with call to specialized functions. - workOnModule([this](IRInst* inst) + workOnModule(sharedContext, [this](IRInst* inst) { if (inst->getOp() == kIROp_lookup_interface_method) { @@ -203,7 +189,7 @@ struct AssociatedTypeLookupSpecializationContext }); // Replace all direct uses of IRWitnessTables with its sequential ID. - workOnModule([this](IRInst* inst) + workOnModule(sharedContext, [this](IRInst* inst) { if (inst->getOp() == kIROp_WitnessTable) { @@ -252,7 +238,7 @@ struct AssociatedTypeLookupSpecializationContext } // `GetSequentialID(WitnessTableIDOperand)` becomes just `WitnessTableIDOperand`. - workOnModule([this](IRInst* inst) + workOnModule(sharedContext, [this](IRInst* inst) { if (inst->getOp() == kIROp_GetSequentialID) { |
