// slang-linkable-impl.h #pragma once // // This file declares various implementations of linkable // objects (subclasses of `ComponentType`). // // Note that the base `ComponentType` class is declared // in `slang-linkable.h`. // // Note that the most important two classes of linkable // objects, `Module`s and `EntryPoint`s, have their own // headers: `slang-module.h` and `slang-entry-point.h`, // respectively. // #include "slang-entry-point.h" #include "slang-linkable.h" #include "slang-module.h" namespace Slang { /// A component type built up from other component types. class CompositeComponentType : public ComponentType { public: static RefPtr create( Linkage* linkage, List> const& childComponents); virtual void buildHash(DigestBuilder& builder) SLANG_OVERRIDE; List> const& getChildComponents() { return m_childComponents; }; Index getChildComponentCount() { return m_childComponents.getCount(); } RefPtr getChildComponent(Index index) { return m_childComponents[index]; } Index getEntryPointCount() SLANG_OVERRIDE; RefPtr getEntryPoint(Index index) SLANG_OVERRIDE; String getEntryPointMangledName(Index index) SLANG_OVERRIDE; String getEntryPointNameOverride(Index index) SLANG_OVERRIDE; Index getShaderParamCount() SLANG_OVERRIDE; ShaderParamInfo getShaderParam(Index index) SLANG_OVERRIDE; SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE; SpecializationParam const& getSpecializationParam(Index index) SLANG_OVERRIDE; Index getRequirementCount() SLANG_OVERRIDE; RefPtr getRequirement(Index index) SLANG_OVERRIDE; List const& getModuleDependencies() SLANG_OVERRIDE; List const& getFileDependencies() SLANG_OVERRIDE; class CompositeSpecializationInfo : public SpecializationInfo { public: List> childInfos; }; protected: void acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) SLANG_OVERRIDE; RefPtr _validateSpecializationArgsImpl( SpecializationArg const* args, Index argCount, Index& outConsumedArgCount, DiagnosticSink* sink) SLANG_OVERRIDE; public: CompositeComponentType(Linkage* linkage, List> const& childComponents); private: List> m_childComponents; // The following arrays hold the concatenated entry points, parameters, // etc. from the child components. This approach allows for reasonably // fast (constant time) access through operations like `getShaderParam`, // but means that the memory usage of a composite is proportional to // the sum of the memory usage of the children, rather than being fixed // by the number of children (as it would be if we just stored // `m_childComponents`). // // TODO: We could conceivably build some O(numChildren) arrays that // support binary-search to provide logarithmic-time access to entry // points, parameters, etc. while giving a better overall memory usage. // List m_entryPoints; List m_entryPointMangledNames; List m_entryPointNameOverrides; List m_shaderParams; List m_specializationParams; List m_requirements; ModuleDependencyList m_moduleDependencyList; FileDependencyList m_fileDependencyList; }; /// A component type created by specializing another component type. class SpecializedComponentType : public ComponentType { public: SpecializedComponentType( ComponentType* base, SpecializationInfo* specializationInfo, List const& specializationArgs, DiagnosticSink* sink); virtual void buildHash(DigestBuilder& builer) SLANG_OVERRIDE; /// Get the base (unspecialized) component type that is being specialized. RefPtr getBaseComponentType() { return m_base; } RefPtr getSpecializationInfo() { return m_specializationInfo; } /// Get the number of arguments supplied for existential type parameters. /// /// Note that the number of arguments may not match the number of parameters. /// In particular, an unspecialized entry point may have many parameters, but zero arguments. Index getSpecializationArgCount() { return m_specializationArgs.getCount(); } /// Get the existential type argument (type and witness table) at `index`. SpecializationArg const& getSpecializationArg(Index index) { return m_specializationArgs[index]; } /// Get an array of all existential type arguments. SpecializationArg const* getSpecializationArgs() { return m_specializationArgs.getBuffer(); } Index getEntryPointCount() SLANG_OVERRIDE { return m_base->getEntryPointCount(); } RefPtr getEntryPoint(Index index) SLANG_OVERRIDE { return m_base->getEntryPoint(index); } String getEntryPointMangledName(Index index) SLANG_OVERRIDE; String getEntryPointNameOverride(Index index) SLANG_OVERRIDE; Index getShaderParamCount() SLANG_OVERRIDE { return m_base->getShaderParamCount(); } ShaderParamInfo getShaderParam(Index index) SLANG_OVERRIDE { return m_base->getShaderParam(index); } SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE { return 0; } SpecializationParam const& getSpecializationParam(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); static SpecializationParam dummy; return dummy; } Index getRequirementCount() SLANG_OVERRIDE; RefPtr getRequirement(Index index) SLANG_OVERRIDE; List const& getModuleDependencies() SLANG_OVERRIDE { return m_moduleDependencies; } List const& getFileDependencies() SLANG_OVERRIDE { return m_fileDependencies; } RefPtr getIRModule() { return m_irModule; } void acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) SLANG_OVERRIDE; protected: RefPtr _validateSpecializationArgsImpl( SpecializationArg const* args, Index argCount, Index& outConsumedArgCount, DiagnosticSink* sink) SLANG_OVERRIDE { SLANG_UNUSED(args); SLANG_UNUSED(argCount); SLANG_UNUSED(sink); outConsumedArgCount = 0; return nullptr; } private: RefPtr m_base; RefPtr m_specializationInfo; SpecializationArgs m_specializationArgs; RefPtr m_irModule; List m_entryPointMangledNames; List m_entryPointNameOverrides; List m_moduleDependencies; List m_fileDependencies; List> m_requirements; }; class RenamedEntryPointComponentType : public ComponentType { public: using Super = ComponentType; RenamedEntryPointComponentType(ComponentType* base, String newName); ComponentType* getBase() { return m_base.Ptr(); } // Forward `IComponentType` methods SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() SLANG_OVERRIDE { return Super::getSession(); } SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout(SlangInt targetIndex, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getLayout(targetIndex, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL specialize( slang::SpecializationArg const* specializationArgs, SlangInt specializationArgCount, slang::IComponentType** outSpecializedComponentType, ISlangBlob** outDiagnostics) SLANG_OVERRIDE { return Super::specialize( specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint(const char* newName, slang::IComponentType** outEntryPoint) SLANG_OVERRIDE { return Super::renameEntryPoint(newName, outEntryPoint); } SLANG_NO_THROW SlangResult SLANG_MCALL link(slang::IComponentType** outLinkedComponentType, ISlangBlob** outDiagnostics) SLANG_OVERRIDE { return Super::link(outLinkedComponentType, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( int entryPointIndex, int targetIndex, ISlangSharedLibrary** outSharedLibrary, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointHostCallable( entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); } List const& getModuleDependencies() SLANG_OVERRIDE { return m_base->getModuleDependencies(); } List const& getFileDependencies() SLANG_OVERRIDE { return m_base->getFileDependencies(); } SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE { return m_base->getSpecializationParamCount(); } SpecializationParam const& getSpecializationParam(Index index) SLANG_OVERRIDE { return m_base->getSpecializationParam(index); } Index getRequirementCount() SLANG_OVERRIDE { return m_base->getRequirementCount(); } RefPtr getRequirement(Index index) SLANG_OVERRIDE { return m_base->getRequirement(index); } Index getEntryPointCount() SLANG_OVERRIDE { return m_base->getEntryPointCount(); } RefPtr getEntryPoint(Index index) SLANG_OVERRIDE { return m_base->getEntryPoint(index); } String getEntryPointMangledName(Index index) SLANG_OVERRIDE { return m_base->getEntryPointMangledName(index); } String getEntryPointNameOverride(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); SLANG_ASSERT(index == 0); return m_entryPointNameOverride; } Index getShaderParamCount() SLANG_OVERRIDE { return m_base->getShaderParamCount(); } ShaderParamInfo getShaderParam(Index index) SLANG_OVERRIDE { return m_base->getShaderParam(index); } void acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) SLANG_OVERRIDE; virtual void buildHash(DigestBuilder& builder) SLANG_OVERRIDE; private: RefPtr m_base; String m_entryPointNameOverride; protected: RefPtr _validateSpecializationArgsImpl( SpecializationArg const* args, Index argCount, Index& outConsumedArgCount, DiagnosticSink* sink) SLANG_OVERRIDE { return m_base->_validateSpecializationArgsImpl(args, argCount, outConsumedArgCount, sink); } }; class TypeConformance : public ComponentType, public slang::ITypeConformance { typedef ComponentType Super; public: SLANG_REF_OBJECT_IUNKNOWN_ALL ISlangUnknown* getInterface(const Guid& guid); TypeConformance( Linkage* linkage, SubtypeWitness* witness, Int confomrmanceIdOverride, DiagnosticSink* sink); // Forward `IComponentType` methods SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() SLANG_OVERRIDE { return Super::getSession(); } SLANG_NO_THROW slang::ProgramLayout* SLANG_MCALL getLayout(SlangInt targetIndex, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getLayout(targetIndex, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointCode(entryPointIndex, targetIndex, outCode, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( SlangInt targetIndex, slang::IBlob** outCode, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getTargetCode(targetIndex, outCode, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( SlangInt entryPointIndex, SlangInt targetIndex, slang::IMetadata** outMetadata, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointMetadata( entryPointIndex, targetIndex, outMetadata, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( SlangInt targetIndex, slang::IMetadata** outMetadata, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getTargetMetadata(targetIndex, outMetadata, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCompileResult( SlangInt entryPointIndex, SlangInt targetIndex, slang::ICompileResult** outCompileResult, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointCompileResult( entryPointIndex, targetIndex, outCompileResult, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCompileResult( SlangInt targetIndex, slang::ICompileResult** outCompileResult, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getTargetCompileResult(targetIndex, outCompileResult, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( SlangInt entryPointIndex, SlangInt targetIndex, ISlangMutableFileSystem** outFileSystem) SLANG_OVERRIDE { return Super::getResultAsFileSystem(entryPointIndex, targetIndex, outFileSystem); } SLANG_NO_THROW SlangResult SLANG_MCALL specialize( slang::SpecializationArg const* specializationArgs, SlangInt specializationArgCount, slang::IComponentType** outSpecializedComponentType, ISlangBlob** outDiagnostics) SLANG_OVERRIDE { return Super::specialize( specializationArgs, specializationArgCount, outSpecializedComponentType, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint(const char* newName, slang::IComponentType** outEntryPoint) SLANG_OVERRIDE { return Super::renameEntryPoint(newName, outEntryPoint); } SLANG_NO_THROW SlangResult SLANG_MCALL link(slang::IComponentType** outLinkedComponentType, ISlangBlob** outDiagnostics) SLANG_OVERRIDE { return Super::link(outLinkedComponentType, outDiagnostics); } virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( slang::IComponentType** outLinkedComponentType, uint32_t count, slang::CompilerOptionEntry* entries, ISlangBlob** outDiagnostics) override { return Super::linkWithOptions(outLinkedComponentType, count, entries, outDiagnostics); } SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( int entryPointIndex, int targetIndex, ISlangSharedLibrary** outSharedLibrary, slang::IBlob** outDiagnostics) SLANG_OVERRIDE { return Super::getEntryPointHostCallable( entryPointIndex, targetIndex, outSharedLibrary, outDiagnostics); } SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( SlangInt entryPointIndex, SlangInt targetIndex, slang::IBlob** outHash) SLANG_OVERRIDE { return Super::getEntryPointHash(entryPointIndex, targetIndex, outHash); } virtual void buildHash(DigestBuilder& builder) SLANG_OVERRIDE; List const& getModuleDependencies() SLANG_OVERRIDE; List const& getFileDependencies() SLANG_OVERRIDE; SLANG_NO_THROW Index SLANG_MCALL getSpecializationParamCount() SLANG_OVERRIDE { return 0; } /// Get the existential type parameter at `index`. SpecializationParam const& getSpecializationParam(Index /*index*/) SLANG_OVERRIDE { static SpecializationParam emptyParam; return emptyParam; } Index getRequirementCount() SLANG_OVERRIDE; RefPtr getRequirement(Index index) SLANG_OVERRIDE; Index getEntryPointCount() SLANG_OVERRIDE { return 0; }; RefPtr getEntryPoint(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); return nullptr; } String getEntryPointMangledName(Index /*index*/) SLANG_OVERRIDE { return ""; } String getEntryPointNameOverride(Index /*index*/) SLANG_OVERRIDE { return ""; } Index getShaderParamCount() SLANG_OVERRIDE { return 0; } ShaderParamInfo getShaderParam(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); return ShaderParamInfo(); } SubtypeWitness* getSubtypeWitness() { return m_subtypeWitness; } IRModule* getIRModule() { return m_irModule.Ptr(); } protected: void acceptVisitor(ComponentTypeVisitor* visitor, SpecializationInfo* specializationInfo) SLANG_OVERRIDE; RefPtr _validateSpecializationArgsImpl( SpecializationArg const* args, Index argCount, Index& outConsumedArgCount, DiagnosticSink* sink) SLANG_OVERRIDE; private: SubtypeWitness* m_subtypeWitness; ModuleDependencyList m_moduleDependencyList; FileDependencyList m_fileDependencyList; List> m_requirements; HashSet m_requirementSet; RefPtr m_irModule; Int m_conformanceIdOverride; void addDepedencyFromWitness(SubtypeWitness* witness); }; /// A visitor for use with `ComponentType`s, allowing dispatch over the concrete subclasses. class ComponentTypeVisitor { public: // The following methods should be overriden in a concrete subclass // to customize how it acts on each of the concrete types of component. // // In cases where the application wants to simply "recurse" on a // composite, specialized, or legacy component type it can use // the `visitChildren` methods below. // virtual void visitEntryPoint( EntryPoint* entryPoint, EntryPoint::EntryPointSpecializationInfo* specializationInfo) = 0; virtual void visitModule( Module* module, Module::ModuleSpecializationInfo* specializationInfo) = 0; virtual void visitComposite( CompositeComponentType* composite, CompositeComponentType::CompositeSpecializationInfo* specializationInfo) = 0; virtual void visitSpecialized(SpecializedComponentType* specialized) = 0; virtual void visitTypeConformance(TypeConformance* conformance) = 0; virtual void visitRenamedEntryPoint( RenamedEntryPointComponentType* renamedEntryPoint, EntryPoint::EntryPointSpecializationInfo* specializationInfo) = 0; protected: // These helpers can be used to recurse into the logical children of a // component type, and are useful for the common case where a visitor // only cares about a few leaf cases. // void visitChildren( CompositeComponentType* composite, CompositeComponentType::CompositeSpecializationInfo* specializationInfo); void visitChildren(SpecializedComponentType* specialized); }; } // namespace Slang