summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-artifact.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/compiler-core/slang-artifact.cpp')
-rw-r--r--source/compiler-core/slang-artifact.cpp630
1 files changed, 0 insertions, 630 deletions
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