summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-shader.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-06-04 13:05:58 -0700
committerGitHub <noreply@github.com>2025-06-04 13:05:58 -0700
commit812e478989e27983b8dea7ab11964de751654ba2 (patch)
treee6db6def9c7896ee48c5fe42926856644e81c0e6 /source/slang/slang-check-shader.cpp
parentb9dc21d362f65f22bc707bede733a9537b80460a (diff)
Make interface types non c-style in Slang2026. (#7260)
* Make interface types non c-style. * Make Optional<T> 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>
Diffstat (limited to 'source/slang/slang-check-shader.cpp')
-rw-r--r--source/slang/slang-check-shader.cpp124
1 files changed, 124 insertions, 0 deletions
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<ComponentType> 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<ComponentType> createUnspecializedGlobalComponentType(FrontEndCompileRequ
CompositeComponentType::create(linkage, translationUnitComponentTypes);
}
+ List<RefPtr<ComponentType>> 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<slang::ITypeConformance> conformanceComponent;
+ ComPtr<ISlangBlob> 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<TypeConformance*>(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);
}