From 812e478989e27983b8dea7ab11964de751654ba2 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 4 Jun 2025 13:05:58 -0700 Subject: Make interface types non c-style in Slang2026. (#7260) * Make interface types non c-style. * Make Optional work with autodiff and existential types. * Fix. * patch behind slang 2026. * Fix warnings. * cleanup. * Fix tests. * Fix. * Fix com interface lowering. * Add comment to test. * regenerate command line reference * Add test for passing `none` to autodiff function. * Fix recording of `getDynamicObjectRTTIBytes`. * Fix nested Optional types. --------- Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> --- source/slang/slang-check-shader.cpp | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) (limited to 'source/slang/slang-check-shader.cpp') diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 6a713f412..a57e01a88 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -915,6 +915,51 @@ RefPtr fillRequirements(ComponentType* inComponentType) return componentType; } +bool parseTypeConformanceArgString( + UnownedStringSlice optionString, + UnownedStringSlice& outTypeName, + UnownedStringSlice& outInterfaceName, + Index& outSequentialId) +{ + // The expected format for the type conformance argument is: + // `TypeName:InterfaceName[=SequentialId]` + // + // Where `TypeName` is the name of a concrete type, `InterfaceName` + // is the name of an interface type, and `SequentialId` is an optional + // integer that specifies a sequential ID for the conformance. + // + // If the string does not match this format, we will return false. + + outTypeName = UnownedStringSlice(); + outInterfaceName = UnownedStringSlice(); + outSequentialId = -1; + auto colonPos = optionString.indexOf(':'); + if (colonPos < 0) + { + // If there is no colon, then the string is invalid. + return false; + } + outTypeName = optionString.head(colonPos); + auto interfaceNameStart = colonPos + 1; + auto equalsPos = optionString.indexOf('='); + if (equalsPos < interfaceNameStart) + { + // If there is no equals sign, then the interface name goes to the end of the string. + outInterfaceName = optionString.tail(interfaceNameStart); + } + else + { + // If there is an equals sign, then the interface name goes up to that point. + outInterfaceName = + optionString.subString(interfaceNameStart, equalsPos - interfaceNameStart); + // The sequential ID is the part after the equals sign. + auto sequentialIdString = optionString.tail(equalsPos + 1); + if (SLANG_FAILED(StringUtil::parseInt(sequentialIdString, outSequentialId))) + return false; + } + return true; +} + /// Create a component type to represent the "global scope" of a compile request. /// /// This component type will include all the modules and their global @@ -965,6 +1010,85 @@ RefPtr createUnspecializedGlobalComponentType(FrontEndCompileRequ CompositeComponentType::create(linkage, translationUnitComponentTypes); } + List> conformanceComponents; + + // Find and include all type conformances specified through compiler options. + for (auto conformances : + compileRequest->optionSet.getArray(CompilerOptionName::TypeConformance)) + { + auto stringValue = conformances.stringValue.getUnownedSlice(); + UnownedStringSlice typeName, interfaceName; + Index sequentialId = -1; + if (!parseTypeConformanceArgString(stringValue, typeName, interfaceName, sequentialId)) + { + compileRequest->getSink()->diagnose( + SourceLoc(), + Diagnostics::invalidTypeConformanceOptionString, + stringValue); + continue; + } + auto concreteType = globalComponentType->getTypeFromString( + String(typeName).getBuffer(), + compileRequest->getSink()); + if (!concreteType) + { + compileRequest->getSink()->diagnose( + SourceLoc(), + Diagnostics::invalidTypeConformanceOptionNoType, + stringValue, + typeName); + continue; + } + auto interfaceType = globalComponentType->getTypeFromString( + String(interfaceName).getBuffer(), + compileRequest->getSink()); + if (!interfaceType) + { + compileRequest->getSink()->diagnose( + SourceLoc(), + Diagnostics::invalidTypeConformanceOptionNoType, + stringValue, + interfaceName); + continue; + } + ComPtr conformanceComponent; + ComPtr diagnostics; + compileRequest->getLinkage()->createTypeConformanceComponentType( + (slang::TypeReflection*)concreteType, + (slang::TypeReflection*)interfaceType, + conformanceComponent.writeRef(), + sequentialId, + diagnostics.writeRef()); + if (!conformanceComponent) + { + // If we failed to create the conformance component, then + // we should report the diagnostics that were generated. + // + compileRequest->getSink()->diagnose( + SourceLoc(), + Diagnostics::cannotCreateTypeConformance, + stringValue); + if (diagnostics) + { + compileRequest->getSink()->diagnoseRaw( + Severity::Error, + UnownedStringSlice((char*)diagnostics->getBufferPointer())); + } + continue; + } + conformanceComponents.add(static_cast(conformanceComponent.get())); + } + + if (conformanceComponents.getCount() > 0) + { + // If we found any type conformances, then we will + // create a composite component type that includes + // the global component type and the conformance components. + // + conformanceComponents.add(globalComponentType); + globalComponentType = CompositeComponentType::create(linkage, conformanceComponents); + } + return fillRequirements(globalComponentType); } -- cgit v1.2.3