summaryrefslogtreecommitdiffstats
path: root/source/compiler-core
diff options
context:
space:
mode:
Diffstat (limited to 'source/compiler-core')
-rw-r--r--source/compiler-core/slang-artifact-desc-util.cpp689
-rw-r--r--source/compiler-core/slang-artifact-desc-util.h (renamed from source/compiler-core/slang-artifact-info.h)38
-rw-r--r--source/compiler-core/slang-artifact-impl.cpp224
-rw-r--r--source/compiler-core/slang-artifact-impl.h116
-rw-r--r--source/compiler-core/slang-artifact-info.cpp421
-rw-r--r--source/compiler-core/slang-artifact-representation-impl.cpp147
-rw-r--r--source/compiler-core/slang-artifact-representation-impl.h94
-rw-r--r--source/compiler-core/slang-artifact-representation.h52
-rw-r--r--source/compiler-core/slang-artifact-util.cpp13
-rw-r--r--source/compiler-core/slang-artifact-util.h5
-rw-r--r--source/compiler-core/slang-artifact.cpp630
-rw-r--r--source/compiler-core/slang-artifact.h280
-rw-r--r--source/compiler-core/slang-dxc-compiler.cpp4
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp8
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp8
15 files changed, 1397 insertions, 1332 deletions
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp
new file mode 100644
index 000000000..e382ca08c
--- /dev/null
+++ b/source/compiler-core/slang-artifact-desc-util.cpp
@@ -0,0 +1,689 @@
+// slang-artifact-desc-util.cpp
+#include "slang-artifact-desc-util.h"
+
+#include "slang-artifact-representation.h"
+
+#include "../core/slang-type-text-util.h"
+#include "../core/slang-io.h"
+
+namespace Slang {
+
+namespace { // anonymous
+
+struct HierarchicalEnumEntry
+{
+ Index value;
+ Index parent;
+ const char* name;
+};
+
+static bool _isHierarchicalEnumOk(ConstArrayView<HierarchicalEnumEntry> entries, Count countOf)
+{
+ // All values should be set
+ if (entries.getCount() != countOf)
+ {
+ return false;
+ }
+
+ List<uint8_t> 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 <typename T>
+struct HierarchicalEnumTable
+{
+ HierarchicalEnumTable(ConstArrayView<HierarchicalEnumEntry> 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<HierarchicalEnumEntry> _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<ENUM_TYPE> 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)
+
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDescUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+/* static */ArtifactDesc ArtifactDescUtil::makeDescFromCompileTarget(SlangCompileTarget target)
+{
+ switch (target)
+ {
+ case SLANG_TARGET_UNKNOWN: return Desc::make(Kind::Unknown, Payload::None, Style::Unknown, 0);
+ case SLANG_TARGET_NONE: return Desc::make(Kind::None, Payload::None, Style::Unknown, 0);
+ case SLANG_GLSL_VULKAN:
+ case SLANG_GLSL_VULKAN_ONE_DESC:
+ case SLANG_GLSL:
+ {
+ // For the moment we Desc::make all just map to GLSL, but we could use flags
+ // or some other mechanism to distinguish the types
+ return Desc::make(Kind::Source, Payload::GLSL, Style::Kernel, 0);
+ }
+ case SLANG_HLSL: return Desc::make(Kind::Source, Payload::HLSL, Style::Kernel, 0);
+ case SLANG_SPIRV: return Desc::make(Kind::Executable, Payload::SPIRV, Style::Kernel, 0);
+ case SLANG_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0);
+ case SLANG_DXBC: return Desc::make(Kind::Executable, Payload::DXBC, Style::Kernel, 0);
+ case SLANG_DXBC_ASM: return Desc::make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0);
+ case SLANG_DXIL: return Desc::make(Kind::Executable, Payload::DXIL, Style::Kernel, 0);
+ case SLANG_DXIL_ASM: return Desc::make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0);
+ case SLANG_C_SOURCE: return Desc::make(Kind::Source, Payload::C, Style::Kernel, 0);
+ case SLANG_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Kernel, 0);
+ case SLANG_HOST_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0);
+ case SLANG_HOST_EXECUTABLE: return Desc::make(Kind::Executable, Payload::HostCPU, Style::Host, 0);
+ case SLANG_SHADER_SHARED_LIBRARY: return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_SHADER_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_CUDA_SOURCE: return Desc::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 Desc::make(Kind::Executable, Payload::PTX, Style::Kernel, 0);
+ case SLANG_OBJECT_CODE: return Desc::make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0);
+ case SLANG_HOST_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0);
+ default: break;
+ }
+
+ SLANG_UNEXPECTED("Unhandled type");
+}
+
+namespace { // anonymous
+struct KindExtension
+{
+ ArtifactKind kind;
+ UnownedStringSlice ext;
+};
+} // anonymous
+
+#define SLANG_KIND_EXTENSION(kind, ext) \
+ { ArtifactKind::kind, toSlice(ext) },
+
+static const KindExtension g_cpuKindExts[] =
+{
+#if SLANG_WINDOWS_FAMILY
+ SLANG_KIND_EXTENSION(Library, "lib")
+ SLANG_KIND_EXTENSION(ObjectCode, "obj")
+ SLANG_KIND_EXTENSION(Executable, "exe")
+ SLANG_KIND_EXTENSION(SharedLibrary, "dll")
+#else
+ SLANG_KIND_EXTENSION(Library, "a")
+ SLANG_KIND_EXTENSION(ObjectCode, "o")
+ SLANG_KIND_EXTENSION(Executable, "")
+
+#if __CYGWIN__
+ SLANG_KIND_EXTENSION(SharedLibrary, "dll")
+#elif SLANG_APPLE_FAMILY
+ SLANG_KIND_EXTENSION(SharedLibrary, "dylib")
+#else
+ SLANG_KIND_EXTENSION(SharedLibrary, "so")
+#endif
+
+#endif
+};
+
+
+/* static */ bool ArtifactDescUtil::isCpuBinary(const ArtifactDesc& desc)
+{
+ return isDerivedFrom(desc.kind, ArtifactKind::BinaryLike) && isDerivedFrom(desc.payload, ArtifactPayload::CPULike);
+}
+
+/* static */bool ArtifactDescUtil::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 ArtifactDescUtil::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 ArtifactDescUtil::isKindBinaryLinkable(Kind kind)
+{
+ switch (kind)
+ {
+ case Kind::Library:
+ case Kind::ObjectCode:
+ {
+ return true;
+ }
+ default: break;
+ }
+ return false;
+}
+
+/* static */bool ArtifactDescUtil::isLinkable(const ArtifactDesc& desc)
+{
+ 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
+
+ // We can't *actually* link PTX or SPIR-V currently but it is in principal possible
+ // so let's say we accept for now
+
+ 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;
+ }
+
+ return true;
+ }
+ else if (isDerivedFrom(desc.payload, ArtifactPayload::GeneralIR))
+ {
+ // We'll *assume* IR is linkable
+ return true;
+ }
+ }
+ return false;
+}
+
+/* static */bool ArtifactDescUtil::isCpuLikeTarget(const ArtifactDesc& desc)
+{
+ if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike))
+ {
+ return isDerivedFrom(desc.payload, ArtifactPayload::CPULike);
+ }
+ 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;
+ }
+
+ return false;
+}
+
+/* static */ArtifactDesc ArtifactDescUtil::getDescFromExtension(const UnownedStringSlice& slice)
+{
+ if (slice == "slang-module" ||
+ slice == "slang-lib")
+ {
+ 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)
+ {
+ // We'll assume it's for the host CPU for now..
+ return ArtifactDesc::make(kindExt.kind, Payload::HostCPU);
+ }
+ }
+
+ const auto target = TypeTextUtil::findCompileTargetFromExtension(slice);
+
+ return makeDescFromCompileTarget(target);
+}
+
+/* static */ArtifactDesc ArtifactDescUtil::getDescFromPath(const UnownedStringSlice& slice)
+{
+ auto extension = Path::getPathExt(slice);
+ return getDescFromExtension(extension);
+}
+
+/* static*/ UnownedStringSlice ArtifactDescUtil::getCpuExtensionForKind(Kind kind)
+{
+ for (const auto& kindExt : g_cpuKindExts)
+ {
+ if (kind == kindExt.kind)
+ {
+ return kindExt.ext;
+ }
+ }
+ return UnownedStringSlice();
+}
+
+UnownedStringSlice ArtifactDescUtil::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 ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& desc)
+{
+ 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 (ArtifactDescUtil::isCpuLikeTarget(desc))
+ {
+ return getCpuExtensionForKind(desc.kind);
+ }
+
+ if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike))
+ {
+ 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 ArtifactDescUtil::getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path)
+{
+ String name = Path::getFileName(path);
+
+ const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY;
+ if (isSharedLibraryPrefixPlatform)
+ {
+ // Strip lib prefix
+ if (isCpuBinary(desc) &&
+ (desc.kind == ArtifactKind::Library ||
+ desc.kind == ArtifactKind::SharedLibrary))
+ {
+ // If it starts with lib strip it
+ if (name.startsWith("lib"))
+ {
+ const String stripLib = name.getUnownedSlice().tail(3);
+ name = stripLib;
+ }
+ }
+ }
+
+ // Strip any extension
+ {
+ auto descExt = getDefaultExtension(desc);
+ // Strip the extension if it's a match
+ if (descExt.getLength() &&
+ Path::getPathExt(name) == descExt)
+ {
+ name = Path::getFileNameWithoutExt(name);
+ }
+ }
+
+ return name;
+}
+
+/* static */String ArtifactDescUtil::getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep)
+{
+ UnownedStringSlice path(fileRep->getPath());
+ return getBaseNameFromPath(desc, path);
+}
+
+/* static */String ArtifactDescUtil::getBaseName(IArtifact* artifact)
+{
+ if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact))
+ {
+ return getBaseName(artifact->getDesc(), fileRep);
+ }
+ // Else use the name
+ return artifact->getName();
+}
+
+/* static */String ArtifactDescUtil::getParentPath(IFileArtifactRepresentation* fileRep)
+{
+ UnownedStringSlice path(fileRep->getPath());
+ return Path::getParentDirectory(path);
+}
+
+/* static */String ArtifactDescUtil::getParentPath(IArtifact* artifact)
+{
+ if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact))
+ {
+ return getParentPath(fileRep);
+ }
+ return String();
+}
+
+/* static */SlangResult ArtifactDescUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath)
+{
+ outPath.Clear();
+
+ UnownedStringSlice baseName;
+
+ // Append the directory
+ Index pos = Path::findLastSeparatorIndex(basePath);
+ if (pos >= 0)
+ {
+ outPath.append(basePath.head(pos));
+ outPath.append(Path::kPathDelimiter);
+
+ baseName = basePath.tail(pos + 1);
+ }
+
+ if (baseName.getLength() == 0)
+ {
+ baseName = toSlice("unknown");
+ }
+
+ if (isCpuBinary(desc) &&
+ (desc.kind == ArtifactKind::SharedLibrary ||
+ desc.kind == ArtifactKind::Library))
+ {
+ const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY;
+ if (isSharedLibraryPrefixPlatform)
+ {
+ outPath << "lib";
+ outPath << baseName;
+ }
+ }
+
+ // If there is an extension append it
+ const UnownedStringSlice ext = getDefaultExtension(desc);
+
+ if (ext.getLength())
+ {
+ outPath.appendChar('.');
+ outPath.append(ext);
+ }
+
+ return SLANG_OK;
+}
+
+} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-info.h b/source/compiler-core/slang-artifact-desc-util.h
index 9f741cbbe..ccd380892 100644
--- a/source/compiler-core/slang-artifact-info.h
+++ b/source/compiler-core/slang-artifact-desc-util.h
@@ -1,23 +1,47 @@
-// slang-artifact-info.h
-#ifndef SLANG_ARTIFACT_INFO_H
-#define SLANG_ARTIFACT_INFO_H
+// slang-artifact-desc.h
+
+#ifndef SLANG_ARTIFACT_DESC_UTIL_H
+#define SLANG_ARTIFACT_DESC_UTIL_H
#include "slang-artifact.h"
namespace Slang
{
-struct ArtifactInfoUtil
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+struct ArtifactDescUtil
{
typedef ArtifactPayload Payload;
typedef ArtifactKind Kind;
-
+ typedef ArtifactStyle Style;
+ typedef ArtifactDesc Desc;
+
/// Returns true if the kind is binary linkable
static bool isKindBinaryLinkable(Kind kind);
/// True if is a CPU target - either
static bool isCpuLikeTarget(const ArtifactDesc& desc);
-
+
/// True if is a CPU binary
static bool isCpuBinary(const ArtifactDesc& desc);
/// True if is a GPU usable (can be passed to a driver/API and be used
@@ -61,6 +85,8 @@ struct ArtifactInfoUtil
/// Given a desc, and a basePath returns a suitable path for a entity of specified desc
static SlangResult calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath);
+ /// Make ArtifactDesc from target
+ static ArtifactDesc makeDescFromCompileTarget(SlangCompileTarget target);
};
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp
new file mode 100644
index 000000000..8dbae063b
--- /dev/null
+++ b/source/compiler-core/slang-artifact-impl.cpp
@@ -0,0 +1,224 @@
+// slang-artifact-impl.cpp
+#include "slang-artifact-impl.h"
+
+#include "slang-artifact-representation.h"
+
+#include "slang-artifact-util.h"
+
+namespace Slang {
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void* ArtifactList::getInterface(const Guid& guid)
+{
+ if (guid == ISlangUnknown::getTypeGuid() ||
+ guid == ICastable::getTypeGuid() ||
+ guid == IArtifactList::getTypeGuid())
+ {
+ return static_cast<IArtifactList*>(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<IArtifact>(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)
+{
+ if (uuid == ISlangUnknown::getTypeGuid() || uuid == IArtifact::getTypeGuid())
+ {
+ return static_cast<IArtifact*>(this);
+ }
+ return nullptr;
+}
+
+bool Artifact::exists()
+{
+ for (ISlangUnknown* item : m_items)
+ {
+ ComPtr<ICastable> castable;
+
+ if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ auto rep = as<IArtifactRepresentation>(castable);
+ 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 (as<IArtifactAssociated>(castable))
+ {
+ continue;
+ }
+ }
+
+ // It can't be IArtifactRepresentation or IArtifactAssociated, so we assume means it exists
+ return true;
+ }
+
+ return false;
+}
+
+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<ISlangUnknown>(intf));
+}
+
+void Artifact::removeItemAt(Index i)
+{
+ m_items.removeAt(i);
+}
+
+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).
+ cast->release();
+ return cast;
+ }
+ }
+ return nullptr;
+}
+
+void* Artifact::findItemObject(const Guid& classGuid)
+{
+ for (ISlangUnknown* intf : m_items)
+ {
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(intf->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
+ {
+ 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 obj;
+ }
+ }
+ }
+ return nullptr;
+}
+
+SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep)
+{
+ auto util = ArtifactUtilImpl::getSingleton();
+ return util->requireFileDefaultImpl(this, keep, outFileRep);
+}
+
+SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
+{
+ // If we have a blob just return it
+ if (auto blob = findItem<ISlangBlob>(this))
+ {
+ blob->addRef();
+ *outBlob = blob;
+ return SLANG_OK;
+ }
+
+ ComPtr<ISlangBlob> blob;
+
+ // Look for a representation that we can serialize into a blob
+ for (ISlangUnknown* intf : m_items)
+ {
+ ComPtr<IArtifactRepresentation> rep;
+ if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep)
+ {
+ SlangResult res = rep->writeToBlob(blob.writeRef());
+ if (SLANG_SUCCEEDED(res) && blob)
+ {
+ break;
+ }
+ }
+ }
+
+ // Wasn't able to construct
+ if (!blob)
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+
+ // Put in cache
+ if (canKeep(keep))
+ {
+ addItem(blob);
+ }
+
+ *outBlob = blob.detach();
+ return SLANG_OK;
+}
+
+} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h
new file mode 100644
index 000000000..35dbe5f98
--- /dev/null
+++ b/source/compiler-core/slang-artifact-impl.h
@@ -0,0 +1,116 @@
+// slang-artifact-impl.h
+#ifndef SLANG_ARTIFACT_IMPL_H
+#define SLANG_ARTIFACT_IMPL_H
+
+#include "slang-artifact.h"
+
+#include "../../slang-com-helper.h"
+#include "../../slang-com-ptr.h"
+
+#include "../core/slang-com-object.h"
+
+namespace Slang
+{
+
+class ArtifactList : public ComBaseObject, public IArtifactList
+{
+public:
+ SLANG_COM_BASE_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<ComPtr<IArtifact>> m_artifacts;
+};
+
+/*
+Discussion:
+
+It could make sense to remove the explicit variables of a ISlangBlob, and the file backing from this interface, as they could
+all be implemented as element types presumably deriving from IArtifactInstance. Doing so would mean how a 'file' is turned into
+a blob is abstracted.
+
+It may be helpful to be able to add temporary files to the artifact (such that they will be deleted when the artifact goes out of
+scope). Using an implementation of the File backed IArtifactInstance, with a suitable desc would sort of work, but it breaks the idea
+that any IArtifactInstance *represents* the contents of Artifact that contains it. Of course there could be types *not* deriving
+from IArtifactInstance that handle temporary file existance. This is probably the simplest answer to the problem.
+
+Another issue occurs around wanting to hold multiple kernels within a container. The problem here is that although through the desc
+we can identify what target a kernel is for, there is no way of telling what stage it is for.
+
+When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could actually be a zip, or directory or in memory rep)
+as the main structure. Within this it can contain kernels, and then a json manifest can describe what each of these actually are.
+
+This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code that uses this can then go through the process
+of finding, and getting the blob, and find from the manifest what it means. That does sound a little tedious though. Perhaps we just have an interface
+that handles this detail, such that we search for that first. That interface is just attached to the artifact as an element.
+*/
+
+/* Implementation of the IArtifact interface */
+class Artifact : public ComBaseObject, public IArtifact
+{
+public:
+
+ SLANG_COM_BASE_IUNKNOWN_ALL
+
+ /// 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, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); }
+ 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_parent(nullptr)
+ {}
+
+protected:
+ void* getInterface(const Guid& uuid);
+
+ Desc m_desc; ///< Description of the artifact
+ IArtifact* m_parent; ///< Artifact this artifact belongs to
+
+ String m_name; ///< Name of this artifact
+
+ List<ComPtr<ISlangUnknown>> m_items; ///< Associated items
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/compiler-core/slang-artifact-info.cpp b/source/compiler-core/slang-artifact-info.cpp
deleted file mode 100644
index 1d309e3c7..000000000
--- a/source/compiler-core/slang-artifact-info.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
-// slang-artifact-info.cpp
-#include "slang-artifact-info.h"
-
-#include "../core/slang-type-text-util.h"
-#include "../core/slang-io.h"
-
-namespace Slang {
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactInfoUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-namespace { // anonymous
-struct KindExtension
-{
- ArtifactKind kind;
- UnownedStringSlice ext;
-};
-} // anonymous
-
-#define SLANG_KIND_EXTENSION(kind, ext) \
- { ArtifactKind::kind, toSlice(ext) },
-
-static const KindExtension g_cpuKindExts[] =
-{
-#if SLANG_WINDOWS_FAMILY
- SLANG_KIND_EXTENSION(Library, "lib")
- SLANG_KIND_EXTENSION(ObjectCode, "obj")
- SLANG_KIND_EXTENSION(Executable, "exe")
- SLANG_KIND_EXTENSION(SharedLibrary, "dll")
-#else
- SLANG_KIND_EXTENSION(Library, "a")
- SLANG_KIND_EXTENSION(ObjectCode, "o")
- SLANG_KIND_EXTENSION(Executable, "")
-
-#if __CYGWIN__
- SLANG_KIND_EXTENSION(SharedLibrary, "dll")
-#elif SLANG_APPLE_FAMILY
- SLANG_KIND_EXTENSION(SharedLibrary, "dylib")
-#else
- SLANG_KIND_EXTENSION(SharedLibrary, "so")
-#endif
-
-#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)
- {
- case Kind::Library:
- case Kind::ObjectCode:
- {
- return true;
- }
- default: break;
- }
- return false;
-}
-
-/* static */bool ArtifactInfoUtil::isLinkable(const ArtifactDesc& desc)
-{
- 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
-
- // We can't *actually* link PTX or SPIR-V currently but it is in principal possible
- // so let's say we accept for now
-
- 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;
- }
-
- return true;
- }
- else if (isDerivedFrom(desc.payload, ArtifactPayload::GeneralIR))
- {
- // We'll *assume* IR is linkable
- return true;
- }
- }
- return false;
-}
-
-/* static */bool ArtifactInfoUtil::isCpuLikeTarget(const ArtifactDesc& desc)
-{
- if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike))
- {
- return isDerivedFrom(desc.payload, ArtifactPayload::CPULike);
- }
- 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;
- }
-
- return false;
-}
-
-/* static */ArtifactDesc ArtifactInfoUtil::getDescFromExtension(const UnownedStringSlice& slice)
-{
- if (slice == "slang-module" ||
- slice == "slang-lib")
- {
- 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)
- {
- // We'll assume it's for the host CPU for now..
- return ArtifactDesc::make(kindExt.kind, Payload::HostCPU);
- }
- }
-
- const auto target = TypeTextUtil::findCompileTargetFromExtension(slice);
-
- return ArtifactDesc::makeFromCompileTarget(target);
-}
-
-/* static */ArtifactDesc ArtifactInfoUtil::getDescFromPath(const UnownedStringSlice& slice)
-{
- auto extension = Path::getPathExt(slice);
- return getDescFromExtension(extension);
-}
-
-/* static*/ UnownedStringSlice ArtifactInfoUtil::getCpuExtensionForKind(Kind kind)
-{
- for (const auto& kindExt : g_cpuKindExts)
- {
- if (kind == kindExt.kind)
- {
- return kindExt.ext;
- }
- }
- 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)
-{
- 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);
- }
-
- if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike))
- {
- 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)
-{
- String name = Path::getFileName(path);
-
- const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY;
- if (isSharedLibraryPrefixPlatform)
- {
- // Strip lib prefix
- if (ArtifactInfoUtil::isCpuBinary(desc) &&
- (desc.kind == ArtifactKind::Library ||
- desc.kind == ArtifactKind::SharedLibrary))
- {
- // If it starts with lib strip it
- if (name.startsWith("lib"))
- {
- const String stripLib = name.getUnownedSlice().tail(3);
- name = stripLib;
- }
- }
- }
-
- // Strip any extension
- {
- auto descExt = ArtifactInfoUtil::getDefaultExtension(desc);
- // Strip the extension if it's a match
- if (descExt.getLength() &&
- Path::getPathExt(name) == descExt)
- {
- name = Path::getFileNameWithoutExt(name);
- }
- }
-
- return name;
-}
-
-/* static */String ArtifactInfoUtil::getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep)
-{
- UnownedStringSlice path(fileRep->getPath());
- return getBaseNameFromPath(desc, path);
-}
-
-/* static */String ArtifactInfoUtil::getBaseName(IArtifact* artifact)
-{
- if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact))
- {
- return getBaseName(artifact->getDesc(), fileRep);
- }
- // Else use the name
- return artifact->getName();
-}
-
-/* static */String ArtifactInfoUtil::getParentPath(IFileArtifactRepresentation* fileRep)
-{
- UnownedStringSlice path(fileRep->getPath());
- return Path::getParentDirectory(path);
-}
-
-/* static */String ArtifactInfoUtil::getParentPath(IArtifact* artifact)
-{
- if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact))
- {
- return getParentPath(fileRep);
- }
- return String();
-}
-
-/* static */SlangResult ArtifactInfoUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath)
-{
- outPath.Clear();
-
- UnownedStringSlice baseName;
-
- // Append the directory
- Index pos = Path::findLastSeparatorIndex(basePath);
- if (pos >= 0)
- {
- outPath.append(basePath.head(pos));
- outPath.append(Path::kPathDelimiter);
-
- baseName = basePath.tail(pos + 1);
- }
-
- if (baseName.getLength() == 0)
- {
- baseName = toSlice("unknown");
- }
-
- if (ArtifactInfoUtil::isCpuBinary(desc) &&
- (desc.kind == ArtifactKind::SharedLibrary ||
- desc.kind == ArtifactKind::Library))
- {
- const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY;
- if (isSharedLibraryPrefixPlatform)
- {
- outPath << "lib";
- outPath << baseName;
- }
- }
-
- // If there is an extension append it
- const UnownedStringSlice ext = ArtifactInfoUtil::getDefaultExtension(desc);
-
- if (ext.getLength())
- {
- outPath.appendChar('.');
- outPath.append(ext);
- }
-
- return SLANG_OK;
-}
-
-} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp
new file mode 100644
index 000000000..20480ae07
--- /dev/null
+++ b/source/compiler-core/slang-artifact-representation-impl.cpp
@@ -0,0 +1,147 @@
+// slang-artifact-representation-impl.cpp
+#include "slang-artifact-representation-impl.h"
+
+#include "../core/slang-file-system.h"
+
+#include "../core/slang-type-text-util.h"
+#include "../core/slang-io.h"
+#include "../core/slang-array-view.h"
+
+#include "slang-artifact-util.h"
+
+namespace Slang {
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void* FileArtifactRepresentation::getInterface(const Guid& guid)
+{
+ if (guid == ISlangUnknown::getTypeGuid() ||
+ guid == ICastable::getTypeGuid() ||
+ guid == IArtifactRepresentation::getTypeGuid() ||
+ guid == IFileArtifactRepresentation::getTypeGuid())
+ {
+ return static_cast<IFileArtifactRepresentation*>(this);
+ }
+ return nullptr;
+}
+
+void* FileArtifactRepresentation::getObject(const Guid& guid)
+{
+ SLANG_UNUSED(guid);
+ return nullptr;
+}
+
+ISlangMutableFileSystem* FileArtifactRepresentation::_getFileSystem()
+{
+ return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton();
+}
+
+void* FileArtifactRepresentation::castAs(const Guid& guid)
+{
+ if (auto intf = getInterface(guid))
+ {
+ return intf;
+ }
+ return getObject(guid);
+}
+
+SlangResult FileArtifactRepresentation::writeToBlob(ISlangBlob** blob)
+{
+ if (m_kind == Kind::NameOnly)
+ {
+ // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general.
+ return SLANG_E_NOT_AVAILABLE;
+ }
+
+ auto fileSystem = _getFileSystem();
+ return fileSystem->loadFile(m_path.getBuffer(), blob);
+}
+
+bool FileArtifactRepresentation::exists()
+{
+ // TODO(JS):
+ // If it's a name only it's hard to know what exists should do. It can't *check* because it relies on the 'system' doing
+ // the actual location. We could ask the IArtifactUtil, and that could change the behavior.
+ // For now we just assume it does.
+ if (m_kind == Kind::NameOnly)
+ {
+ return true;
+ }
+
+ auto fileSystem = _getFileSystem();
+
+ SlangPathType pathType;
+ const auto res = fileSystem->getPathType(m_path.getBuffer(), &pathType);
+
+ // It exists if it is a file
+ return SLANG_SUCCEEDED(res) && pathType == SLANG_PATH_TYPE_FILE;
+}
+
+FileArtifactRepresentation::~FileArtifactRepresentation()
+{
+ if (m_kind == Kind::Owned)
+ {
+ auto fileSystem = _getFileSystem();
+ fileSystem->remove(m_path.getBuffer());
+ }
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LockFile !!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void* LockFile::getInterface(const Guid& guid)
+{
+ if (guid == ISlangUnknown::getTypeGuid() ||
+ guid == ICastable::getTypeGuid() ||
+ guid == ILockFile::getTypeGuid())
+ {
+ return static_cast<ILockFile*>(this);
+ }
+ return nullptr;
+}
+
+void* LockFile::getObject(const Guid& guid)
+{
+ SLANG_UNUSED(guid);
+ return nullptr;
+}
+
+ISlangMutableFileSystem* LockFile::_getFileSystem()
+{
+ return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton();
+}
+
+void* LockFile::castAs(const Guid& guid)
+{
+ if (auto intf = getInterface(guid))
+ {
+ return intf;
+ }
+ return getObject(guid);
+}
+
+const char* LockFile::getPath()
+{
+ return (m_path.getLength() > 0) ? m_path.getBuffer() : nullptr;
+}
+
+ISlangMutableFileSystem* LockFile::getFileSystem()
+{
+ return m_fileSystem;
+}
+
+LockFile::~LockFile()
+{
+ if (m_path.getLength() > 0)
+ {
+ auto fileSystem = _getFileSystem();
+ fileSystem->remove(m_path.getBuffer());
+ }
+}
+
+void LockFile::disown()
+{
+ m_path = String();
+ m_fileSystem.setNull();
+}
+
+} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h
new file mode 100644
index 000000000..9c2066e55
--- /dev/null
+++ b/source/compiler-core/slang-artifact-representation-impl.h
@@ -0,0 +1,94 @@
+// slang-artifact-representation-impl.h
+#ifndef SLANG_ARTIFACT_REPRESENTATION_IMPL_H
+#define SLANG_ARTIFACT_REPRESENTATION_IMPL_H
+
+#include "slang-artifact-representation.h"
+
+#include "../../slang-com-helper.h"
+#include "../../slang-com-ptr.h"
+
+#include "../core/slang-com-object.h"
+
+namespace Slang
+{
+
+/* An implementation of ILockFile */
+class LockFile : public ComBaseObject, public ILockFile
+{
+public:
+ SLANG_COM_BASE_IUNKNOWN_ALL
+
+ // ICastable
+ SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
+
+ // ILockFile
+ SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE;
+ SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE;
+ SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE;
+
+ /// Ctor
+ LockFile(String path, ISlangMutableFileSystem* fileSystem) :
+ m_path(path),
+ m_fileSystem(fileSystem)
+ {
+ }
+
+ ~LockFile();
+
+protected:
+ void* getInterface(const Guid& uuid);
+ void* getObject(const Guid& uuid);
+
+ ISlangMutableFileSystem* _getFileSystem();
+
+ String m_path;
+ ComPtr<ISlangMutableFileSystem> m_fileSystem;
+};
+
+/*
+A representation of an artifact that is held in a file */
+class FileArtifactRepresentation : public ComBaseObject, public IFileArtifactRepresentation
+{
+public:
+ typedef IFileArtifactRepresentation::Kind Kind;
+
+ SLANG_COM_BASE_IUNKNOWN_ALL
+
+ // ICastable
+ SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
+
+ // IArtifactRepresentation
+ SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) SLANG_OVERRIDE;
+ SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE;
+
+ // IFileArtifactRepresentation
+ virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; }
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); }
+ virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; }
+ virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; }
+
+ FileArtifactRepresentation(Kind kind, String path, ILockFile* lockFile, ISlangMutableFileSystem* fileSystem):
+ m_kind(kind),
+ m_path(path),
+ m_lockFile(lockFile),
+ m_fileSystem(fileSystem)
+ {
+ }
+
+ ~FileArtifactRepresentation();
+
+protected:
+ void* getInterface(const Guid& uuid);
+ void* getObject(const Guid& uuid);
+
+ ISlangMutableFileSystem* _getFileSystem();
+
+ Kind m_kind;
+ String m_path;
+ ComPtr<ILockFile> m_lockFile;
+ ComPtr<ISlangMutableFileSystem> m_fileSystem;
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h
new file mode 100644
index 000000000..00a5c9e5b
--- /dev/null
+++ b/source/compiler-core/slang-artifact-representation.h
@@ -0,0 +1,52 @@
+// slang-artifact-representation.h
+#ifndef SLANG_ARTIFACT_REPRESENTATION_H
+#define SLANG_ARTIFACT_REPRESENTATION_H
+
+#include "slang-artifact.h"
+
+namespace Slang
+{
+
+/* A lock file */
+class ILockFile : public ICastable
+{
+ SLANG_COM_INTERFACE(0x9177ea36, 0xa608, 0x4490, { 0x87, 0xf0, 0xf3, 0x93, 0x9, 0x7d, 0x36, 0xce })
+
+ /// The path to a lock file.
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
+ /// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
+ virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0;
+
+ /// Makes the lock file no longer owned. Doing so will make the path nullptr, and getFileSystem nullptr.
+ virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0;
+};
+
+/*
+A representation as a file. If it is a temporary file, it will likely disappear.
+A file representation does not have to be a representation of a file on the file system.
+That is indicated by getFileSystem returning nullptr. Then the path is the path on the *actual* OS file system.
+This distinction is important as it is sometimes necessary to have an artifact stored on the OS file system
+to be usable. */
+class IFileArtifactRepresentation : public IArtifactRepresentation
+{
+public:
+ enum class Kind
+ {
+ Reference, ///< References a file on the file system
+ Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope
+ NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob.
+ };
+
+ /// The the kind of file.
+ virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0;
+ /// The path (on the file system)
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
+ /// Get the lock file. Return nullptr if there is no lock file.
+ virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() = 0;
+ /// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
+ virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0;
+};
+
+} // namespace Slang
+
+#endif
diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp
index 5c1641f7f..9a8194969 100644
--- a/source/compiler-core/slang-artifact-util.cpp
+++ b/source/compiler-core/slang-artifact-util.cpp
@@ -1,7 +1,10 @@
// slang-artifact.cpp
#include "slang-artifact-util.h"
-#include "slang-artifact-info.h"
+#include "slang-artifact-impl.h"
+#include "slang-artifact-representation-impl.h"
+
+#include "slang-artifact-desc-util.h"
#include "../core/slang-file-system.h"
#include "../core/slang-io.h"
@@ -31,7 +34,6 @@ void* ArtifactUtilImpl::getInterface(const Guid& guid)
return nullptr;
}
-
SlangResult ArtifactUtilImpl::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact)
{
String name;
@@ -93,7 +95,7 @@ SlangResult ArtifactUtilImpl::calcArtifactPath(const ArtifactDesc& desc, const c
UnownedStringSlice basePath(inBasePath);
StringBuilder path;
- SLANG_RETURN_ON_FAIL(ArtifactInfoUtil::calcPathForDesc(desc, basePath, path));
+ SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path));
auto blob = new StringBlob(path);
blob->addRef();
@@ -150,4 +152,9 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa
return SLANG_OK;
}
+ArtifactDesc ArtifactUtilImpl::makeDescFromCompileTarget(SlangCompileTarget target)
+{
+ return ArtifactDescUtil::makeDescFromCompileTarget(target);
+}
+
} // namespace Slang
diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h
index f60578d14..f9070a76e 100644
--- a/source/compiler-core/slang-artifact-util.h
+++ b/source/compiler-core/slang-artifact-util.h
@@ -3,6 +3,7 @@
#define SLANG_ARTIFACT_UTIL_H
#include "slang-artifact.h"
+#include "slang-artifact-representation.h"
namespace Slang
{
@@ -34,6 +35,8 @@ class IArtifactUtil : public ISlangUnknown
/// Default implementation of getting
virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFileRep) = 0;
+
+ virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) = 0;
};
class ArtifactUtilImpl : public IArtifactUtil
@@ -67,6 +70,8 @@ public:
virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE;
+
static IArtifactUtil* getSingleton() { return &g_singleton; }
protected:
diff --git a/source/compiler-core/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp
deleted file mode 100644
index cefb8d753..000000000
--- a/source/compiler-core/slang-artifact.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-// slang-artifact.cpp
-#include "slang-artifact.h"
-
-#include "slang-artifact-info.h"
-
-#include "../core/slang-file-system.h"
-
-#include "../core/slang-type-text-util.h"
-#include "../core/slang-io.h"
-#include "../core/slang-array-view.h"
-
-#include "slang-artifact-util.h"
-
-namespace Slang {
-
-namespace { // anonymous
-
-struct HierarchicalEnumEntry
-{
- Index value;
- Index parent;
- const char* name;
-};
-
-static bool _isHierarchicalEnumOk(ConstArrayView<HierarchicalEnumEntry> entries, Count countOf)
-{
- // All values should be set
- if (entries.getCount() != countOf)
- {
- return false;
- }
-
- List<uint8_t> 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 <typename T>
-struct HierarchicalEnumTable
-{
- HierarchicalEnumTable(ConstArrayView<HierarchicalEnumEntry> 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<HierarchicalEnumEntry> _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<ENUM_TYPE> 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)
- {
- case SLANG_TARGET_UNKNOWN: return make(Kind::Unknown, Payload::None, Style::Unknown, 0);
- case SLANG_TARGET_NONE: return make(Kind::None, Payload::None, Style::Unknown, 0);
- case SLANG_GLSL_VULKAN:
- case SLANG_GLSL_VULKAN_ONE_DESC:
- case SLANG_GLSL:
- {
- // 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::Source, Payload::GLSL, 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::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::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::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::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::HostCallable, Payload::HostCPU, Style::Host, 0);
- default: break;
- }
-
- SLANG_UNEXPECTED("Unhandled type");
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* FileArtifactRepresentation::getInterface(const Guid& guid)
-{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid() ||
- guid == IArtifactRepresentation::getTypeGuid() ||
- guid == IFileArtifactRepresentation::getTypeGuid())
- {
- return static_cast<IFileArtifactRepresentation*>(this);
- }
- return nullptr;
-}
-
-void* FileArtifactRepresentation::getObject(const Guid& guid)
-{
- SLANG_UNUSED(guid);
- return nullptr;
-}
-
-ISlangMutableFileSystem* FileArtifactRepresentation::_getFileSystem()
-{
- return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton();
-}
-
-void* FileArtifactRepresentation::castAs(const Guid& guid)
-{
- if (auto intf = getInterface(guid))
- {
- return intf;
- }
- return getObject(guid);
-}
-
-SlangResult FileArtifactRepresentation::writeToBlob(ISlangBlob** blob)
-{
- if (m_kind == Kind::NameOnly)
- {
- // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general.
- return SLANG_E_NOT_AVAILABLE;
- }
-
- auto fileSystem = _getFileSystem();
- return fileSystem->loadFile(m_path.getBuffer(), blob);
-}
-
-bool FileArtifactRepresentation::exists()
-{
- // TODO(JS):
- // If it's a name only it's hard to know what exists should do. It can't *check* because it relies on the 'system' doing
- // the actual location. We could ask the IArtifactUtil, and that could change the behavior.
- // For now we just assume it does.
- if (m_kind == Kind::NameOnly)
- {
- return true;
- }
-
- auto fileSystem = _getFileSystem();
-
- SlangPathType pathType;
- const auto res = fileSystem->getPathType(m_path.getBuffer(), &pathType);
-
- // It exists if it is a file
- return SLANG_SUCCEEDED(res) && pathType == SLANG_PATH_TYPE_FILE;
-}
-
-FileArtifactRepresentation::~FileArtifactRepresentation()
-{
- if (m_kind == Kind::Owned)
- {
- auto fileSystem = _getFileSystem();
- fileSystem->remove(m_path.getBuffer());
- }
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LockFile !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* LockFile::getInterface(const Guid& guid)
-{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid() ||
- guid == ILockFile::getTypeGuid())
- {
- return static_cast<ILockFile*>(this);
- }
- return nullptr;
-}
-
-void* LockFile::getObject(const Guid& guid)
-{
- SLANG_UNUSED(guid);
- return nullptr;
-}
-
-ISlangMutableFileSystem* LockFile::_getFileSystem()
-{
- return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton();
-}
-
-void* LockFile::castAs(const Guid& guid)
-{
- if (auto intf = getInterface(guid))
- {
- return intf;
- }
- return getObject(guid);
-}
-
-const char* LockFile::getPath()
-{
- return (m_path.getLength() > 0) ? m_path.getBuffer() : nullptr;
-}
-
-ISlangMutableFileSystem* LockFile::getFileSystem()
-{
- return m_fileSystem;
-}
-
-LockFile::~LockFile()
-{
- if (m_path.getLength() > 0)
- {
- auto fileSystem = _getFileSystem();
- fileSystem->remove(m_path.getBuffer());
- }
-}
-
-void LockFile::disown()
-{
- m_path = String();
- m_fileSystem.setNull();
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void* ArtifactList::getInterface(const Guid& guid)
-{
- if (guid == ISlangUnknown::getTypeGuid() ||
- guid == ICastable::getTypeGuid() ||
- guid == IArtifactList::getTypeGuid())
- {
- return static_cast<IArtifactList*>(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<IArtifact>(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)
-{
- if (uuid == ISlangUnknown::getTypeGuid() || uuid == IArtifact::getTypeGuid())
- {
- return static_cast<IArtifact*>(this);
- }
- return nullptr;
-}
-
-bool Artifact::exists()
-{
- for (ISlangUnknown* item : m_items)
- {
- ComPtr<ICastable> castable;
-
- if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- auto rep = as<IArtifactRepresentation>(castable);
- 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 (as<IArtifactAssociated>(castable))
- {
- continue;
- }
- }
-
- // It can't be IArtifactRepresentation or IArtifactAssociated, so we assume means it exists
- return true;
- }
-
- return false;
-}
-
-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<ISlangUnknown>(intf));
-}
-
-void Artifact::removeItemAt(Index i)
-{
- m_items.removeAt(i);
-}
-
-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).
- cast->release();
- return cast;
- }
- }
- return nullptr;
-}
-
-void* Artifact::findItemObject(const Guid& classGuid)
-{
- for (ISlangUnknown* intf : m_items)
- {
- ComPtr<ICastable> castable;
- if (SLANG_SUCCEEDED(intf->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable)
- {
- 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 obj;
- }
- }
- }
- return nullptr;
-}
-
-SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep)
-{
- auto util = ArtifactUtilImpl::getSingleton();
- return util->requireFileDefaultImpl(this, keep, outFileRep);
-}
-
-SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
-{
- // If we have a blob just return it
- if (auto blob = findItem<ISlangBlob>(this))
- {
- blob->addRef();
- *outBlob = blob;
- return SLANG_OK;
- }
-
- ComPtr<ISlangBlob> blob;
-
- // Look for a representation that we can serialize into a blob
- for (ISlangUnknown* intf : m_items)
- {
- ComPtr<IArtifactRepresentation> rep;
- if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep)
- {
- SlangResult res = rep->writeToBlob(blob.writeRef());
- if (SLANG_SUCCEEDED(res) && blob)
- {
- break;
- }
- }
- }
-
- // Wasn't able to construct
- if (!blob)
- {
- return SLANG_E_NOT_FOUND;
- }
-
- // Put in cache
- if (canKeep(keep))
- {
- addItem(blob);
- }
-
- *outBlob = blob.detach();
- return SLANG_OK;
-}
-
-} // namespace Slang
diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h
index 88993773d..86b08dbb9 100644
--- a/source/compiler-core/slang-artifact.h
+++ b/source/compiler-core/slang-artifact.h
@@ -5,9 +5,7 @@
#include "../core/slang-basic.h"
#include "../../slang-com-helper.h"
-#include "../../slang-com-ptr.h"
-#include "../core/slang-com-object.h"
#include "../core/slang-destroyable.h"
namespace Slang
@@ -53,13 +51,6 @@ enum class ArtifactKind : uint8_t
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);
/* Payload.
@@ -120,13 +111,6 @@ enum class ArtifactPayload : uint8_t
CountOf,
};
-/// 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);
-
/* Style.
NOTE!
@@ -148,13 +132,6 @@ enum class ArtifactStyle : uint8_t
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
{
@@ -186,9 +163,6 @@ public:
bool operator==(const This& rhs) const { return kind == rhs.kind && payload == rhs.payload && style == rhs.style && flags == rhs.flags; }
bool operator!=(const This& rhs) const { return !(*this == rhs); }
- /// Given a code gen target, get the equivalent ArtifactDesc
- static This makeFromCompileTarget(SlangCompileTarget target);
-
/// Construct from the elements
static This make(Kind inKind, Payload inPayload, Style inStyle = Style::Unknown, Flags flags = 0) { return This{ inKind, inPayload, inStyle, flags }; }
@@ -225,6 +199,8 @@ inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked)
return r;
}
+// Forward declare
+class IFileArtifactRepresentation;
// Controls what items can be kept.
enum class ArtifactKeep
@@ -241,77 +217,6 @@ SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(Artif
/// Returns the keep type for an intermediate
SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; }
-enum ArtifactPathType
-{
- None,
- Temporary, ///< Is a temporary file
- Existing, ///< Is an existing file
-};
-
-/* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far
-as
-
-* IArtifactRepresentation can be queried for it's underlying object class
-* Can optionally serialize into a blob
-*/
-class IArtifactRepresentation : public ICastable
-{
- SLANG_COM_INTERFACE(0x311457a8, 0x1796, 0x4ebb, { 0x9a, 0xfc, 0x46, 0xa5, 0x44, 0xc7, 0x6e, 0xa9 })
-
- /// Convert the instance into a serializable blob.
- /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) = 0;
-
- /// Returns true if this representation exists and is available for use.
- virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0;
-};
-
-/* A lock file */
-class ILockFile : public ICastable
-{
- SLANG_COM_INTERFACE(0x9177ea36, 0xa608, 0x4490, { 0x87, 0xf0, 0xf3, 0x93, 0x9, 0x7d, 0x36, 0xce })
-
- /// The path to a lock file.
- virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
- /// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
- virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0;
-
- /// Makes the lock file no longer owned. Doing so will make the path nullptr, and getFileSystem nullptr.
- virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0;
-};
-
-/*
-A representation as a file. If it is a temporary file, it will likely disappear.
-A file representation does not have to be a representation of a file on the file system.
-That is indicated by getFileSystem returning nullptr. Then the path is the path on the *actual* OS file system.
-This distinction is important as it is sometimes necessary to have an artifact stored on the OS file system
-to be usable. */
-struct IFileArtifactRepresentation : public IArtifactRepresentation
-{
- enum class Kind
- {
- Reference, ///< References a file on the file system
- Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope
- NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob.
- };
-
- /// The the kind of file.
- virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0;
- /// The path (on the file system)
- virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0;
- /// Get the lock file. Return nullptr if there is no lock file.
- virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() = 0;
- /// Optional, the file system it's on. If nullptr its on 'regular' OS file system.
- virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 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.
An abstraction is desirable here, because depending on the compiler the artifact/s could be
@@ -359,7 +264,6 @@ public:
typedef ArtifactStyle Style;
typedef ArtifactFlags Flags;
typedef ArtifactKeep Keep;
- typedef ArtifactPathType PathType;
/// Get the Desc defining the contents of the artifact
virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() = 0;
@@ -420,180 +324,32 @@ class IArtifactList : public ICastable
virtual SLANG_NO_THROW void SLANG_MCALL clear() = 0;
};
-class ArtifactList : public ComBaseObject, public IArtifactList
-{
-public:
- SLANG_COM_BASE_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<ComPtr<IArtifact>> m_artifacts;
-};
-
-/*
-Discussion:
-
-It could make sense to remove the explicit variables of a ISlangBlob, and the file backing from this interface, as they could
-all be implemented as element types presumably deriving from IArtifactInstance. Doing so would mean how a 'file' is turned into
-a blob is abstracted.
-
-It may be helpful to be able to add temporary files to the artifact (such that they will be deleted when the artifact goes out of
-scope). Using an implementation of the File backed IArtifactInstance, with a suitable desc would sort of work, but it breaks the idea
-that any IArtifactInstance *represents* the contents of Artifact that contains it. Of course there could be types *not* deriving
-from IArtifactInstance that handle temporary file existance. This is probably the simplest answer to the problem.
-
-Another issue occurs around wanting to hold multiple kernels within a container. The problem here is that although through the desc
-we can identify what target a kernel is for, there is no way of telling what stage it is for.
+/* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far
+as
-When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could actually be a zip, or directory or in memory rep)
-as the main structure. Within this it can contain kernels, and then a json manifest can describe what each of these actually are.
-
-This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code that uses this can then go through the process
-of finding, and getting the blob, and find from the manifest what it means. That does sound a little tedious though. Perhaps we just have an interface
-that handles this detail, such that we search for that first. That interface is just attached to the artifact as an element.
+* IArtifactRepresentation can be queried for it's underlying object class
+* Can optionally serialize into a blob
*/
-
-/* Implementation of the IArtifact interface */
-class Artifact : public ComBaseObject, public IArtifact
-{
-public:
-
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- /// 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, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); }
- 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_parent(nullptr)
- {}
-
-protected:
- void* getInterface(const Guid& uuid);
-
- Desc m_desc; ///< Description of the artifact
- IArtifact* m_parent; ///< Artifact this artifact belongs to
-
- String m_name; ///< Name of this artifact
-
- List<ComPtr<ISlangUnknown>> m_items; ///< Associated items
-};
-
-/* An implementation of ILockFile */
-class LockFile : public ComBaseObject, public ILockFile
+class IArtifactRepresentation : public ICastable
{
-public:
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- // ICastable
- SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
-
- // ILockFile
- SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE;
- SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE;
- SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE;
-
- /// Ctor
- LockFile(String path, ISlangMutableFileSystem* fileSystem):
- m_path(path),
- m_fileSystem(fileSystem)
- {
- }
-
- ~LockFile();
-
-protected:
- void* getInterface(const Guid& uuid);
- void* getObject(const Guid& uuid);
+ SLANG_COM_INTERFACE(0x311457a8, 0x1796, 0x4ebb, { 0x9a, 0xfc, 0x46, 0xa5, 0x44, 0xc7, 0x6e, 0xa9 })
- ISlangMutableFileSystem* _getFileSystem();
+ /// Convert the instance into a serializable blob.
+ /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) = 0;
- String m_path;
- ComPtr<ISlangMutableFileSystem> m_fileSystem;
+ /// Returns true if this representation exists and is available for use.
+ virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0;
};
-/*
-A representation of an artifact that is held in a file */
-class FileArtifactRepresentation : public ComBaseObject, public IFileArtifactRepresentation
+/* 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
{
-public:
- SLANG_COM_BASE_IUNKNOWN_ALL
-
- // ICastable
- SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
-
- // IArtifactRepresentation
- SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) SLANG_OVERRIDE;
- SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE;
-
- // IFileArtifactRepresentation
- virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; }
- virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); }
- virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; }
- virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; }
-
- FileArtifactRepresentation(IFileArtifactRepresentation::Kind kind, String path, ILockFile* lockFile, ISlangMutableFileSystem* fileSystem):
- m_kind(kind),
- m_path(path),
- m_lockFile(lockFile),
- m_fileSystem(fileSystem)
- {
- }
-
- ~FileArtifactRepresentation();
-
-protected:
- void* getInterface(const Guid& uuid);
- void* getObject(const Guid& uuid);
-
- ISlangMutableFileSystem* _getFileSystem();
-
- IFileArtifactRepresentation::Kind m_kind;
- String m_path;
- ComPtr<ILockFile> m_lockFile;
- ComPtr<ISlangMutableFileSystem> m_fileSystem;
+ SLANG_COM_INTERFACE(0xafc0e4db, 0x16d4, 0x4d7a, { 0x93, 0x5f, 0x3e, 0x47, 0x7a, 0x23, 0x2a, 0x7f })
};
+
// Helper template to make finding an item more simple
// There isn't a problem if we only have a forward declaration, because in that case T::getTypeGuid can't work.
SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const ISlangUnknown* intf)
diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp
index 6375ba23a..8467cbbdc 100644
--- a/source/compiler-core/slang-dxc-compiler.cpp
+++ b/source/compiler-core/slang-dxc-compiler.cpp
@@ -19,7 +19,7 @@
#include "../core/slang-shared-library.h"
-#include "../compiler-core/slang-artifact-info.h"
+#include "../compiler-core/slang-artifact-desc-util.h"
// Enable calling through to `dxc` to
// generate code on Windows.
@@ -83,7 +83,7 @@ static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlic
static UnownedStringSlice _addName(IArtifact* artifact, StringSlicePool& pool)
{
- return _addName(ArtifactInfoUtil::getBaseName(artifact).getUnownedSlice(), pool);
+ return _addName(ArtifactDescUtil::getBaseName(artifact).getUnownedSlice(), pool);
}
class DxcIncludeHandler : public IDxcIncludeHandler
diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp
index bbf9eaf26..aee3b1bcc 100644
--- a/source/compiler-core/slang-gcc-compiler-util.cpp
+++ b/source/compiler-core/slang-gcc-compiler-util.cpp
@@ -10,7 +10,7 @@
#include "../core/slang-char-util.h"
#include "../core/slang-string-slice-pool.h"
-#include "slang-artifact-info.h"
+#include "slang-artifact-desc-util.h"
namespace Slang
{
@@ -635,15 +635,15 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse
{
const auto desc = artifact->getDesc();
// If it's a library for CPU types, try and use it
- if (ArtifactInfoUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library)
+ if (ArtifactDescUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library)
{
ComPtr<IFileArtifactRepresentation> fileRep;
// Get the name and path (can be empty) to the library
SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef()));
- libPathPool.add(ArtifactInfoUtil::getParentPath(fileRep));
- cmdLine.addPrefixPathArg("-l", ArtifactInfoUtil::getBaseName(artifact->getDesc(), fileRep));
+ libPathPool.add(ArtifactDescUtil::getParentPath(fileRep));
+ cmdLine.addPrefixPathArg("-l", ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep));
}
}
diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp
index a2e9c78d1..a4b4e7bc6 100644
--- a/source/compiler-core/slang-visual-studio-compiler-util.cpp
+++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp
@@ -12,7 +12,7 @@
#endif
#include "../core/slang-io.h"
-#include "slang-artifact-info.h"
+#include "slang-artifact-desc-util.h"
namespace Slang
{
@@ -264,15 +264,15 @@ namespace Slang
{
auto desc = artifact->getDesc();
- if (ArtifactInfoUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library)
+ if (ArtifactDescUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library)
{
// Get the libray name and path
ComPtr<IFileArtifactRepresentation> fileRep;
SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef()));
- libPathPool.add(ArtifactInfoUtil::getParentPath(fileRep));
+ libPathPool.add(ArtifactDescUtil::getParentPath(fileRep));
// We need the extension for windows
- cmdLine.addArg(ArtifactInfoUtil::getBaseName(artifact->getDesc(), fileRep) + ".lib");
+ cmdLine.addArg(ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep) + ".lib");
}
}