From e43ef82e288afe486f45ef2736d378e88f40cc90 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 3 Aug 2022 17:10:46 -0400 Subject: Improvements around Artifact (#2346) * #include an absolute path didn't work - because paths were taken to always be relative. * WIP with hierarchical enums. * Some small fixes and improvements around artifact desc related types. * Improvements around hierarchical enum. * Fixes to get Artifact types refactor to be able to execute tests. * Attempt to better categorize PTX. * Work around for potentially unused function warning. * Typo fix. * Simplify Artifact header. * Small improvements around Artifact kind/payload/style. * Added IDestroyable/ICastable * Add IArtifactList. * First impl of IArtifactUtil. * Use the ICastable interface for IArtifactRepresentation. * Added IArtifactRepresentation & IArtifactAssociated. * Add SLANG_OVERRIDE to avoid gcc/clang warning. * Fix calling convention issue on win32. * Fix missing SLANG_OVERRIDE. --- source/compiler-core/slang-artifact-info.cpp | 326 +++++++++++--------- source/compiler-core/slang-artifact-info.h | 76 +---- source/compiler-core/slang-artifact-util.cpp | 63 ++++ source/compiler-core/slang-artifact-util.h | 65 ++++ source/compiler-core/slang-artifact.cpp | 425 +++++++++++++++++++++++---- source/compiler-core/slang-artifact.h | 296 +++++++++++++------ source/core/slang-destroyable.h | 41 +++ source/slang/slang-compiler.cpp | 4 +- source/slang/slang-ir-link.cpp | 2 +- source/slang/slang-module-library.cpp | 22 +- source/slang/slang-module-library.h | 10 +- source/slang/slang-options.cpp | 6 +- source/slang/slang-parameter-binding.cpp | 2 +- source/slang/slang-type-layout.cpp | 2 +- source/slang/slang.cpp | 6 +- 15 files changed, 993 insertions(+), 353 deletions(-) create mode 100644 source/compiler-core/slang-artifact-util.cpp create mode 100644 source/compiler-core/slang-artifact-util.h create mode 100644 source/core/slang-destroyable.h (limited to 'source') diff --git a/source/compiler-core/slang-artifact-info.cpp b/source/compiler-core/slang-artifact-info.cpp index b67adb666..f76bf45f0 100644 --- a/source/compiler-core/slang-artifact-info.cpp +++ b/source/compiler-core/slang-artifact-info.cpp @@ -6,86 +6,8 @@ namespace Slang { -static ArtifactPayloadInfo::Lookup _makePayloadInfoLookup() -{ - ArtifactPayloadInfo::Lookup values; - memset(&values, 0, sizeof(values)); - - - typedef ArtifactPayload Payload; - typedef ArtifactPayloadInfo::Flag Flag; - typedef ArtifactPayloadInfo::Flags Flags; - typedef ArtifactPayloadInfo::Flavor Flavor; - - struct Info - { - Payload payload; - Flavor flavor; - Flags flags; - }; - - const Info infos[] = - { - {Payload::None, Flavor::None, 0}, - {Payload::Unknown, Flavor::Unknown, 0}, - - // It seems as if DXBC is potentially linkable from - // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-keywords#export - - // We can't *actually* link PTX or SPIR-V currently but it is in principal possible - // so let's say we accept for now - - {Payload::DXIL, Flavor::Binary, Flag::IsGpuNative | Flag::IsLinkable}, - {Payload::DXBC, Flavor::Binary, Flag::IsGpuNative | Flag::IsLinkable}, - {Payload::SPIRV, Flavor::Binary, Flag::IsGpuNative | Flag::IsLinkable }, - {Payload::PTX, Flavor::Binary, Flag::IsGpuNative | Flag::IsLinkable }, - - {Payload::DXILAssembly, Flavor::Assembly, 0}, - {Payload::DXBCAssembly, Flavor::Assembly, 0}, - {Payload::SPIRVAssembly, Flavor::Assembly, 0}, - {Payload::PTXAssembly, Flavor::Assembly, 0}, - - {Payload::HostCPU, Flavor::Binary, Flag::IsCpuNative | Flag::IsLinkable}, - - // Do we want some other Flavor for these? - {Payload::SlangIR, Flavor::Binary, Flag::IsLinkable}, - {Payload::LLVMIR, Flavor::Binary, 0}, - {Payload::SlangAST, Flavor::Binary, 0}, - - {Payload::X86, Flavor::Binary, Flag::IsCpuNative | Flag::IsLinkable}, - {Payload::X86_64, Flavor::Binary, Flag::IsCpuNative | Flag::IsLinkable}, - {Payload::AARCH, Flavor::Binary, Flag::IsCpuNative | Flag::IsLinkable}, - {Payload::AARCH64, Flavor::Binary, Flag::IsCpuNative | Flag::IsLinkable}, - - {Payload::HLSL, Flavor::Source, 0}, - {Payload::GLSL, Flavor::Source, 0}, - {Payload::CPP, Flavor::Source, 0}, - {Payload::C, Flavor::Source, 0}, - {Payload::CUDA, Flavor::Source, 0}, - {Payload::Slang, Flavor::Source, 0}, - - {Payload::DebugInfo, Flavor::Unknown, 0}, - - {Payload::Diagnostics, Flavor::Unknown, 0}, - - {Payload::Zip, Flavor::Container, 0}, - }; - - for (auto info : infos) - { - auto& v = values.values[Index(info.payload)]; - v.flavor = info.flavor; - v.flags = info.flags; - } - - return values; -} - -/* static */const ArtifactPayloadInfo::Lookup ArtifactPayloadInfo::Lookup::g_values = _makePayloadInfoLookup(); - /* !!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactInfoUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ - namespace { // anonymous struct KindExtension { @@ -95,7 +17,7 @@ struct KindExtension } // anonymous #define SLANG_KIND_EXTENSION(kind, ext) \ - { ArtifactKind::kind, UnownedStringSlice::fromLiteral(ext) }, + { ArtifactKind::kind, toSlice(ext) }, static const KindExtension g_cpuKindExts[] = { @@ -120,6 +42,41 @@ static const KindExtension g_cpuKindExts[] = #endif }; +/* static */ bool ArtifactInfoUtil::isCpuBinary(const ArtifactDesc& desc) +{ + return isDerivedFrom(desc.kind, ArtifactKind::BinaryLike) && isDerivedFrom(desc.payload, ArtifactPayload::CPULike); +} + +/* static */bool ArtifactInfoUtil::isText(const ArtifactDesc& desc) +{ + // If it's derived from text... + if (isDerivedFrom(desc.kind, ArtifactKind::Text)) + { + return true; + } + + // Special case PTX... + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) + { + return desc.payload == ArtifactPayload::PTX; + } + + // Not text + return false; +} + +/* static */bool ArtifactInfoUtil::isGpuUsable(const ArtifactDesc& desc) +{ + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) + { + return isDerivedFrom(desc.payload, ArtifactPayload::KernelLike); + } + + // PTX is a kind of special case, it's an 'assembly' (low level text represention) that can be passed + // to CUDA runtime + return desc.kind == ArtifactKind::Assembly && desc.payload == ArtifactPayload::PTX; +} + /* static */bool ArtifactInfoUtil::isKindBinaryLinkable(Kind kind) { switch (kind) @@ -134,71 +91,53 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */bool ArtifactInfoUtil::isBinaryLinkable(const ArtifactDesc& desc) +/* static */bool ArtifactInfoUtil::isLinkable(const ArtifactDesc& desc) { - return isKindBinaryLinkable(desc.kind) && - getInfo(desc.payload).isSet(ArtifactPayloadInfo::Flag::IsLinkable); -} + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) + { + if (isDerivedFrom(desc.payload, ArtifactPayload::KernelLike)) + { + // It seems as if DXBC is potentially linkable from + // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-keywords#export -/* static */bool ArtifactInfoUtil::isPayloadCpuBinary(Payload payload) -{ - auto info = getInfo(payload); - return info.isSet(ArtifactPayloadInfo::Flag::IsCpuNative) && info.flavor == ArtifactPayloadInfo::Flavor::Binary; -} + // We can't *actually* link PTX or SPIR-V currently but it is in principal possible + // so let's say we accept for now -/* static */bool ArtifactInfoUtil::isPayloadGpuBinary(Payload payload) -{ - auto info = getInfo(payload); - return info.isSet(ArtifactPayloadInfo::Flag::IsGpuNative) && info.flavor == ArtifactPayloadInfo::Flavor::Binary; -} + return true; + } + else if (isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + // If kind is exe or shared library, linking will arguably not work + if (desc.kind == ArtifactKind::SharedLibrary || + desc.kind == ArtifactKind::Executable) + { + return false; + } -/* static */bool ArtifactInfoUtil::isPayloadCpuTarget(Payload payload) -{ - return isPayloadCpuBinary(payload) || - (payload == Payload::C || payload == Payload::CPP); + return true; + } + else if (isDerivedFrom(desc.payload, ArtifactPayload::GeneralIR)) + { + // We'll *assume* IR is linkable + return true; + } + } + return false; } -/* static */UnownedStringSlice ArtifactInfoUtil::getDefaultExtensionForPayload(Payload payload) +/* static */bool ArtifactInfoUtil::isCpuLikeTarget(const ArtifactDesc& desc) { - switch (payload) - { - case Payload::None: return UnownedStringSlice(); - case Payload::Unknown: return UnownedStringSlice::fromLiteral("unknown"); - - case Payload::DXIL: return UnownedStringSlice::fromLiteral("dxil"); - case Payload::DXBC: return UnownedStringSlice::fromLiteral("dxbc"); - case Payload::SPIRV: return UnownedStringSlice::fromLiteral("spirv"); - - case Payload::PTX: return UnownedStringSlice::fromLiteral("ptx"); - - case Payload::X86: - case Payload::X86_64: - case Payload::AARCH: - case Payload::AARCH64: - case Payload::HostCPU: + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) { - return UnownedStringSlice(); + return isDerivedFrom(desc.payload, ArtifactPayload::CPULike); } - - case Payload::SlangIR: return UnownedStringSlice::fromLiteral("slang-ir"); - case Payload::LLVMIR: return UnownedStringSlice::fromLiteral("llvm-ir"); - - case Payload::HLSL: return UnownedStringSlice::fromLiteral("hlsl"); - case Payload::GLSL: return UnownedStringSlice::fromLiteral("glsl"); - - case Payload::CPP: return UnownedStringSlice::fromLiteral("cpp"); - case Payload::C: return UnownedStringSlice::fromLiteral("c"); - - case Payload::CUDA: return UnownedStringSlice::fromLiteral("cu"); - - case Payload::Slang: return UnownedStringSlice::fromLiteral("slang"); - - case Payload::Zip: return UnownedStringSlice::fromLiteral("zip"); - - default: break; + else if (isDerivedFrom(desc.kind, ArtifactKind::Source)) + { + // We'll assume C/C++ are targetting CPU, although that is perhaps somewhat arguable. + return desc.payload == Payload::C || desc.payload == Payload::Cpp; } - SLANG_UNEXPECTED("Unknown content type"); + return false; } /* static */ArtifactDesc ArtifactInfoUtil::getDescFromExtension(const UnownedStringSlice& slice) @@ -209,6 +148,32 @@ static const KindExtension g_cpuKindExts[] = return ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); } + // Metal + // https://developer.apple.com/documentation/metal/shader_libraries/building_a_library_with_metal_s_command-line_tools + if (slice == toSlice("air")) + { + return ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::MetalAIR); + } + else if (slice == toSlice("metallib") || slice == toSlice("metalar")) + { + return ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::MetalAIR); + } + + if (slice == toSlice("zip")) + { + return ArtifactDesc::make(ArtifactKind::Zip, ArtifactPayload::Unknown); + } + else if (slice == toSlice("riff")) + { + return ArtifactDesc::make(ArtifactKind::Riff, ArtifactPayload::Unknown); + } + + if (slice == toSlice("asm")) + { + // We'll assume asm means current CPU assembler.. + return ArtifactDesc::make(ArtifactKind::Assembly, ArtifactPayload::HostCPU); + } + for (const auto& kindExt : g_cpuKindExts) { if (slice == kindExt.ext) @@ -241,16 +206,105 @@ static const KindExtension g_cpuKindExts[] = return UnownedStringSlice(); } +UnownedStringSlice ArtifactInfoUtil::getAssemblyExtensionForPayload(ArtifactPayload payload) +{ + switch (payload) + { + case ArtifactPayload::DXIL: return toSlice("dxil-asm"); + case ArtifactPayload::DXBC: return toSlice("dxbc-asm"); + case ArtifactPayload::SPIRV: return toSlice("spv-asm"); + case ArtifactPayload::PTX: return toSlice("ptx"); + + // TODO(JS): + // Not sure what to do for metal - does it have an assembly name? + + default: break; + } + + // We'll just use asm for all CPU assembly type + if (isDerivedFrom(payload, ArtifactPayload::CPULike)) + { + return toSlice("asm"); + } + + if (isDerivedFrom(payload, ArtifactPayload::GeneralIR)) + { + switch (payload) + { + case ArtifactPayload::SlangIR: return toSlice("slang-ir-asm"); + case ArtifactPayload::LLVMIR: return toSlice("llvm-ir-asm"); + break; + } + } + + return UnownedStringSlice(); +} + UnownedStringSlice ArtifactInfoUtil::getDefaultExtension(const ArtifactDesc& desc) { - if (ArtifactInfoUtil::isPayloadCpuBinary(desc.payload)) + switch (desc.kind) + { + case ArtifactKind::Zip: return toSlice("zip"); + case ArtifactKind::Riff: return toSlice("riff"); + case ArtifactKind::Assembly: + { + return getAssemblyExtensionForPayload(desc.payload); + } + case ArtifactKind::Source: + { + switch (desc.payload) + { + case Payload::HLSL: return toSlice("hlsl"); + case Payload::GLSL: return toSlice("glsl"); + + case Payload::Cpp: return toSlice("cpp"); + case Payload::C: return toSlice("c"); + + case Payload::Metal: return toSlice("metal"); + + case Payload::CUDA: return toSlice("cu"); + + case Payload::Slang: return toSlice("slang"); + default: break; + } + } + default: break; + } + + if (ArtifactInfoUtil::isCpuLikeTarget(desc)) { return getCpuExtensionForKind(desc.kind); } - else + + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike)) { - return getDefaultExtensionForPayload(desc.payload); + switch (desc.payload) + { + case Payload::None: return UnownedStringSlice(); + case Payload::Unknown: return toSlice("unknown"); + + case Payload::DXIL: return toSlice("dxil"); + case Payload::DXBC: return toSlice("dxbc"); + case Payload::SPIRV: return toSlice("spv"); + + case Payload::PTX: return toSlice("ptx"); + + case Payload::LLVMIR: return toSlice("llvm-ir"); + + case Payload::SlangIR: + { + return (desc.kind == ArtifactKind::Library) ? toSlice("slang-module") : toSlice("slang-ir"); + } + case Payload::MetalAIR: + { + // https://developer.apple.com/documentation/metal/shader_libraries/building_a_library_with_metal_s_command-line_tools + return (desc.kind == ArtifactKind::Library) ? toSlice("metallib") : toSlice("air"); + } + default: break; + } } + + return UnownedStringSlice(); } /* static */String ArtifactInfoUtil::getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path) diff --git a/source/compiler-core/slang-artifact-info.h b/source/compiler-core/slang-artifact-info.h index e63349937..393771a6f 100644 --- a/source/compiler-core/slang-artifact-info.h +++ b/source/compiler-core/slang-artifact-info.h @@ -7,53 +7,6 @@ namespace Slang { -/* We want to centralize information about artifact descs and related types, such that when new types are added they only need -to be added/altered in one place */ -struct ArtifactPayloadInfo -{ - typedef ArtifactPayloadInfo This; - enum class Flavor : uint8_t - { - Unknown, - None, - Assembly, - Source, - Container, - Binary, - CountOf, - }; - - typedef uint8_t Flags; - struct Flag - { - enum Enum : Flags - { - IsCpuNative = 0x01, ///< True if is a CPU native type - IsGpuNative = 0x02, ///< True if is a GPU native type - IsLinkable = 0x04, ///< True if in principal is linkable - }; - }; - - bool isSet(Flag::Enum flag) const { return (flags & Flags(flag)) != 0; } - bool isReset(Flag::Enum flag) const { return (flags & Flags(flag)) == 0; } - - struct Lookup; - - Flags flags; - Flavor flavor; -}; - -struct ArtifactPayloadInfo::Lookup -{ - void setFlag(ArtifactPayload payload, Flag::Enum flag) { values[Index(payload)].flags |= Flags(flag); } - void setFlags(ArtifactPayload payload, Flags flags) { values[Index(payload)].flags |= flags; } - - This values[Index(ArtifactPayload::CountOf)]; - static const Lookup g_values; -}; - -SLANG_FORCE_INLINE ArtifactPayloadInfo getInfo(ArtifactPayload payload) { return ArtifactPayloadInfo::Lookup::g_values.values[Index(payload)]; } - struct ArtifactInfoUtil { typedef ArtifactPayload Payload; @@ -62,27 +15,22 @@ struct ArtifactInfoUtil /// Returns true if the kind is binary linkable static bool isKindBinaryLinkable(Kind kind); - /// Returns true if the payload type is CPU - static bool isPayloadCpuBinary(Payload payload); - /// Returns true if the payload type is applicable to the GPU - static bool isPayloadGpuBinary(Payload payload); - - /// True if is a CPU target - static bool isPayloadCpuTarget(Payload payload); - /// True if is a CPU target - either - static bool isCpuTarget(const ArtifactDesc& desc) { return isPayloadCpuTarget(desc.payload); } - + static bool isCpuLikeTarget(const ArtifactDesc& desc); + /// True if is a CPU binary - static bool isCpuBinary(const ArtifactDesc& desc) { return isPayloadCpuBinary(desc.payload); } - /// True if is a GPU binary - static bool isGpuBinary(const ArtifactDesc& desc) { return isPayloadGpuBinary(desc.payload); } + static bool isCpuBinary(const ArtifactDesc& desc); + /// True if is a GPU usable (can be passed to a driver/API and be used + static bool isGpuUsable(const ArtifactDesc& desc); + + /// True if the desc holds textual information + static bool isText(const ArtifactDesc& desc); - /// True if artifact appears to be binary linkable - static bool isBinaryLinkable(const ArtifactDesc& desc); + /// Given an assembly type returns it's extension from the payload type + static UnownedStringSlice getAssemblyExtensionForPayload(ArtifactPayload payload); - /// Get the default extension type for a payload type - static UnownedStringSlice getDefaultExtensionForPayload(Payload payload); + /// True if artifact appears to be linkable + static bool isLinkable(const ArtifactDesc& desc); /// Try to determine the desc from just a file extension (passed without .) static ArtifactDesc getDescFromExtension(const UnownedStringSlice& slice); diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp new file mode 100644 index 000000000..3ca10446c --- /dev/null +++ b/source/compiler-core/slang-artifact-util.cpp @@ -0,0 +1,63 @@ +// slang-artifact.cpp +#include "slang-artifact-util.h" + +#include "slang-artifact-info.h" + +namespace Slang { + +/* static */ArtifactUtilImpl ArtifactUtilImpl::g_singleton; + +SlangResult ArtifactUtilImpl::queryInterface(SlangUUID const& uuid, void** outObject) +{ + if (auto intf = getInterface(uuid)) + { + *outObject = intf; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; +} + +void* ArtifactUtilImpl::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || guid == IArtifactUtil::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + + +SlangResult ArtifactUtilImpl::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +{ + String name; + if (inName) + { + name = inName; + } + + ComPtr artifact(new Artifact(desc, name)); + + *outArtifact = artifact.detach(); + return SLANG_OK; +} + +SlangResult ArtifactUtilImpl::createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) +{ + ComPtr artifactList(new ArtifactList(parent)); + *outArtifactList = artifactList.detach(); + return SLANG_OK; +} + +ArtifactKind ArtifactUtilImpl::getKindParent(ArtifactKind kind) { return getParent(kind); } +UnownedStringSlice ArtifactUtilImpl::getKindName(ArtifactKind kind) { return getName(kind); } +bool ArtifactUtilImpl::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } + +ArtifactPayload ArtifactUtilImpl::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } +UnownedStringSlice ArtifactUtilImpl::getPayloadName(ArtifactPayload payload) { return getName(payload); } +bool ArtifactUtilImpl::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } + +ArtifactStyle ArtifactUtilImpl::getStyleParent(ArtifactStyle style) { return getParent(style); } +UnownedStringSlice ArtifactUtilImpl::getStyleName(ArtifactStyle style) { return getName(style); } +bool ArtifactUtilImpl::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } + +} // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h new file mode 100644 index 000000000..2b006fd78 --- /dev/null +++ b/source/compiler-core/slang-artifact-util.h @@ -0,0 +1,65 @@ +// slang-artifact-util.h +#ifndef SLANG_ARTIFACT_UTIL_H +#define SLANG_ARTIFACT_UTIL_H + +#include "slang-artifact.h" + +namespace Slang +{ + +class IArtifactUtil : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, { 0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20 }) + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) = 0; + + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) = 0; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; +}; + +class ArtifactUtilImpl : public IArtifactUtil +{ + // ISlangUnknown + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + + // IArtifactInterface + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; + + static IArtifactUtil* getSingleton() { return &g_singleton; } + +protected: + void* getInterface(const Guid& guid); + + static ArtifactUtilImpl g_singleton; +}; + +} // namespace Slang + +#endif diff --git a/source/compiler-core/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp index bf61763c8..cb77f5140 100644 --- a/source/compiler-core/slang-artifact.cpp +++ b/source/compiler-core/slang-artifact.cpp @@ -5,9 +5,236 @@ #include "../core/slang-type-text-util.h" #include "../core/slang-io.h" +#include "../core/slang-array-view.h" namespace Slang { +namespace { // anonymous + +struct HierarchicalEnumEntry +{ + Index value; + Index parent; + const char* name; +}; + +static bool _isHierarchicalEnumOk(ConstArrayView entries, Count countOf) +{ + // All values should be set + if (entries.getCount() != countOf) + { + return false; + } + + List isUsed; + isUsed.setCount(countOf); + ::memset(isUsed.getBuffer(), 0, countOf); + + for (const auto& entry : entries) + { + const auto value = entry.value; + // Must be in range + if (value < 0 || value >= countOf) + { + return false; + } + + if (isUsed[value] != 0) + { + return false; + } + // Mark as used + isUsed[value]++; + } + + // There can't be any gaps + for (auto v : isUsed) + { + if (v == 0) + { + return false; + } + } + + // Okay, looks reasonable.. + return true; +} + +template +struct HierarchicalEnumTable +{ + HierarchicalEnumTable(ConstArrayView entries) + { + // Remove warnings around this not being used. + { + const auto unused = _isHierarchicalEnumOk; + SLANG_UNUSED(unused); + } + + SLANG_COMPILE_TIME_ASSERT(Index(T::Invalid) < Index(T::Base)); + SLANG_ASSERT(entries.getCount() == Count(T::CountOf)); + + SLANG_ASSERT(_isHierarchicalEnumOk(entries, Count(T::CountOf))); + + ::memset(&m_parents, 0, sizeof(m_parents)); + + for (const auto& entry : entries) + { + const auto value = entry.value; + m_parents[value] = T(entry.parent); + m_names[value] = UnownedStringSlice(entry.name); + } + + // TODO(JS): NOTE! If we wanted to use parent to indicate if a value was *invalid* + // we would want the Parent of Base to be Base. + // + // Base parent should be invalid + SLANG_ASSERT(getParent(T::Base) == T::Invalid); + // Invalids parent should be invalid + SLANG_ASSERT(getParent(T::Invalid) == T::Invalid); + } + + T getParent(T kind) const + { + return (kind >= T::CountOf) ? + T::Invalid : + m_parents[Index(kind)]; + } + UnownedStringSlice getName(T kind) const + { + return (kind >= T::CountOf) ? + UnownedStringSlice() : + m_names[Index(kind)]; + } + + bool isDerivedFrom(T type, T base) const + { + if (Index(type) >= Index(T::CountOf)) + { + return false; + } + + do + { + if (type == base) + { + return true; + } + type = m_parents[Index(type)]; + } while (Index(type) > Index(T::Base)); + + return false; + } + +protected: + T m_parents[Count(T::CountOf)]; + UnownedStringSlice m_names[Count(T::CountOf)]; +}; + +} // anonymous + +// Macro utils to create "enum hierarchy" tables + +#define SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_ENTRY_MACRO) \ +static ConstArrayView _getEntries##ENUM_TYPE() \ +{ \ + static const HierarchicalEnumEntry values[] = { ENUM_TYPE_MACRO(ENUM_ENTRY_MACRO) }; \ + return makeConstArrayView(values); \ +} + +#define SLANG_HIERARCHICAL_ENUM(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ +SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ +\ +static const HierarchicalEnumTable g_table##ENUM_TYPE(_getEntries##ENUM_TYPE()); \ +\ +ENUM_TYPE getParent(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getParent(kind); } \ +UnownedStringSlice getName(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getName(kind); } \ +bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) { return g_table##ENUM_TYPE.isDerivedFrom(kind, base); } + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactKind !!!!!!!!!!!!!!!!!!!!!!! */ + +#define SLANG_ARTIFACT_KIND(x) \ + x(Invalid, Invalid) \ + x(Base, Invalid) \ + x(None, Base) \ + x(Unknown, Base) \ + x(Container, Base) \ + x(Zip, Container) \ + x(Riff, Container) \ + x(Text, Base) \ + x(HumanText, Text) \ + x(Source, Text) \ + x(Assembly, Text) \ + x(BinaryLike, Base) \ + x(ObjectCode, BinaryLike) \ + x(Library, BinaryLike) \ + x(Executable, BinaryLike) \ + x(SharedLibrary, BinaryLike) \ + x(HostCallable, BinaryLike) \ + \ + x(DebugInfo, Base) \ + x(Diagnostics, Base) + +#define SLANG_ARTIFACT_KIND_ENTRY(TYPE, PARENT) { Index(ArtifactKind::TYPE), Index(ArtifactKind::PARENT), #TYPE }, + +SLANG_HIERARCHICAL_ENUM(ArtifactKind, SLANG_ARTIFACT_KIND, SLANG_ARTIFACT_KIND_ENTRY) + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactPayload !!!!!!!!!!!!!!!!!!!!!!! */ + +#define SLANG_ARTIFACT_PAYLOAD(x) \ + x(Invalid, Invalid) \ + x(Base, Invalid) \ + x(None, Base) \ + x(Unknown, Base) \ + x(Source, Base) \ + x(C, Source) \ + x(Cpp, Source) \ + x(HLSL, Source) \ + x(GLSL, Source) \ + x(CUDA, Source) \ + x(Metal, Source) \ + x(Slang, Source) \ + x(KernelLike, Base) \ + x(DXIL, KernelLike) \ + x(DXBC, KernelLike) \ + x(SPIRV, KernelLike) \ + x(PTX, KernelLike) \ + x(CuBin, KernelLike) \ + x(MetalAIR, KernelLike) \ + x(CPULike, Base) \ + x(UnknownCPU, CPULike) \ + x(X86, CPULike) \ + x(X86_64, CPULike) \ + x(Aarch, CPULike) \ + x(Aarch64, CPULike) \ + x(HostCPU, CPULike) \ + x(UniversalCPU, CPULike) \ + x(GeneralIR, Base) \ + x(SlangIR, GeneralIR) \ + x(LLVMIR, GeneralIR) \ + x(AST, Base) \ + x(SlangAST, AST) + +#define SLANG_ARTIFACT_PAYLOAD_ENTRY(TYPE, PARENT) { Index(ArtifactPayload::TYPE), Index(ArtifactPayload::PARENT), #TYPE }, + +SLANG_HIERARCHICAL_ENUM(ArtifactPayload, SLANG_ARTIFACT_PAYLOAD, SLANG_ARTIFACT_PAYLOAD_ENTRY) + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactStyle !!!!!!!!!!!!!!!!!!!!!!! */ + +#define SLANG_ARTIFACT_STYLE(x) \ + x(Invalid, Invalid) \ + x(Base, Invalid) \ + x(Unknown, Base) \ + x(Kernel, Base) \ + x(Host, Base) + +#define SLANG_ARTIFACT_STYLE_ENTRY(TYPE, PARENT) { Index(ArtifactStyle::TYPE), Index(ArtifactStyle::PARENT), #TYPE }, + +SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYLE_ENTRY) + + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDesc !!!!!!!!!!!!!!!!!!!!!!! */ + /* static */ArtifactDesc ArtifactDesc::makeFromCompileTarget(SlangCompileTarget target) { switch (target) @@ -20,31 +247,106 @@ namespace Slang { { // For the moment we make all just map to GLSL, but we could use flags // or some other mechanism to distinguish the types - return make(Kind::Text, Payload::GLSL, Style::Kernel, 0); + return make(Kind::Source, Payload::GLSL, Style::Kernel, 0); } - case SLANG_HLSL: return make(Kind::Text, Payload::HLSL, Style::Kernel, 0); + case SLANG_HLSL: return make(Kind::Source, Payload::HLSL, Style::Kernel, 0); case SLANG_SPIRV: return make(Kind::Executable, Payload::SPIRV, Style::Kernel, 0); - case SLANG_SPIRV_ASM: return make(Kind::Text, Payload::SPIRVAssembly, Style::Kernel, 0); + case SLANG_SPIRV_ASM: return make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0); case SLANG_DXBC: return make(Kind::Executable, Payload::DXBC, Style::Kernel, 0); - case SLANG_DXBC_ASM: return make(Kind::Text, Payload::DXBCAssembly, Style::Kernel, 0); + case SLANG_DXBC_ASM: return make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0); case SLANG_DXIL: return make(Kind::Executable, Payload::DXIL, Style::Kernel, 0); - case SLANG_DXIL_ASM: return make(Kind::Text, Payload::DXILAssembly, Style::Kernel, 0); - case SLANG_C_SOURCE: return make(Kind::Text, Payload::C, Style::Kernel, 0); - case SLANG_CPP_SOURCE: return make(Kind::Text, Payload::CPP, Style::Kernel, 0); - case SLANG_HOST_CPP_SOURCE: return make(Kind::Text, Payload::CPP, Style::Host, 0); + case SLANG_DXIL_ASM: return make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0); + case SLANG_C_SOURCE: return make(Kind::Source, Payload::C, Style::Kernel, 0); + case SLANG_CPP_SOURCE: return make(Kind::Source, Payload::Cpp, Style::Kernel, 0); + case SLANG_HOST_CPP_SOURCE: return make(Kind::Source, Payload::Cpp, Style::Host, 0); case SLANG_HOST_EXECUTABLE: return make(Kind::Executable, Payload::HostCPU, Style::Host, 0); case SLANG_SHADER_SHARED_LIBRARY: return make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0); - case SLANG_SHADER_HOST_CALLABLE: return make(Kind::Callable, Payload::HostCPU, Style::Kernel, 0); - case SLANG_CUDA_SOURCE: return make(Kind::Text, Payload::CUDA, Style::Kernel, 0); + case SLANG_SHADER_HOST_CALLABLE: return make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0); + case SLANG_CUDA_SOURCE: return make(Kind::Source, Payload::CUDA, Style::Kernel, 0); + // TODO(JS): + // Not entirely clear how best to represent PTX here. We could mark as 'Assembly'. Saying it is + // 'Executable' implies it is Binary (which PTX isn't). Executable also implies 'complete for executation', + // irrespective of it being text. case SLANG_PTX: return make(Kind::Executable, Payload::PTX, Style::Kernel, 0); case SLANG_OBJECT_CODE: return make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0); - case SLANG_HOST_HOST_CALLABLE: return make(Kind::Callable, Payload::HostCPU, Style::Host, 0); + case SLANG_HOST_HOST_CALLABLE: return make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0); default: break; } SLANG_UNEXPECTED("Unhandled type"); } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ArtifactList::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactList::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + +void* ArtifactList::getObject(const Guid& guid) +{ + // For now we can't cast to an object + SLANG_UNUSED(guid); + return nullptr; +} + +void* ArtifactList::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +void ArtifactList::add(IArtifact* artifact) +{ + // Must be set + SLANG_ASSERT(artifact); + // Can't already be in the list + SLANG_ASSERT(m_artifacts.indexOf(artifact) < 0); + // Can't have another owner + SLANG_ASSERT(artifact->getParent() == nullptr); + + // Set the parent + artifact->setParent(m_parent); + + // Add + m_artifacts.add(ComPtr(artifact)); +} + +void ArtifactList::removeAt(Index index) +{ + IArtifact* artifact = m_artifacts[index]; + artifact->setParent(nullptr); + m_artifacts.removeAt(index); +} + +void ArtifactList::clear() +{ + _setParent(nullptr); + m_artifacts.clear(); +} + +void ArtifactList::_setParent(IArtifact* parent) +{ + if (m_parent == parent) + { + return; + } + + for (IArtifact* artifact : m_artifacts) + { + artifact->setParent(artifact); + } +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* Artifact::getInterface(const Guid& uuid) @@ -78,9 +380,30 @@ bool Artifact::exists() return true; } - // If we have an associated entry that represents the artifact it exists - if (findElement(IArtifactInstance::getTypeGuid())) + for (ISlangUnknown* item : m_items) { + ComPtr castable; + + if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + auto rep = (IArtifactRepresentation*)castable->castAs(IArtifactRepresentation::getTypeGuid()); + if (rep) + { + // It is a rep and it exists + if (rep->exists()) + { + return true; + } + continue; + } + // Associated types don't encapsulate an artifact representation, so don't signal existance + if (castable->castAs(IArtifactAssociated::getTypeGuid())) + { + continue; + } + } + + // It can't be IArtifactRepresentation or IArtifactAssociated, so we assume means it exists return true; } @@ -94,54 +417,57 @@ bool Artifact::exists() return File::exists(m_path); } -ISlangUnknown* Artifact::findElement(const Guid& guid) + +void Artifact::addItem(ISlangUnknown* intf) +{ + SLANG_ASSERT(intf); + // Can't already be in there + SLANG_ASSERT(m_items.indexOf(intf) < 0); + // Add it + m_items.add(ComPtr(intf)); +} + +void Artifact::removeItemAt(Index i) { - for (auto const& element : m_elements) - { - ISlangUnknown* value = element.value; + m_items.removeAt(i); +} + - ISlangUnknown* intf = nullptr; - if (SLANG_SUCCEEDED(value->queryInterface(guid, (void**)&intf)) && intf) +void* Artifact::findItemInterface(const Guid& guid) +{ + for (ISlangUnknown* intf : m_items) + { + ISlangUnknown* cast = nullptr; + if (SLANG_SUCCEEDED(intf->queryInterface(guid, (void**)&cast)) && cast) { // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope // (as strict COM requires so as to allow on demand interfaces). - intf->release(); - return intf; + cast->release(); + return cast; } } - return nullptr; } -void Artifact::addElement(const Desc& desc, ISlangUnknown* intf) -{ - SLANG_ASSERT(intf); - Element element{ desc, ComPtr(intf) }; - m_elements.add(element); -} - -void Artifact::removeElementAt(Index i) +void* Artifact::findItemObject(const Guid& classGuid) { - m_elements.removeAt(i); -} - -void* Artifact::findElementObject(const Guid& classGuid) -{ - ComPtr instance; - for (const auto& element : m_elements) + for (ISlangUnknown* intf : m_items) { - ISlangUnknown* value = element.value; - - if (SLANG_SUCCEEDED(value->queryInterface(IArtifactInstance::getTypeGuid(), (void**)instance.writeRef())) && instance) + ComPtr castable; + if (SLANG_SUCCEEDED(intf->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) { - void* classInstance = instance->queryObject(classGuid); - if (classInstance) + void* obj = castable->castAs(classGuid); + + // NOTE! This assumes we *DONT* need to ref count to keep an interface in scope + // (as strict COM requires so as to allow on demand interfaces). + + // If could cast return the result + if (obj) { - return classInstance; + return obj; } } } - return nullptr; } @@ -270,14 +596,13 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) else { // Look for a representation that we can serialize into a blob - for (const auto& element : m_elements) + for (ISlangUnknown* intf : m_items) { - ISlangUnknown* intf = element.value; - - ComPtr inst; - if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactInstance::getTypeGuid(), (void**)inst.writeRef())) && inst) + + ComPtr rep; + if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep) { - SlangResult res = inst->writeToBlob(blob.writeRef()); + SlangResult res = rep->writeToBlob(blob.writeRef()); if (SLANG_SUCCEEDED(res) && blob) { break; diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 362dac16f..c63ec3b67 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -8,84 +8,153 @@ #include "../../slang-com-ptr.h" #include "../core/slang-com-object.h" +#include "../core/slang-destroyable.h" namespace Slang { +/* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the highest level. +If some aspect can apply to multiple items identically we move that to a separate enum. + +NOTE! +New Kinds must be added at the end. Values can be depreciated, or disabled +but never removed, without breaking binary compatability. + +Any change requires a change to SLANG_ARTIFACT_KIND +*/ enum class ArtifactKind : uint8_t -{ - None, ///< There is no container +{ + Invalid, ///< Invalid + Base, ///< Base kind of all valid kinds - Unknown, ///< There is a container of unknown type + None, ///< Doesn't contain anything + Unknown, ///< Unknown - Library, ///< Library of object code (typically made up multiple ObjectCode) - ObjectCode, ///< Object code (for CPU typically .o or .obj file types) + Container, ///< Container like types + Zip, ///< Zip container + Riff, ///< Riff format - Executable, ///< Self contained such it can exectuted. On GPU this would be a kernel. - SharedLibrary, ///< Shared library/dll - Callable, ///< Callable directly (can mean there isn't a binary artifact) + Text, ///< Representation is text. Encoding is utf8, unless prefixed with 'encoding'. + + Source, ///< Source (Source type is in payload) + Assembly, ///< Assembly (Type is in payload) + HumanText, ///< Text for human consumption - Text, ///< Text + BinaryLike, ///< Kinds which are 'binary like' - can be executed, linked with and so forth. + + ObjectCode, ///< Object file + Library, ///< Library (collection of object code) + Executable, ///< Executable + SharedLibrary, ///< Shared library - can be dynamically linked + HostCallable, ///< Code can be executed directly on the host - Container, ///< A container holding other things + DebugInfo, ///< Debugging information + Diagnostics, ///< Diagnostics information CountOf, }; + +/// Get the parent kind +ArtifactKind getParent(ArtifactKind kind); +/// Returns true if kind is derived from base +bool isDerivedFrom(ArtifactKind kind, ArtifactKind base); +/// Get the name for the kind +UnownedStringSlice getName(ArtifactKind kind); -enum class ArtifactPayload : uint8_t -{ - None, ///< There is no payload +/* Payload. - Unknown, ///< Has payload but its unknown variety +SlangIR and LLVMIR can be GPU or CPU orientated, so put in own category. - DXIL, - DXBC, - SPIRV, - PTX, +NOTE! +New Payloads must be added at the end. Values can be depreciated, or disabled +but never removed, without breaking binary compatability. - DXILAssembly, - DXBCAssembly, - SPIRVAssembly, - PTXAssembly, +Any change requires a change to SLANG_ARTIFACT_PAYLOAD +*/ +enum class ArtifactPayload : uint8_t +{ + Invalid, ///< Is invalid - indicates some kind of problem + Base, ///< The base of the hierarchy + + None, ///< Doesn't have a payload + Unknown, ///< Unknown but probably valid + + Source, ///< Source code + + C, ///< C source + Cpp, ///< C++ source + HLSL, ///< HLSL source + GLSL, ///< GLSL source + CUDA, ///< CUDA source + Metal, ///< Metal source + Slang, ///< Slang source + + KernelLike, ///< GPU Kernel like + + DXIL, ///< DXIL + DXBC, ///< DXBC + SPIRV, ///< SPIR-V + PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. + MetalAIR, ///< Metal AIR + CuBin, ///< CUDA binary + + CPULike, ///< CPU code + + UnknownCPU, ///< CPU code for unknown/undetermined type + X86, ///< X86 + X86_64, ///< X86_64 + Aarch, ///< 32 bit arm + Aarch64, ///< Aarch64 + HostCPU, ///< HostCPU + UniversalCPU, ///< CPU code for multiple CPU types - HostCPU, ///< The host CPU architecture + GeneralIR, ///< General purpose IR representation (IR) SlangIR, ///< Slang IR LLVMIR, ///< LLVM IR - SlangAST, ///< Slang AST - - X86, - X86_64, - AARCH, - AARCH64, + AST, ///< Abstract syntax tree (AST) - HLSL, ///< HLSL - GLSL, ///< GLSL - CPP, ///< C++ - C, ///< C Language - CUDA, ///< CUDA - Slang, ///< Slang + SlangAST, ///< Slang AST - DebugInfo, ///< Debug information + CountOf, +}; - Diagnostics, ///< Diagnostics +/// Get the parent payload +ArtifactPayload getParent(ArtifactPayload payload); +/// Returns true if payload is derived from base +bool isDerivedFrom(ArtifactPayload payload, ArtifactPayload base); +/// Get the name for the payload +UnownedStringSlice getName(ArtifactPayload payload); - Zip, ///< It's a zip +/* Style. - CountOf, -}; +NOTE! +New Styles must be added at the end. Values can be depreciated, or disabled +but never removed, without breaking binary compatability. +Any change requires a change to SLANG_ARTIFACT_STYLE +*/ enum class ArtifactStyle : uint8_t { - Unknown, ///< Unknown + Invalid, ///< Invalid style (indicating an error) + Base, + + Unknown, ///< Unknown - Kernel, ///< Compiled as `GPU kernel` style. - Host, ///< Compiled in `host` style + Kernel, ///< Compiled as `GPU kernel` style. + Host, ///< Compiled in `host` style CountOf, }; +/// Get the parent style +ArtifactStyle getParent(ArtifactStyle style); +/// Returns true if style is derived from base +bool isDerivedFrom(ArtifactStyle style, ArtifactStyle base); +/// Get the name for the style +UnownedStringSlice getName(ArtifactStyle style); + typedef uint8_t ArtifactFlags; struct ArtifactFlag { @@ -95,7 +164,6 @@ struct ArtifactFlag }; }; - /** A value type to describe aspects of the contents of an Artifact. **/ @@ -180,13 +248,13 @@ enum ArtifactPathType Existing, ///< Is an existing file }; -/* The IArtifactInstance interface represents a single instance of a type that can be part of an artifact. It's special in so far +/* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far as -* IArtifactInstance can be queried for it's underlying object class +* IArtifactRepresentation can be queried for it's underlying object class * Can optionally serialize into a blob */ -class IArtifactInstance : public ISlangUnknown +class IArtifactRepresentation : public ICastable { SLANG_COM_INTERFACE(0x311457a8, 0x1796, 0x4ebb, { 0x9a, 0xfc, 0x46, 0xa5, 0x44, 0xc7, 0x6e, 0xa9 }) @@ -194,13 +262,15 @@ class IArtifactInstance : public ISlangUnknown /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) = 0; - /// Queries for the backing object type. The type is represented by a guid. - /// If the object doesn't derive from the type guid the function returns nullptr. - /// Unlike the analagous queryInterface method the ref count remains unchanged. - /// NOTE! - /// Whilst this method *could) be used across an ABI boundary (whereas using something like dynamic_cast would not), - /// it is generally dangerous to do so. - virtual SLANG_NO_THROW void* SLANG_MCALL queryObject(const Guid& classGuid) = 0; + /// Returns true if this representation exists and is available for use. + virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; +}; + +/* Interface for types that are associated with an artifact, but aren't a representation, or are +only part of a representation. */ +class IArtifactAssociated : public ICastable +{ + SLANG_COM_INTERFACE(0xafc0e4db, 0x16d4, 0x4d7a, { 0x93, 0x5f, 0x3e, 0x47, 0x7a, 0x23, 0x2a, 0x7f }) }; /* The IArtifact interface is designed to represent some Artifact of compilation. It could be input to or output from a compilation. @@ -255,6 +325,11 @@ public: /// Get the Desc defining the contents of the artifact virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() = 0; + /// Get the artifact (if any) that this artifact belongs to + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() = 0; + /// Set the parent that 'owns' this artifact. The parent is *not* reference counted (ie weak reference) + virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* parent) = 0; + /// Returns true if the artifact in principal exists virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; @@ -275,12 +350,6 @@ public: /// artifact name needs to be correct. virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileLike(Keep keep) = 0; - /// Finds an instance of that has the the interface guid - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL findElement(const Guid& guid) = 0; - - /// Find an element that derives from IArtifactInstance, and which queryObject works with the classGuid - virtual SLANG_NO_THROW void* SLANG_MCALL findElementObject(const Guid& classGuid) = 0; - /// Add items virtual SLANG_NO_THROW void SLANG_MCALL setPath(PathType pathType, const char* filePath) = 0; @@ -295,19 +364,78 @@ public: /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; - /// Add an interface - virtual SLANG_NO_THROW void SLANG_MCALL addElement(const Desc& desc, ISlangUnknown* intf) = 0; - - /// Get the item at the index - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getElementAt(Index i) = 0; - /// Get the desc associated with an element - virtual SLANG_NO_THROW Desc SLANG_MCALL getElementDescAt(Index i) = 0; + /// Find an item by casting it's interface + virtual SLANG_NO_THROW void* SLANG_MCALL findItemInterface(const Guid& uuid) = 0; + /// Only works on ICastable derived items. Can find interfaces or objects. + virtual SLANG_NO_THROW void* SLANG_MCALL findItemObject(const Guid& classGuid) = 0; + /// Add a representation + virtual SLANG_NO_THROW void SLANG_MCALL addItem(ISlangUnknown* item) = 0; + /// Get the item at the index + virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getItemAt(Index i) = 0; /// Remove the element at the specified index. - virtual SLANG_NO_THROW void SLANG_MCALL removeElementAt(Index i) = 0; - + virtual SLANG_NO_THROW void SLANG_MCALL removeItemAt(Index i) = 0; /// Get the amount of elements - virtual SLANG_NO_THROW Index SLANG_MCALL getElementCount() = 0; + virtual SLANG_NO_THROW Index SLANG_MCALL getItemCount() = 0; +}; + +/* A list of artifacts. */ +class IArtifactList : public ICastable +{ + SLANG_COM_INTERFACE(0x5ef6ace5, 0xc928, 0x4c7b, { 0xbc, 0xba, 0x83, 0xa9, 0xd9, 0x66, 0x64, 0x27 }) + + /// Get the artifact this list belongs to. Can be nullptr. + /// Note this is a *weak* reference. + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() = 0; + /// The parent is no longer accessible + virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* artifact) = 0; + + /// Get the artifact at the specified index + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getAt(Index index) = 0; + /// Get the count of all the artifacts + virtual SLANG_NO_THROW Count SLANG_MCALL getCount() = 0; + /// Add the artifact to the list + virtual SLANG_NO_THROW void SLANG_MCALL add(IArtifact* artifact) = 0; + /// Removes at index, keeps other artifacts in the same order + virtual SLANG_NO_THROW void SLANG_MCALL removeAt(Index index) = 0; + /// Clear the list + virtual SLANG_NO_THROW void SLANG_MCALL clear() = 0; +}; + +class ArtifactList : public ComObject, public IArtifactList +{ +public: + SLANG_COM_OBJECT_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactList + SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() SLANG_OVERRIDE { return m_parent; } + SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* parent) SLANG_OVERRIDE { _setParent(parent); } + + SLANG_NO_THROW IArtifact* SLANG_MCALL getAt(Index index) SLANG_OVERRIDE { return m_artifacts[index]; } + SLANG_NO_THROW Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_artifacts.getCount(); } + SLANG_NO_THROW void SLANG_MCALL add(IArtifact* artifact) SLANG_OVERRIDE; + SLANG_NO_THROW void SLANG_MCALL removeAt(Index index) SLANG_OVERRIDE; + SLANG_NO_THROW void SLANG_MCALL clear() SLANG_OVERRIDE; + + // NOTE! The parent is a weak reference. + ArtifactList(IArtifact* parent): + m_parent(parent) + { + } + + virtual ~ArtifactList() { _setParent(nullptr); } + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + void _setParent(IArtifact* artifact); + + IArtifact* m_parent; + List> m_artifacts; }; /* @@ -342,27 +470,29 @@ public: /// IArtifact impl virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() SLANG_OVERRIDE { return m_parent; } + virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* parent) SLANG_OVERRIDE { m_parent = parent; } virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileLike(Keep keep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL findElement(const Guid& guid) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void* SLANG_MCALL findElementObject(const Guid& classGuid) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setPath(PathType pathType, const char* path) SLANG_OVERRIDE { _setPath(pathType, path); } virtual SLANG_NO_THROW void SLANG_MCALL setBlob(ISlangBlob* blob) SLANG_OVERRIDE { m_blob = blob; } virtual SLANG_NO_THROW PathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return m_pathType; } virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } - virtual SLANG_NO_THROW void SLANG_MCALL addElement(const Desc& desc, ISlangUnknown* intf) SLANG_OVERRIDE; - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getElementAt(Index i) SLANG_OVERRIDE { return m_elements[i].value; } - virtual SLANG_NO_THROW Desc SLANG_MCALL getElementDescAt(Index i) SLANG_OVERRIDE { return m_elements[i].desc; } - virtual SLANG_NO_THROW void SLANG_MCALL removeElementAt(Index i) SLANG_OVERRIDE; - virtual SLANG_NO_THROW Index SLANG_MCALL getElementCount() SLANG_OVERRIDE { return m_elements.getCount(); } + virtual SLANG_NO_THROW void* SLANG_MCALL findItemInterface(const Guid& uuid) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void* SLANG_MCALL findItemObject(const Guid& classGuid) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL addItem(ISlangUnknown* intf) SLANG_OVERRIDE; + virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getItemAt(Index i) SLANG_OVERRIDE { return m_items[i]; } + virtual SLANG_NO_THROW void SLANG_MCALL removeItemAt(Index i) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Index SLANG_MCALL getItemCount() SLANG_OVERRIDE { return m_items.getCount(); } /// Ctor Artifact(const Desc& desc, const String& name) : m_desc(desc), - m_name(name) + m_name(name), + m_parent(nullptr) {} /// Dtor ~Artifact(); @@ -372,13 +502,9 @@ protected: void _setPath(PathType pathType, const String& path) { m_pathType = pathType; m_path = path; } - struct Element - { - ArtifactDesc desc; - ComPtr value; - }; - Desc m_desc; ///< Description of the artifact + IArtifact* m_parent; ///< Artifact this artifact belongs to + String m_name; ///< Name of this artifact PathType m_pathType = PathType::None; ///< What the path indicates @@ -387,7 +513,7 @@ protected: ComPtr m_blob; ///< Blob to store result in memory - List m_elements; ///< Associated elements + List> m_items; ///< Associated items }; } // namespace Slang diff --git a/source/core/slang-destroyable.h b/source/core/slang-destroyable.h new file mode 100644 index 000000000..4e6be2629 --- /dev/null +++ b/source/core/slang-destroyable.h @@ -0,0 +1,41 @@ +#ifndef SLANG_CORE_DESTROYABLE_H +#define SLANG_CORE_DESTROYABLE_H + +#include "slang-string.h" + +#include "../../slang-com-helper.h" +#include "../../slang-com-ptr.h" + +namespace Slang +{ + +/* An interface to provide a mechanism to cast, that doesn't require ref counting +and doesn't have to return a pointer to a ISlangUnknown derived class */ +class ICastable : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0x87ede0e1, 0x4852, 0x44b0, { 0x8b, 0xf2, 0xcb, 0x31, 0x87, 0x4d, 0xe2, 0x39 } ); + + /// Can be used to cast to interfaces without reference counting. + /// Also provides access to internal implementations, when they provide a guid + /// Can simulate a 'generated' interface as long as kept in scope by cast from. + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) = 0; +}; + +/* An interface that allows for an object to implement 'destruction'. A destroyed +interface/object should release any other contained references. +Behavior of an interface that is IDestroyed should be defined on the interface. Typically +it will produce an assert on debug builds. +Calling destroy/isDestroyed can always be performed. */ +class IDestroyable : public ICastable +{ + SLANG_COM_INTERFACE(0x99c6228e, 0xa82, 0x43eb, { 0x8f, 0xd1, 0xf3, 0x54, 0x3e, 0x2e, 0x86, 0xc0 } ); + + /// Destroy. Can call on destroyed - is a no op. + virtual SLANG_NO_THROW void SLANG_MCALL destroy() = 0; + /// Once destroyed *no* functionality is supported other than IUnknown and destroy/isDestroyed + virtual SLANG_NO_THROW bool SLANG_MCALL isDestroyed() = 0; +}; + +} + +#endif // SLANG_CORE_DESTROYABLE_H diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index d4c5812b7..8a9c322b2 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1303,7 +1303,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) // If we aren't using LLVM 'host callable', we want downstream compile to produce a shared library if (compilerType != PassThroughMode::LLVM && - ArtifactDesc::makeFromCompileTarget(asExternal(target)).kind == ArtifactKind::Callable) + ArtifactDesc::makeFromCompileTarget(asExternal(target)).kind == ArtifactKind::HostCallable) { target = CodeGenTarget::ShaderSharedLibrary; } @@ -1800,7 +1800,7 @@ void printDiagnosticArg(StringBuilder& sb, CodeGenTarget val) ComPtr blob; if (SLANG_FAILED(result.getBlob(blob))) { - if (ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget())).kind == ArtifactKind::Callable) + if (ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget())).kind == ArtifactKind::HostCallable) { // Some HostCallable are not directly representable as a 'binary'. // So here, we just ignore if that appears the case, and don't output an unexpected error. diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 14724046a..636a32a4d 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -1411,7 +1411,7 @@ LinkedIR linkIR( }); for (IArtifact* artifact : linkage->m_libModules) { - ModuleLibrary* library = (ModuleLibrary*)artifact->findElementObject(ModuleLibrary::getTypeGuid()); + ModuleLibrary* library = (ModuleLibrary*)artifact->findItemObject(ModuleLibrary::getTypeGuid()); if (library) { irModules.addRange(library->m_modules.getBuffer()->readRef(), library->m_modules.getCount()); diff --git a/source/slang/slang-module-library.cpp b/source/slang/slang-module-library.cpp index 140be4d64..b60555766 100644 --- a/source/slang/slang-module-library.cpp +++ b/source/slang/slang-module-library.cpp @@ -15,13 +15,27 @@ namespace Slang { void* ModuleLibrary::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || uuid == IArtifactInstance::getTypeGuid()) + if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || uuid == IArtifactRepresentation::getTypeGuid()) { - return static_cast(this); + return static_cast(this); } return nullptr; } +void* ModuleLibrary::getObject(const Guid& uuid) +{ + return uuid == getTypeGuid() ? this : nullptr; +} + +void* ModuleLibrary::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr& outLibrary) { RefPtr library = new ModuleLibrary; @@ -77,7 +91,7 @@ SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCo SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, RefPtr& outLibrary) { - if (auto foundLibrary = (ModuleLibrary*)artifact->findElementObject(ModuleLibrary::getTypeGuid())) + if (auto foundLibrary = (ModuleLibrary*)artifact->findItemObject(ModuleLibrary::getTypeGuid())) { outLibrary = foundLibrary; return SLANG_OK; @@ -93,7 +107,7 @@ SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCo if (canKeep(keep)) { - artifact->addElement(artifact->getDesc(), library); + artifact->addItem(library); } outLibrary = library; diff --git a/source/slang/slang-module-library.h b/source/slang/slang-module-library.h index 7b65dad9e..58d10bfc3 100644 --- a/source/slang/slang-module-library.h +++ b/source/slang/slang-module-library.h @@ -10,7 +10,7 @@ namespace Slang { // Class to hold information serialized in from a -r slang-lib/slang-module -class ModuleLibrary : public ComObject, public IArtifactInstance +class ModuleLibrary : public ComObject, public IArtifactRepresentation { public: @@ -18,14 +18,18 @@ public: SLANG_CLASS_GUID(0x2f7412bd, 0x6154, 0x40a9, { 0x89, 0xb3, 0x62, 0xe0, 0x24, 0x17, 0x24, 0xa1 }); - // IArtifactInstance + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactRepresentation virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) SLANG_OVERRIDE { SLANG_UNUSED(blob); return SLANG_E_NOT_IMPLEMENTED; } - virtual SLANG_NO_THROW void* SLANG_MCALL queryObject(const Guid& classGuid) SLANG_OVERRIDE { return classGuid == getTypeGuid() ? this : nullptr; } + virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return true; } List m_entryPoints; List> m_modules; void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); }; SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr& module); diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 9825e4e23..f56395f5b 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -1467,12 +1467,12 @@ struct OptionsParser } // If it's a GPU binary, then we'll assume it's a library - if (ArtifactInfoUtil::isGpuBinary(desc)) + if (ArtifactInfoUtil::isGpuUsable(desc)) { desc.kind = ArtifactKind::Library; } - if (!ArtifactInfoUtil::isBinaryLinkable(desc)) + if (!ArtifactInfoUtil::isLinkable(desc)) { sink->diagnose(referenceModuleName.loc, Diagnostics::kindNotLinkable, Path::getPathExt(path)); return SLANG_FAIL; @@ -2036,7 +2036,7 @@ struct OptionsParser // and output type is callable, add an empty' rawOutput. if (rawOutputs.getCount() == 0 && rawTargets.getCount() == 1 && - ArtifactDesc::makeFromCompileTarget(asExternal(rawTargets[0].format)).kind == ArtifactKind::Callable) + ArtifactDesc::makeFromCompileTarget(asExternal(rawTargets[0].format)).kind == ArtifactKind::HostCallable) { RawOutput rawOutput; rawOutput.impliedFormat = rawTargets[0].format; diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index d0b12b19b..220cfb992 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -3032,7 +3032,7 @@ static int _calcTotalNumUsedRegistersForLayoutResourceKind(ParameterBindingConte static bool _isCPUTarget(CodeGenTarget target) { const auto desc = ArtifactDesc::makeFromCompileTarget(asExternal(target)); - return ArtifactInfoUtil::isCpuTarget(desc); + return ArtifactInfoUtil::isCpuLikeTarget(desc); } static bool _isPTXTarget(CodeGenTarget target) diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 09a21fb6f..cde70d488 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -1606,7 +1606,7 @@ bool isKhronosTarget(TargetRequest* targetReq) bool isCPUTarget(TargetRequest* targetReq) { - return ArtifactInfoUtil::isCpuTarget(ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget()))); + return ArtifactInfoUtil::isCpuLikeTarget(ArtifactDesc::makeFromCompileTarget(asExternal(targetReq->getTarget()))); } bool isCUDATarget(TargetRequest* targetReq) diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 891b9827a..b3762e471 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -727,7 +727,7 @@ SlangPassThrough Session::getDownstreamCompilerForTransition(SlangCompileTarget const auto desc = ArtifactDesc::makeFromCompileTarget(inTarget); // Special case host-callable - if ((desc.kind == ArtifactKind::Callable) && + if ((desc.kind == ArtifactKind::HostCallable) && (source == CodeGenTarget::CSource || source == CodeGenTarget::CPPSource)) { // We prefer LLVM if it's available @@ -4507,9 +4507,9 @@ SlangResult EndToEndCompileRequest::addLibraryReference(const void* libData, siz const auto desc = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); // Create an artifact without any name (as one is not provided) - RefPtr artifact = new Artifact(desc, String()); + ComPtr artifact(new Artifact(desc, String())); - artifact->addElement(desc, library); + artifact->addItem(library); return _addLibraryReference(this, artifact); } -- cgit v1.2.3