diff options
28 files changed, 1135 insertions, 380 deletions
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 69a9b66f1..314703c0b 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -3,6 +3,8 @@ #include "slang-artifact-representation.h" +#include "slang-artifact-impl.h" + #include "../core/slang-type-text-util.h" #include "../core/slang-io.h" @@ -170,9 +172,7 @@ bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) { return g_table##ENUM_TYPE.i x(Executable, BinaryLike) \ x(SharedLibrary, BinaryLike) \ x(HostCallable, BinaryLike) \ - \ - x(DebugInfo, Base) \ - x(Diagnostics, Base) + x(Instance, Base) #define SLANG_ARTIFACT_KIND_ENTRY(TYPE, PARENT) { Index(ArtifactKind::TYPE), Index(ArtifactKind::PARENT), #TYPE }, @@ -212,7 +212,12 @@ SLANG_HIERARCHICAL_ENUM(ArtifactKind, SLANG_ARTIFACT_KIND, SLANG_ARTIFACT_KIND_E x(SlangIR, GeneralIR) \ x(LLVMIR, GeneralIR) \ x(AST, Base) \ - x(SlangAST, AST) + x(SlangAST, AST) \ + x(CompileResults, Base) \ + x(MetaData, Base) \ + x(PostEmitMetadata, MetaData) \ + x(DebugInfo, MetaData) \ + x(Diagnostics, MetaData) #define SLANG_ARTIFACT_PAYLOAD_ENTRY(TYPE, PARENT) { Index(ArtifactPayload::TYPE), Index(ArtifactPayload::PARENT), #TYPE }, @@ -309,7 +314,6 @@ static const KindExtension g_cpuKindExts[] = #endif }; - /* static */ bool ArtifactDescUtil::isCpuBinary(const ArtifactDesc& desc) { return isDerivedFrom(desc.kind, ArtifactKind::BinaryLike) && isDerivedFrom(desc.payload, ArtifactPayload::CPULike); @@ -686,4 +690,10 @@ UnownedStringSlice ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& des return SLANG_OK; } +/* static */ComPtr<IArtifactContainer> ArtifactDescUtil::createContainer(const ArtifactDesc& desc) +{ + const auto containerDesc = ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::CompileResults, desc.style); + return ArtifactContainer::create(containerDesc); +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h index ccd380892..604d5a4ce 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -87,6 +87,9 @@ struct ArtifactDescUtil /// Make ArtifactDesc from target static ArtifactDesc makeDescFromCompileTarget(SlangCompileTarget target); + + /// Create an empty container which is compatible with the desc + static ComPtr<IArtifactContainer> createContainer(const ArtifactDesc& desc); }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index 73927db96..061aa9ee7 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -4,90 +4,44 @@ #include "slang-artifact-representation.h" #include "slang-artifact-util.h" +#include "slang-artifact-desc-util.h" #include "../core/slang-castable-list-impl.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; -} +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void* ArtifactList::getObject(const Guid& guid) +IArtifactHandler* Artifact::_getHandler() { - // For now we can't cast to an object - SLANG_UNUSED(guid); - return nullptr; + // TODO(JS): For now we just use the default handler, but in the future this should probably be a member + return DefaultArtifactHandler::getSingleton(); } -void* ArtifactList::castAs(const Guid& guid) +void* Artifact::castAs(const Guid& guid) { - if (auto intf = getInterface(guid)) + if (auto ptr = getInterface(guid)) { - return intf; + return ptr; } 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) +void* Artifact::getInterface(const Guid& uuid) { - if (m_parent == parent) + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ICastable::getTypeGuid() || + uuid == IArtifact::getTypeGuid()) { - return; - } - - for (IArtifact* artifact : m_artifacts) - { - artifact->setParent(artifact); + return static_cast<IArtifact*>(this); } + return nullptr; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ - -void* Artifact::getInterface(const Guid& uuid) +void* Artifact::getObject(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || uuid == IArtifact::getTypeGuid()) - { - return static_cast<IArtifact*>(this); - } + SLANG_UNUSED(uuid); return nullptr; } @@ -113,50 +67,43 @@ bool Artifact::exists() return false; } -SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) +SlangResult Artifact::requireFile(Keep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) { - auto util = ArtifactUtilImpl::getSingleton(); - return util->requireFileDefaultImpl(this, keep, outFileRep); + auto handler = _getHandler(); + return handler->getOrCreateFileRepresentation(this, keep, fileSystem, outFileRep); } -SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) +SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) { - // If we have a blob just return it - if (auto blob = (ISlangBlob*)findRepresentation(ISlangBlob::getTypeGuid())) - { - blob->addRef(); - *outBlob = blob; - return SLANG_OK; - } + auto handler = _getHandler(); - ComPtr<ISlangBlob> blob; + ComPtr<ICastable> castable; + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangSharedLibrary::getTypeGuid(), keep, castable.writeRef())); + + ISlangSharedLibrary* lib = as<ISlangSharedLibrary>(castable); + lib->addRef(); - // Look for a representation that we can serialize into a blob - for (auto rep : m_representations.getView()) - { - if (auto artifactRep = as<IArtifactRepresentation>(rep)) - { - SlangResult res = artifactRep->writeToBlob(blob.writeRef()); - if (SLANG_SUCCEEDED(res) && blob) - { - break; - } - } - } - - // Wasn't able to construct - if (!blob) - { - return SLANG_E_NOT_FOUND; - } + *outSharedLibrary = lib; + return SLANG_OK; +} - // Put in cache - if (canKeep(keep)) - { - addRepresentationUnknown(blob); - } +SlangResult Artifact::getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) +{ + auto handler = _getHandler(); + return handler->getOrCreateRepresentation(this, typeGuid, keep, outCastable); +} - *outBlob = blob.detach(); +SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) +{ + auto handler = _getHandler(); + + ComPtr<ICastable> castable; + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangBlob::getTypeGuid(), keep, castable.writeRef())); + + ISlangBlob* blob = as<ISlangBlob>(castable); + blob->addRef(); + + *outBlob = blob; return SLANG_OK; } @@ -171,6 +118,12 @@ void* Artifact::findAssociated(const Guid& guid) return m_associated.find(guid); } + +ICastable* Artifact::findAssociatedWithPredicate(ICastableList::FindFunc findFunc, void* data) +{ + return m_associated.findWithPredicate(findFunc, data); +} + ICastableList* Artifact::getAssociated() { return m_associated.requireList(); @@ -218,24 +171,164 @@ void* Artifact::findRepresentation(const Guid& guid) return m_representations.find(guid); } -ICastableList* Artifact::getRepresentations() +ICastable* Artifact::findRepresentationWithPredicate(ICastableList::FindFunc findFunc, void* data) +{ + return m_representations.findWithPredicate(findFunc, data); +} + +Slice<ICastable*> Artifact::getRepresentations() +{ + const auto view = m_representations.getView(); + return Slice<ICastable*>(view.getBuffer(), view.getCount()); +} + +ICastableList* Artifact::getRepresentationList() { return m_representations.requireList(); } -IArtifactList* Artifact::getChildren() +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactContainer !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ArtifactContainer::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifact::getTypeGuid() || + guid == IArtifactContainer::getTypeGuid()) + { + return static_cast<IArtifactContainer*>(this); + } + return nullptr; +} + +void* ArtifactContainer::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +void* ArtifactContainer::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + +void ArtifactContainer::setChildren(IArtifact** children, Count count) +{ + m_expandResult = SLANG_OK; + + m_children.clearAndDeallocate(); + m_children.setCount(count); + + ComPtr<IArtifact>* dst = m_children.getBuffer(); + for (Index i = 0; i < count; ++i) + { + dst[i] = children[i]; + } +} + +SlangResult ArtifactContainer::expandChildren() +{ + auto handler = _getHandler(); + return handler->expandChildren(this); +} + +Slice<IArtifact*> ArtifactContainer::getChildren() +{ + _requireChildren(); + + return Slice<IArtifact*>((IArtifact**)m_children.getBuffer(), m_children.getCount()); +} + +void ArtifactContainer::addChild(IArtifact* artifact) +{ + SLANG_ASSERT(artifact); + SLANG_ASSERT(m_children.indexOf(artifact) < 0); + + _requireChildren(); + + m_children.add(ComPtr<IArtifact>(artifact)); +} + +void ArtifactContainer::removeChildAt(Index index) { - // If it has already evaluated, return it. - if (m_children) + _requireChildren(); + + m_children.removeAt(index); +} + +void ArtifactContainer::clearChildren() +{ + _requireChildren(); + + m_children.clearAndDeallocate(); +} + +IArtifact* ArtifactContainer::findChildByDesc(const ArtifactDesc& desc) +{ + _requireChildren(); + + for (IArtifact* artifact : m_children) { - return m_children; + if (artifact->getDesc() == desc) + { + return artifact; + } } + return nullptr; +} - auto util = ArtifactUtilImpl::getSingleton(); - util->getChildrenDefaultImpl(this, m_children.writeRef()); +IArtifact* ArtifactContainer::findChildByDerivedDesc(const ArtifactDesc& desc) +{ + _requireChildren(); - return m_children; + for (IArtifact* artifact : m_children) + { + const ArtifactDesc artifactDesc = artifact->getDesc(); + // TODO(JS): Currently this ignores flags in desc. That may or may not be right + // long term. + if (isDerivedFrom(artifactDesc.kind, desc.kind) && + isDerivedFrom(artifactDesc.payload, desc.payload) && + isDerivedFrom(artifactDesc.style, desc.style)) + { + return artifact; + } + } + return nullptr; } +IArtifact* ArtifactContainer::findChildByName(const char* name) +{ + _requireChildren(); + + for (IArtifact* artifact : m_children) + { + const char* artifactName = artifact->getName(); + + if (artifactName == name || + ::strcmp(artifactName, name) == 0) + { + return artifact; + } + } + return nullptr; +} + +IArtifact* ArtifactContainer::findChildByPredicate(FindFunc func, void* data) +{ + _requireChildren(); + + for (IArtifact* artifact : m_children) + { + if (func(artifact, data)) + { + return artifact; + } + } + return nullptr; +} } // namespace Slang diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index e4db46222..8b15d0664 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -14,42 +14,6 @@ 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: @@ -62,34 +26,58 @@ as the main structure. Within this it can contain kernels, and then a json manif 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 +Note: Implementation of the IArtifact interface. We derive from IArtifactContainer, such that we don't have the +irritating multiple inheritance issue. */ +class Artifact : public ComBaseObject, public IArtifactContainer { public: SLANG_COM_BASE_IUNKNOWN_ALL - /// IArtifact impl + /// ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + /// 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 SlangResult SLANG_MCALL requireFile(Keep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; + virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(ICastable* castable) SLANG_OVERRIDE; - virtual void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) SLANG_OVERRIDE; - virtual ICastableList* SLANG_MCALL getAssociated() SLANG_OVERRIDE; + virtual SLANG_NO_THROW void* SLANG_MCALL findAssociated(const Guid& unk) SLANG_OVERRIDE; + virtual SLANG_NO_THROW ICastableList* SLANG_MCALL getAssociated() SLANG_OVERRIDE; + virtual SLANG_NO_THROW ICastable* SLANG_MCALL findAssociatedWithPredicate(ICastableList::FindFunc findFunc, void* data) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) SLANG_OVERRIDE; - virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) SLANG_OVERRIDE; - virtual ICastableList* SLANG_MCALL getRepresentations() SLANG_OVERRIDE; - - virtual IArtifactList* SLANG_MCALL getChildren() SLANG_OVERRIDE; + virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(const Guid& guid) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Slice<ICastable*> SLANG_MCALL getRepresentations() SLANG_OVERRIDE; + virtual SLANG_NO_THROW ICastableList* SLANG_MCALL getRepresentationList() SLANG_OVERRIDE; + virtual SLANG_NO_THROW ICastable* SLANG_MCALL findRepresentationWithPredicate(ICastableList::FindFunc findFunc, void* data) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; + + // IArtifactCollection (Not implemented) + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE { SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact** children, Count count) SLANG_OVERRIDE { SLANG_UNUSED(children); SLANG_UNUSED(count); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() SLANG_OVERRIDE { SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() SLANG_OVERRIDE { SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) SLANG_OVERRIDE { SLANG_UNUSED(artifact); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW void SLANG_MCALL removeChildAt(Index index) SLANG_OVERRIDE { SLANG_UNUSED(index); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW void SLANG_MCALL clearChildren() SLANG_OVERRIDE { SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDesc(const ArtifactDesc& desc) SLANG_OVERRIDE { SLANG_UNUSED(desc); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDerivedDesc(const ArtifactDesc& desc) SLANG_OVERRIDE { SLANG_UNUSED(desc); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByName(const char* name) SLANG_OVERRIDE { SLANG_UNUSED(name); SLANG_UNREACHABLE("Not implemented"); } + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByPredicate(FindFunc func, void* data) SLANG_OVERRIDE { SLANG_UNUSED(func); SLANG_UNUSED(data); SLANG_UNREACHABLE("Not implemented"); } + + static ComPtr<IArtifact> create(const Desc& desc) { return ComPtr<IArtifact>(new Artifact(desc)); } + static ComPtr<IArtifact> create(const Desc& desc, const String& name) { return ComPtr<IArtifact>(new Artifact(desc, name)); } + +protected: /// Ctor Artifact(const Desc& desc, const String& name) : @@ -97,9 +85,15 @@ public: m_name(name), m_parent(nullptr) {} + Artifact(const Desc& desc) : + m_desc(desc), + m_parent(nullptr) + {} + + IArtifactHandler* _getHandler(); -protected: void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); Desc m_desc; ///< Description of the artifact IArtifact* m_parent; ///< Artifact this artifact belongs to @@ -112,6 +106,53 @@ protected: ComPtr<IArtifactList> m_children; ///< The children to this artifact }; +class ArtifactContainer : public Artifact +{ +public: + typedef Artifact Super; + SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE + + /// ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactCollection + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE { return m_expandResult; } + virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact** children, Count count) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() SLANG_OVERRIDE; + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL removeChildAt(Index index) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL clearChildren() SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDesc(const ArtifactDesc& desc) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDerivedDesc(const ArtifactDesc& desc) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByName(const char* name) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByPredicate(FindFunc func, void* data) SLANG_OVERRIDE; + + static ComPtr<IArtifactContainer> create(const Desc& desc) { return ComPtr<IArtifactContainer>(new ArtifactContainer(desc)); } + static ComPtr<IArtifactContainer> create(const Desc& desc, const String& name) { return ComPtr<IArtifactContainer>(new ArtifactContainer(desc, name)); } + +protected: + /// Ctor + ArtifactContainer(const Desc& desc, const String& name) :Super(desc, name) {} + ArtifactContainer(const Desc& desc) : Super(desc) {} + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + void _requireChildren() + { + if (m_expandResult == SLANG_E_UNINITIALIZED) + { + const auto res = expandChildren(); + SLANG_UNUSED(res); + SLANG_ASSERT(SLANG_SUCCEEDED(res)); + } + } + + SlangResult m_expandResult = SLANG_E_UNINITIALIZED; + + List<ComPtr<IArtifact>> m_children; +}; + } // namespace Slang #endif diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index d1de75c79..6ae2d646f 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -94,4 +94,94 @@ FileArtifactRepresentation::~FileArtifactRepresentation() } } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticsArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* DiagnosticsArtifactRepresentation::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactRepresentation::getTypeGuid() || + guid == IDiagnosticsArtifactRepresentation::getTypeGuid()) + { + return static_cast<DiagnosticsArtifactRepresentation*>(this); + } + return nullptr; +} + +void* DiagnosticsArtifactRepresentation::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +void* DiagnosticsArtifactRepresentation::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +SlangResult DiagnosticsArtifactRepresentation::writeToBlob(ISlangBlob** outBlob) +{ + *outBlob = nullptr; + return SLANG_E_NOT_IMPLEMENTED; +} + +bool DiagnosticsArtifactRepresentation::exists() +{ + return true; +} + +ZeroTerminatedCharSlice DiagnosticsArtifactRepresentation::_allocateSlice(const Slice<char>& in) +{ + if (in.count == 0) + { + return ZeroTerminatedCharSlice("", 0); + } + const char* dst = m_arena.allocateString(in.data, in.count); + return ZeroTerminatedCharSlice(dst, in.count); +} + +void DiagnosticsArtifactRepresentation::add(const Diagnostic& inDiagnostic) +{ + Diagnostic diagnostic(inDiagnostic); + + diagnostic.text = _allocateSlice(inDiagnostic.text); + diagnostic.code = _allocateSlice(inDiagnostic.code); + diagnostic.filePath = _allocateSlice(inDiagnostic.filePath); + + m_diagnostics.add(diagnostic); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* PostEmitMetadataArtifactRepresentation::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactRepresentation::getTypeGuid() || + guid == IPostEmitMetadataArtifactRepresentation::getTypeGuid()) + { + return static_cast<IPostEmitMetadataArtifactRepresentation*>(this); + } + return nullptr; +} + +void* PostEmitMetadataArtifactRepresentation::getObject(const Guid& uuid) +{ + if (uuid == getTypeGuid()) + { + return this; + } + return nullptr; +} + +Slice<ShaderBindingRange> PostEmitMetadataArtifactRepresentation::getBindingRanges() +{ + return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount()); +} + + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index a40adf0e9..00d36ab49 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -8,6 +8,9 @@ #include "../../slang-com-ptr.h" #include "../core/slang-com-object.h" +#include "../core/slang-memory-arena.h" + +//#include "../core/slang-string-slice-pool.h" namespace Slang { @@ -59,6 +62,139 @@ protected: ComPtr<ISlangMutableFileSystem> m_fileSystem; }; +class DiagnosticsArtifactRepresentation : public ComBaseObject, public IDiagnosticsArtifactRepresentation +{ +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; + // IDiagnosticArtifactRepresentation + SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return &m_diagnostics[i]; } + SLANG_NO_THROW virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_diagnostics.getCount(); } + SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE { m_diagnostics.removeAt(i); } + SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() SLANG_OVERRIDE { return m_result; } + SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE { m_result = res; } + + DiagnosticsArtifactRepresentation(): + m_arena(1024) + { + } + +protected: + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + ZeroTerminatedCharSlice _allocateSlice(const Slice<char>& in); + + // We could consider storing paths, codes in StringSlicePool, but for now we just allocate all 'string type things' + // in the arena. + MemoryArena m_arena; + + List<Diagnostic> m_diagnostics; + SlangResult m_result = SLANG_OK; + + ZeroTerminatedCharSlice m_raw; +}; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!! */ + +struct ShaderBindingRange +{ + slang::ParameterCategory category = slang::ParameterCategory::None; + UInt spaceIndex = 0; + UInt registerIndex = 0; + UInt registerCount = 0; // 0 for unsized + + bool isInfinite() const + { + return registerCount == 0; + } + + bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) const + { + return category == _category + && spaceIndex == _spaceIndex + && registerIndex <= _registerIndex + && (isInfinite() || registerCount + registerIndex > _registerIndex); + } + + bool intersectsWith(const ShaderBindingRange& other) const + { + if (category != other.category || spaceIndex != other.spaceIndex) + return false; + + const bool leftIntersection = (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = (other.registerIndex < registerIndex + registerCount) || isInfinite(); + + return leftIntersection && rightIntersection; + } + + bool adjacentTo(const ShaderBindingRange& other) const + { + if (category != other.category || spaceIndex != other.spaceIndex) + return false; + + const bool leftIntersection = (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = (other.registerIndex <= registerIndex + registerCount) || isInfinite(); + + return leftIntersection && rightIntersection; + } + + void mergeWith(const ShaderBindingRange other) + { + UInt newRegisterIndex = Math::Min(registerIndex, other.registerIndex); + + if (other.isInfinite()) + registerCount = 0; + else if (!isInfinite()) + registerCount = Math::Max(registerIndex + registerCount, other.registerIndex + other.registerCount) - newRegisterIndex; + + registerIndex = newRegisterIndex; + } + + static bool isUsageTracked(slang::ParameterCategory category) + { + switch (category) + { + case slang::ConstantBuffer: + case slang::ShaderResource: + case slang::UnorderedAccess: + case slang::SamplerState: + return true; + default: + return false; + } + } +}; + +typedef List<ShaderBindingRange> ShaderBindingRanges; + +class PostEmitMetadataArtifactRepresentation : public ComBaseObject, public IPostEmitMetadataArtifactRepresentation +{ +public: + SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, { 0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc }) + + 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; + // IPostEmitMetadataArtifactRepresentation + SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getBindingRanges() SLANG_OVERRIDE; + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + ShaderBindingRanges m_usedBindings; +}; + } // namespace Slang #endif diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h index 230283ce4..43a975d3c 100644 --- a/source/compiler-core/slang-artifact-representation.h +++ b/source/compiler-core/slang-artifact-representation.h @@ -16,6 +16,8 @@ to be usable. */ class IFileArtifactRepresentation : public IArtifactRepresentation { public: + SLANG_COM_INTERFACE(0xc7d7d3a4, 0x8683, 0x44b5, { 0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b }); + // NOTE! enum class Kind { @@ -38,6 +40,71 @@ public: virtual SLANG_NO_THROW IFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0; }; +/* Diagnostics. + +If there are raw diagnostics they can be associated to an artifact as (Kind::Text, Payload::Diagnostics) artifact */ +class IDiagnosticsArtifactRepresentation : public IArtifactRepresentation +{ +public: + SLANG_COM_INTERFACE(0x91f9b857, 0xcd6b, 0x45ca, { 0x8e, 0x3, 0x8f, 0xa3, 0x3c, 0x5c, 0xf0, 0x1a }); + + enum class Severity + { + Unknown, + Info, + Warning, + Error, + CountOf, + }; + enum class Stage + { + Compile, + Link, + }; + + struct Location + { + Int line = 0; ///< One indexed line number. 0 if not defined + Int column = 0; ///< One indexed *character (not byte)* column number. 0 if not defined + }; + + struct Diagnostic + { + Severity severity = Severity::Unknown; ///< The severity of error + Stage stage = Stage::Compile; ///< The stage the error came from + ZeroTerminatedCharSlice text; ///< The text of the error + ZeroTerminatedCharSlice code; ///< The compiler specific error code + ZeroTerminatedCharSlice filePath; ///< The path the error originated from + Location location; + }; + + /// Get the diagnostic at the index + SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) = 0; + /// Get the amount of diangostics + SLANG_NO_THROW virtual Count SLANG_MCALL getCount() = 0; + /// Add a diagnostic + SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) = 0; + /// Remove the diagnostic at the index + SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) = 0; + + /// Get the result for a compilation + SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() = 0; + /// Set the result + SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) = 0; +}; + +struct ShaderBindingRange; + +class IPostEmitMetadataArtifactRepresentation : public IArtifactRepresentation +{ +public: + SLANG_COM_INTERFACE(0x5d03bce9, 0xafb1, 0x4fc8, { 0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b }); + + /// Get the binding ranges + SLANG_NO_THROW virtual Slice<ShaderBindingRange> SLANG_MCALL getBindingRanges() = 0; +}; + + } // namespace Slang #endif diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 909c9b3d2..366ab4111 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -6,120 +6,177 @@ #include "slang-artifact-desc-util.h" +#include "../core/slang-castable-list-impl.h" + #include "../core/slang-file-system.h" #include "../core/slang-io.h" +#include "../core/slang-shared-library.h" namespace Slang { -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtilImpl !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ArtifactUtilImpl ArtifactUtilImpl::g_singleton; +/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; -SlangResult ArtifactUtilImpl::queryInterface(SlangUUID const& uuid, void** outObject) +SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) { - if (auto intf = getInterface(uuid)) + if (auto ptr = getInterface(uuid)) { - *outObject = intf; + addRef(); + *outObject = static_cast<IArtifactHandler*>(this); return SLANG_OK; } return SLANG_E_NO_INTERFACE; } -void* ArtifactUtilImpl::getInterface(const Guid& guid) +void* DefaultArtifactHandler::castAs(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || guid == IArtifactUtil::getTypeGuid()) + if (auto ptr = getInterface(guid)) { - return static_cast<IArtifactUtil*>(this); + return ptr; } - return nullptr; + return getObject(guid); } -SlangResult ArtifactUtilImpl::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +void* DefaultArtifactHandler::getInterface(const Guid& uuid) { - String name; - if (inName) + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ICastable::getTypeGuid() || + uuid == IArtifactHandler::getTypeGuid()) { - name = inName; + return static_cast<IArtifactHandler*>(this); } - ComPtr<IArtifact> artifact(new Artifact(desc, name)); + return nullptr; +} - *outArtifact = artifact.detach(); - return SLANG_OK; +void* DefaultArtifactHandler::getObject(const Guid& uuid) +{ + SLANG_UNUSED(uuid); + return nullptr; } -SlangResult ArtifactUtilImpl::createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) { - ComPtr<IArtifactList> artifactList(new ArtifactList(parent)); - *outArtifactList = artifactList.detach(); - return SLANG_OK; + SLANG_ASSERT(rep); + + // See if it implements ICastable + { + ComPtr<ICastable> castable; + if (SLANG_SUCCEEDED(rep->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + return _addRepresentation(artifact, keep, castable, outCastable); + } + } + + // We have to wrap + ComPtr<IUnknownCastableAdapter> adapter(new UnknownCastableAdapter(rep)); + return _addRepresentation(artifact, keep, adapter, outCastable); } -ArtifactKind ArtifactUtilImpl::getKindParent(ArtifactKind kind) { return getParent(kind); } -UnownedStringSlice ArtifactUtilImpl::getKindName(ArtifactKind kind) { return getName(kind); } -bool ArtifactUtilImpl::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +{ + SLANG_ASSERT(castable); -ArtifactPayload ArtifactUtilImpl::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } -UnownedStringSlice ArtifactUtilImpl::getPayloadName(ArtifactPayload payload) { return getName(payload); } -bool ArtifactUtilImpl::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } + if (canKeep(keep)) + { + artifact->addRepresentation(castable); + } -ArtifactStyle ArtifactUtilImpl::getStyleParent(ArtifactStyle style) { return getParent(style); } -UnownedStringSlice ArtifactUtilImpl::getStyleName(ArtifactStyle style) { return getName(style); } -bool ArtifactUtilImpl::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } + castable->addRef(); + *outCastable = castable; + return SLANG_OK; +} -SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) +SlangResult DefaultArtifactHandler::expandChildren(IArtifactContainer* container) { - if (fileSystem) + SlangResult res = container->getExpandChildrenResult(); + if (res != SLANG_E_UNINITIALIZED) { - if (fileSystem != OSFileSystem::getMutableSingleton()) - { - // We can only create lock files, on the global OS file system - return SLANG_E_NOT_AVAILABLE; - } - fileSystem = nullptr; + // It's already expanded + return res; } - const UnownedStringSlice nameBase = (inNameBase && inNameBase[0] != 0) ? UnownedStringSlice(inNameBase) : UnownedStringSlice("unknown"); + // For the generic container type, we just expand as empty + const auto desc = container->getDesc(); + if (desc.kind == ArtifactKind::Container) + { + container->setChildren(nullptr, 0); + return SLANG_OK; + } + // TODO(JS): + // Proper implementation should (for example) be able to expand a Zip file etc. + return SLANG_E_NOT_IMPLEMENTED; +} - String lockPath; - SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); +SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) +{ + + // See if we already have a rep of this type + { + for (ICastable* rep : artifact->getRepresentations()) + { + if (rep->castAs(guid)) + { + rep->addRef(); + *outCastable = rep; + return SLANG_OK; + } + } + } - ComPtr<IFileArtifactRepresentation> lockFile(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Lock, lockPath, nullptr, fileSystem)); + if (guid == ISlangBlob::getTypeGuid()) + { + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(_loadBlob(artifact, keep, blob.writeRef())); + return _addRepresentation(artifact, keep, blob, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr<ISlangSharedLibrary> sharedLib; + SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, keep, sharedLib.writeRef())); + return _addRepresentation(artifact, keep, sharedLib, outCastable); + } - *outLockFile = lockFile.detach(); - return SLANG_OK; + return SLANG_E_NOT_AVAILABLE; } -SlangResult ArtifactUtilImpl::calcArtifactPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) +static bool _isFileSystemFile(ICastable* castable, void* data) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); - *outPath = StringBlob::create(path).detach(); - return SLANG_OK; + if (auto fileRep = as<IFileArtifactRepresentation>(castable)) + { + ISlangMutableFileSystem* fileSystem = (ISlangMutableFileSystem*)data; + if (fileRep->getFileSystem() == fileSystem) + { + return true; + } + } + return false; } -SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFile) +SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) { // See if we already have it - if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact)) + if (auto fileRep = as<IFileArtifactRepresentation>(artifact->findRepresentationWithPredicate(&_isFileSystemFile, fileSystem))) { fileRep->addRef(); - *outFile = fileRep; + *outFileRep = fileRep; return SLANG_OK; } + auto util = ArtifactUtilImpl::getSingleton(); + // If we are going to access as a file we need to be able to write it, and to do that we need a blob ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(keep, blob.writeRef())); + SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); // Okay we need to store as a temporary. Get a lock file. ComPtr<IFileArtifactRepresentation> lockFile; - SLANG_RETURN_ON_FAIL(createLockFile(artifact->getName(), nullptr, lockFile.writeRef())); + SLANG_RETURN_ON_FAIL(util->createLockFile(artifact->getName(), fileSystem, lockFile.writeRef())); // Now we need the appropriate name for this item ComPtr<ISlangBlob> pathBlob; - SLANG_RETURN_ON_FAIL(calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef())); + SLANG_RETURN_ON_FAIL(util->calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef())); const auto path = StringUtil::getString(pathBlob); @@ -141,7 +198,7 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa else { // Create a new rep that references the lock file - fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, nullptr); + fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, lockFile->getFileSystem()); } // Create the rep @@ -151,28 +208,170 @@ SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, Artifa } // Return the file - *outFile = fileRep.detach(); + *outFileRep = fileRep.detach(); return SLANG_OK; } -ArtifactDesc ArtifactUtilImpl::makeDescFromCompileTarget(SlangCompileTarget target) +SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) { - return ArtifactDescUtil::makeDescFromCompileTarget(target); + // If it is 'shared library' for a CPU like thing, we can try and load it + const auto desc = artifact->getDesc(); + if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || + isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + // Get as a file represenation on the OS file system + ComPtr<IFileArtifactRepresentation> fileRep; + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, nullptr, fileRep.writeRef())); + + // We requested on the OS file system, just check that's what we got... + SLANG_ASSERT(fileRep->getFileSystem() == nullptr); + + // Try loading the shared library + SharedLibrary::Handle handle; + if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) + { + return SLANG_FAIL; + } + + // The ScopeSharedLibrary will keep the fileRep in scope as long as is needed + auto sharedLibrary = new ScopeSharedLibrary(handle, fileRep); + + if (canKeep(keep)) + { + // We want to keep the fileRep, as that is necessary for the sharedLibrary to even work + artifact->addRepresentation(fileRep); + // Keep the shared library + artifact->addRepresentation(sharedLibrary); + } + + // Output + sharedLibrary->addRef(); + *outSharedLibrary = sharedLibrary; + + return SLANG_OK; + } + + return SLANG_FAIL; } -SlangResult ArtifactUtilImpl::getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList) +SlangResult DefaultArtifactHandler::_loadBlob(IArtifact* artifact, ArtifactKeep keep, ISlangBlob** outBlob) { - auto desc = artifact->getDesc(); + SLANG_UNUSED(keep); + + ComPtr<ISlangBlob> blob; + + // Look for a representation that we can serialize into a blob + for (auto rep : artifact->getRepresentations()) + { + if (auto artifactRep = as<IArtifactRepresentation>(rep)) + { + SlangResult res = artifactRep->writeToBlob(blob.writeRef()); + if (SLANG_SUCCEEDED(res) && blob) + { + break; + } + } + } - // If it's a container type for now, just create empty list of children - if (isDerivedFrom(desc.kind, ArtifactKind::Container)) + // Wasn't able to construct + if (!blob) { - *outList = ComPtr<IArtifactList>(new ArtifactList(artifact)).detach(); + return SLANG_E_NOT_FOUND; + } + + *outBlob = blob.detach(); + return SLANG_OK; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtilImpl !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */ArtifactUtilImpl ArtifactUtilImpl::g_singleton; + +SlangResult ArtifactUtilImpl::queryInterface(SlangUUID const& uuid, void** outObject) +{ + if (auto intf = getInterface(uuid)) + { + *outObject = intf; return SLANG_OK; } + return SLANG_E_NO_INTERFACE; +} + +void* ArtifactUtilImpl::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || guid == IArtifactUtil::getTypeGuid()) + { + return static_cast<IArtifactUtil*>(this); + } + return nullptr; +} - return SLANG_E_NOT_AVAILABLE; +SlangResult ArtifactUtilImpl::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +{ + *outArtifact = inName ? + Artifact::create(desc, inName).detach() : + Artifact::create(desc).detach(); + + return SLANG_OK; } +SlangResult ArtifactUtilImpl::createArtifactContainer(const ArtifactDesc& desc, const char* inName, IArtifactContainer** outArtifactContainer) +{ + *outArtifactContainer = inName ? + ArtifactContainer::create(desc, inName).detach() : + ArtifactContainer::create(desc).detach(); + + return SLANG_OK; +} + +ArtifactKind ArtifactUtilImpl::getKindParent(ArtifactKind kind) { return getParent(kind); } +UnownedStringSlice ArtifactUtilImpl::getKindName(ArtifactKind kind) { return getName(kind); } +bool ArtifactUtilImpl::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } + +ArtifactPayload ArtifactUtilImpl::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } +UnownedStringSlice ArtifactUtilImpl::getPayloadName(ArtifactPayload payload) { return getName(payload); } +bool ArtifactUtilImpl::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } + +ArtifactStyle ArtifactUtilImpl::getStyleParent(ArtifactStyle style) { return getParent(style); } +UnownedStringSlice ArtifactUtilImpl::getStyleName(ArtifactStyle style) { return getName(style); } +bool ArtifactUtilImpl::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } + +SlangResult ArtifactUtilImpl::createLockFile(const char* inNameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) +{ + if (fileSystem) + { + if (fileSystem != OSFileSystem::getMutableSingleton()) + { + // We can only create lock files, on the global OS file system + return SLANG_E_NOT_AVAILABLE; + } + fileSystem = nullptr; + } + + const UnownedStringSlice nameBase = (inNameBase && inNameBase[0] != 0) ? UnownedStringSlice(inNameBase) : UnownedStringSlice("unknown"); + + String lockPath; + SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); + + ComPtr<IFileArtifactRepresentation> lockFile(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Lock, lockPath, nullptr, fileSystem)); + + *outLockFile = lockFile.detach(); + return SLANG_OK; +} + +SlangResult ArtifactUtilImpl::calcArtifactPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) +{ + UnownedStringSlice basePath(inBasePath); + StringBuilder path; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); + *outPath = StringBlob::create(path).detach(); + 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 c391a5056..5e44b7565 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -5,16 +5,47 @@ #include "slang-artifact.h" #include "slang-artifact-representation.h" +#include "../core/slang-com-object.h" + namespace Slang { +class DefaultArtifactHandler : public ComBaseObject, public IArtifactHandler +{ +public: + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactHandler + SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifactContainer* container) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + + static IArtifactHandler* getSingleton() { return &g_singleton; } +protected: + + SlangResult _loadSharedLibrary(IArtifact* artifact, ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary); + SlangResult _loadBlob(IArtifact* artifact, ArtifactKeep keep, ISlangBlob** outBlob); + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable); + SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable); + + static DefaultArtifactHandler g_singleton; +}; + class IArtifactUtil : public ISlangUnknown { SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, { 0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20 }) virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactContainer(const ArtifactDesc& desc, const char* name, IArtifactContainer** outArtifactContainer) = 0; virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; @@ -33,12 +64,7 @@ class IArtifactUtil : public ISlangUnknown /// Given a desc and a basePath returns a suitable name virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; - /// 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; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList) = 0; }; class ArtifactUtilImpl : public IArtifactUtil @@ -51,8 +77,7 @@ public: // IArtifactInterface virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactList(IArtifact* parent, IArtifactList** outArtifactList) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifactContainer(const ArtifactDesc& desc, const char* name, IArtifactContainer** outArtifactContainer) SLANG_OVERRIDE; virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) SLANG_OVERRIDE; @@ -70,12 +95,8 @@ public: virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; - 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; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getChildrenDefaultImpl(IArtifact* artifact, IArtifactList** outList) SLANG_OVERRIDE; - static IArtifactUtil* getSingleton() { return &g_singleton; } protected: diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 55b3ff89f..e399578a9 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -4,14 +4,40 @@ #include "../core/slang-basic.h" -//#include "../../slang-com-helper.h" -//#include "../core/slang-destroyable.h" - #include "../core/slang-castable-list.h" namespace Slang { + +/* Simplest slice types. We can't use UnownedStringSlice etc, because they implement functionality in libraries, +and we want to use these types in headers. +If we wanted a C implementation it would be easy to use a macro to generate the functionality */ + +template <typename T> +struct Slice +{ + const T* begin() const { return data; } + const T* end() const { return data + count; } + + Slice() :count(0), data(nullptr) {} + Slice(const T* inData, Count inCount) : + data(inData), + count(inCount) + {} + + const T* data; + Count count; +}; + +struct ZeroTerminatedCharSlice : Slice<char> +{ + typedef Slice<char> Super; + explicit ZeroTerminatedCharSlice(const char* in) :Super(in, ::strlen(in)) {} + ZeroTerminatedCharSlice(const char* in, Count inCount) :Super(in, inCount) { SLANG_ASSERT(in[inCount] == 0); } + ZeroTerminatedCharSlice() :Super("", 0) {} +}; + /* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the highest level. If some aspect can apply to multiple items identically we move that to a separate enum. @@ -47,9 +73,8 @@ enum class ArtifactKind : uint8_t SharedLibrary, ///< Shared library - can be dynamically linked HostCallable, ///< Code can be executed directly on the host - DebugInfo, ///< Debugging information - Diagnostics, ///< Diagnostics information - + Instance, ///< Primary representation is an interface/class instance + CountOf, }; @@ -109,6 +134,14 @@ enum class ArtifactPayload : uint8_t SlangAST, ///< Slang AST + CompileResults, ///< Payload is a collection of compilation results + + MetaData, ///< Meta data + + DebugInfo, ///< Debugging information + Diagnostics, ///< Diagnostics information + PostEmitMetadata, ///< Post emit meta data + CountOf, }; @@ -220,6 +253,9 @@ 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; } +/* Forward define */ +class IArtifactHandler; + /* 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 @@ -266,7 +302,7 @@ More long term goals would be to * Make Diagnostics into an interface (such it can be added to a Artifact result) * Use Artifact and related types for downstream compiler */ -class IArtifact : public ISlangUnknown +class IArtifact : public ICastable { public: SLANG_COM_INTERFACE(0x57375e20, 0xbed, 0x42b6, { 0x9f, 0x5e, 0x59, 0x4f, 0x6, 0x2b, 0xe6, 0x90 }) @@ -282,11 +318,6 @@ public: /// Get the Desc defining the contents of the artifact virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() = 0; - /// Get the artifact (if any) that this artifact belongs to - virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() = 0; - /// Set the parent that 'owns' this artifact. The parent is *not* reference counted (ie weak reference) - virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* parent) = 0; - /// Returns true if the artifact in principal exists virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; @@ -295,7 +326,10 @@ public: /// Require artifact is available as a file. /// NOTE! May need to serialize and write as a temporary file. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) = 0; + + /// Load the artifact as a shared library + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; @@ -303,24 +337,61 @@ public: /// Add data associated with this artifact virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(ICastable* castable) = 0; /// Find an associated item - virtual void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) = 0; + virtual SLANG_NO_THROW void* SLANG_MCALL SLANG_MCALL findAssociated(const Guid& unk) = 0; /// TODO(JS): We may want this to return nullptr if it's empty. /// Get the list of associated items - virtual ICastableList* SLANG_MCALL getAssociated() = 0; + virtual SLANG_NO_THROW ICastableList* SLANG_MCALL getAssociated() = 0; + /// Find first associated that matches the predicate + virtual SLANG_NO_THROW ICastable* SLANG_MCALL findAssociatedWithPredicate(ICastableList::FindFunc findFunc, void* data) = 0; /// Add a representation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) = 0; /// Add a representation that doesn't derive from IArtifactRepresentation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) = 0; /// Find representation - virtual void* SLANG_MCALL SLANG_MCALL findRepresentation(const Guid& guid) = 0; + virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(const Guid& guid) = 0; + /// Find first representation that matches the predicate + virtual SLANG_NO_THROW ICastable* SLANG_MCALL findRepresentationWithPredicate(ICastableList::FindFunc findFunc, void* data) = 0; + + /// Get all the representations + virtual SLANG_NO_THROW Slice<ICastable*> SLANG_MCALL getRepresentations() = 0; /// Get the list of all representations - virtual ICastableList* SLANG_MCALL getRepresentations() = 0; + virtual SLANG_NO_THROW ICastableList* SLANG_MCALL getRepresentationList() = 0; - /// Get the children. This may be evaluated lazily. - /// Only artifacts with a ArtifactKind that derives from Container generally produce childen. - /// If an artifact doesn't support children, it can return nullptr. - virtual IArtifactList* SLANG_MCALL getChildren() = 0; + /// Given a typeGuid representing the desired type get or create the representation. + /// If found outCastable holds an entity that *must* be castable to typeGuid + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) = 0; +}; + +class IArtifactContainer : public IArtifact +{ +public: + SLANG_COM_INTERFACE(0xa96e29bd, 0xb546, 0x4e79, { 0xa0, 0xdc, 0x67, 0x49, 0x22, 0x2c, 0x39, 0xad }) + + typedef bool (*FindFunc)(IArtifact* artifact, void* data); + + /// Returns the result of expansion. Will return SLANG_E_UNINITIALIZED if expansion hasn't happened + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() = 0; + /// Sets all of the children, will set the expansion state to SLANG_OK + virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact**children, Count count) = 0; + /// Will be called implicitly on access to children + virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() = 0; + /// Get the children, will only remain valid if no mutation of children list + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() = 0; + /// Add the artifact to the list + virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) = 0; + /// Removes the child at index, keeps other artifacts in the same order + virtual SLANG_NO_THROW void SLANG_MCALL removeChildAt(Index index) = 0; + /// Clear the list + virtual SLANG_NO_THROW void SLANG_MCALL clearChildren() = 0; + /// Find an artifact which is an exact match for the desc + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDesc(const ArtifactDesc& desc) = 0; + /// Find an artifact that matches desc allowing derivations. Flags is ignored + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByDerivedDesc(const ArtifactDesc& desc) = 0; + /// Find by name + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByName(const char* name) = 0; + /// Find via predicate function + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findChildByPredicate(FindFunc func, void* data) = 0; }; template <typename T> @@ -329,29 +400,6 @@ SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact) return reinterpret_cast<T*>(artifact->findRepresentation(T::getTypeGuid())); } -/* A list of artifacts. */ -class IArtifactList : public ICastable -{ - SLANG_COM_INTERFACE(0x5ef6ace5, 0xc928, 0x4c7b, { 0xbc, 0xba, 0x83, 0xa9, 0xd9, 0x66, 0x64, 0x27 }) - - /// Get the artifact this list belongs to. Can be nullptr. - /// Note this is a *weak* reference. - virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getParent() = 0; - /// The parent is no longer accessible - virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* artifact) = 0; - - /// Get the artifact at the specified index - virtual SLANG_NO_THROW IArtifact* SLANG_MCALL getAt(Index index) = 0; - /// Get the count of all the artifacts - virtual SLANG_NO_THROW Count SLANG_MCALL getCount() = 0; - /// Add the artifact to the list - virtual SLANG_NO_THROW void SLANG_MCALL add(IArtifact* artifact) = 0; - /// Removes at index, keeps other artifacts in the same order - virtual SLANG_NO_THROW void SLANG_MCALL removeAt(Index index) = 0; - /// Clear the list - virtual SLANG_NO_THROW void SLANG_MCALL clear() = 0; -}; - /* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far as @@ -370,6 +418,18 @@ class IArtifactRepresentation : public ICastable virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; }; +/* Handler provides functionality external to the artifact */ +class IArtifactHandler : public ICastable +{ + SLANG_COM_INTERFACE(0x6a646f57, 0xb3ac, 0x4c6a, { 0xb6, 0xf1, 0x33, 0xb6, 0xef, 0x60, 0xa6, 0xae }); + + /// Given an artifact expands children + virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifactContainer* container) = 0; + /// Given an artifact gets or creates a representation. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) = 0; + /// Given an artifact gets a represenation of it on the file system. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) = 0; +}; } // namespace Slang diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 2c1380cde..3a0217d86 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -647,7 +647,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse ComPtr<IFileArtifactRepresentation> fileRep; // Get the name and path (can be empty) to the library - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef())); + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); 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 a4b4e7bc6..43c991337 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -268,7 +268,7 @@ namespace Slang { // Get the libray name and path ComPtr<IFileArtifactRepresentation> fileRep; - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef())); + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); libPathPool.add(ArtifactDescUtil::getParentPath(fileRep)); // We need the extension for windows diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h index b1384bb2c..8a9ab5dea 100644 --- a/source/core/slang-blob.h +++ b/source/core/slang-blob.h @@ -45,11 +45,18 @@ public: SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_string.getLength(); } static ComPtr<ISlangBlob> create(const String& in) { return ComPtr<ISlangBlob>(new StringBlob(in)); } + static ComPtr<ISlangBlob> moveCreate(String& in) + { + auto blob = new StringBlob; + blob->m_string.swapWith(in); + return ComPtr<ISlangBlob>(blob); + } protected: explicit StringBlob(String const& string) : m_string(string) {} + StringBlob() {} /// Get the contained string SLANG_FORCE_INLINE const String& getString() const { return m_string; } diff --git a/source/core/slang-castable-list-impl.cpp b/source/core/slang-castable-list-impl.cpp index ee10ea995..56f8c7cae 100644 --- a/source/core/slang-castable-list-impl.cpp +++ b/source/core/slang-castable-list-impl.cpp @@ -36,9 +36,10 @@ void* UnknownCastableAdapter::castAs(const Guid& guid) void* UnknownCastableAdapter::getInterface(const Guid& guid) { if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid()) + guid == ICastable::getTypeGuid() || + guid == IUnknownCastableAdapter::getTypeGuid()) { - return static_cast<ICastable*>(this); + return static_cast<IUnknownCastableAdapter*>(this); } return nullptr; } @@ -97,6 +98,18 @@ void* CastableList::find(const Guid& guid) return nullptr; } +ICastable* SLANG_MCALL CastableList::findWithPredicate(FindFunc func, void* data) +{ + for (ICastable* castable : m_list) + { + if (func(castable, data)) + { + return castable; + } + } + return nullptr; +} + Index CastableList::indexOf(ICastable* castable) { const Count count = m_list.getCount(); diff --git a/source/core/slang-castable-list-impl.h b/source/core/slang-castable-list-impl.h index 6c03855f2..b578e8de4 100644 --- a/source/core/slang-castable-list-impl.h +++ b/source/core/slang-castable-list-impl.h @@ -66,6 +66,7 @@ public: virtual Index SLANG_MCALL indexOf(ICastable* castable) SLANG_OVERRIDE; virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) SLANG_OVERRIDE; virtual void* SLANG_MCALL find(const Guid& guid) SLANG_OVERRIDE; + virtual ICastable* SLANG_MCALL findWithPredicate(FindFunc func, void* data) SLANG_OVERRIDE; virtual ICastable*const* SLANG_MCALL getBuffer() SLANG_OVERRIDE { return m_list.getBuffer(); } /// Dtor diff --git a/source/core/slang-castable-list.h b/source/core/slang-castable-list.h index 942f53376..b9c98d65a 100644 --- a/source/core/slang-castable-list.h +++ b/source/core/slang-castable-list.h @@ -9,11 +9,14 @@ namespace Slang { + /* A useful interface for handling lists of castable interfaces. Cannot hold nullptr */ class ICastableList : public ICastable { SLANG_COM_INTERFACE(0x335f3d40, 0x934c, 0x40dc, { 0xb5, 0xe1, 0xf7, 0x6e, 0x40, 0x3, 0x62, 0x5 }) - + + typedef bool (*FindFunc)(ICastable* castable, void* data); + /// Get the count of all interfaces held in the list virtual Count SLANG_MCALL getCount() = 0; /// Get the interface at the specified index @@ -32,6 +35,8 @@ class ICastableList : public ICastable virtual Index SLANG_MCALL indexOfUnknown(ISlangUnknown* unk) = 0; /// Find the first item that casts to non null virtual void* SLANG_MCALL find(const Guid& guid) = 0; + /// Find the fast castable that matches the predicate + virtual ICastable* SLANG_MCALL findWithPredicate(FindFunc func, void* data) = 0; /// Access the internal buffer (any mutation can invalidate this value) virtual ICastable*const* SLANG_MCALL getBuffer() = 0; }; @@ -43,6 +48,12 @@ SLANG_FORCE_INLINE T* find(ICastableList* list) return reinterpret_cast<T*>(list->find(T::getTypeGuid())); } +template <typename T> +SLANG_FORCE_INLINE T* find(ICastableList* list, ICastableList::FindFunc func, void* data) +{ + return reinterpret_cast<T*>(list->findWithPredicate(T::getTypeGuid(), func, data)); +} + /* Adapter interface to make a non castable types work as ICastable */ class IUnknownCastableAdapter : public ICastable { diff --git a/source/core/slang-lazy-castable-list.cpp b/source/core/slang-lazy-castable-list.cpp index d9f0090d5..1832a67f4 100644 --- a/source/core/slang-lazy-castable-list.cpp +++ b/source/core/slang-lazy-castable-list.cpp @@ -112,7 +112,19 @@ void* LazyCastableList::find(const Guid& guid) } return nullptr; } - + +ICastable* LazyCastableList::findWithPredicate(ICastableList::FindFunc func, void* data) +{ + for (auto castable : getView()) + { + if (func(castable, data)) + { + return castable; + } + } + return nullptr; +} + ConstArrayView<ICastable*> LazyCastableList::getView() const { switch (m_state) diff --git a/source/core/slang-lazy-castable-list.h b/source/core/slang-lazy-castable-list.h index 4f73ce9ca..84bfd8c6d 100644 --- a/source/core/slang-lazy-castable-list.h +++ b/source/core/slang-lazy-castable-list.h @@ -35,6 +35,8 @@ public: void clearAndDeallocate(); /// Find the first item that castAs(guid) produces a result void* find(const Guid& guid); + /// Find first match using predicate function + ICastable* findWithPredicate(ICastableList::FindFunc func, void* data); /// Get the contents of the list as a view ConstArrayView<ICastable*> getView() const; /// Get the index of castable in the list. Returns -1 if not found diff --git a/source/core/slang-shared-library.cpp b/source/core/slang-shared-library.cpp index 0e4f0ee73..35440ac9e 100644 --- a/source/core/slang-shared-library.cpp +++ b/source/core/slang-shared-library.cpp @@ -33,7 +33,7 @@ SlangResult DefaultSharedLibraryLoader::loadSharedLibrary(const char* path, ISla { *outSharedLibrary = nullptr; // Try loading - SharedLibrary::Handle handle = nullptr; + SharedLibrary::Handle handle; SLANG_RETURN_ON_FAIL(SharedLibrary::load(path, handle)); *outSharedLibrary = ComPtr<ISlangSharedLibrary>(new DefaultSharedLibrary(handle)).detach(); return SLANG_OK; @@ -74,6 +74,18 @@ TemporarySharedLibrary::~TemporarySharedLibrary() } } +/* !!!!!!!!!!!!!!!!!!!!!!!!!! ScopeSharedLibrary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +ScopeSharedLibrary::~ScopeSharedLibrary() +{ + if (m_sharedLibraryHandle) + { + // We have to unload if we want to be able to remove + SharedLibrary::unload(m_sharedLibraryHandle); + m_sharedLibraryHandle = nullptr; + } +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!! DefaultSharedLibrary !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ DefaultSharedLibrary::~DefaultSharedLibrary() diff --git a/source/core/slang-shared-library.h b/source/core/slang-shared-library.h index c0074bad3..0a63e570e 100644 --- a/source/core/slang-shared-library.h +++ b/source/core/slang-shared-library.h @@ -100,6 +100,24 @@ protected: String m_path; }; +class ScopeSharedLibrary : public DefaultSharedLibrary +{ +public: + typedef DefaultSharedLibrary Super; + + /// Ctor + ScopeSharedLibrary(const SharedLibrary::Handle sharedLibraryHandle, ISlangUnknown* scope) : + Super(sharedLibraryHandle), + m_scope(scope) + { + } + + virtual ~ScopeSharedLibrary(); + +protected: + ComPtr<ISlangUnknown> m_scope; +}; + class SharedLibraryUtils { public: diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h index 45083c1eb..75c4398a5 100644 --- a/source/core/slang-smart-pointer.h +++ b/source/core/slang-smart-pointer.h @@ -236,6 +236,13 @@ namespace Slang return rs; } + void swapWith(RefPtr<T>& rhs) + { + auto rhsPtr = rhs.pointer; + rhs.pointer = pointer; + pointer = rhsPtr; + } + SLANG_FORCE_INLINE void setNull() { releaseReference(pointer); diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 69ca7e2c3..028eec3e4 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -765,6 +765,11 @@ namespace Slang return indexOf(str.begin(), 0); } + void swapWith(String& other) + { + m_buffer.swapWith(other.m_buffer); + } + Index indexOf(char ch, Index id) const { const Index length = getLength(); diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 17785bdc6..80015440a 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1366,7 +1366,7 @@ namespace Slang options.libraryPaths.add(Path::getParentDirectory(Path::getExecutablePath())); // Set up the library artifact - ComPtr<IArtifact> artifact(new Artifact(ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU), "slang-rt")); + auto artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU), "slang-rt"); ComPtr<IFileArtifactRepresentation> fileRep(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::NameOnly, "slang-rt", nullptr, nullptr)); artifact->addRepresentation(fileRep); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index fd338361e..56e161483 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -25,6 +25,8 @@ #include "slang-serialize-ir-types.h" +#include "../compiler-core/slang-artifact-representation-impl.h" + #include "../../slang.h" namespace Slang @@ -142,75 +144,6 @@ namespace Slang class Module; class TranslationUnitRequest; - struct ShaderBindingRange - { - slang::ParameterCategory category = slang::ParameterCategory::None; - UInt spaceIndex = 0; - UInt registerIndex = 0; - UInt registerCount = 0; // 0 for unsized - - bool isInfinite() const - { - return registerCount == 0; - } - - bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) const - { - return category == _category - && spaceIndex == _spaceIndex - && registerIndex <= _registerIndex - && (isInfinite() || registerCount + registerIndex > _registerIndex); - } - - bool intersectsWith(const ShaderBindingRange& other) const - { - if (category != other.category || spaceIndex != other.spaceIndex) - return false; - - const bool leftIntersection = (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex < registerIndex + registerCount) || isInfinite(); - - return leftIntersection && rightIntersection; - } - - bool adjacentTo(const ShaderBindingRange& other) const - { - if (category != other.category || spaceIndex != other.spaceIndex) - return false; - - const bool leftIntersection = (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex <= registerIndex + registerCount) || isInfinite(); - - return leftIntersection && rightIntersection; - } - - void mergeWith(const ShaderBindingRange other) - { - UInt newRegisterIndex = Math::Min(registerIndex, other.registerIndex); - - if (other.isInfinite()) - registerCount = 0; - else if (!isInfinite()) - registerCount = Math::Max(registerIndex + registerCount, other.registerIndex + other.registerCount) - newRegisterIndex; - - registerIndex = newRegisterIndex; - } - - static bool isUsageTracked(slang::ParameterCategory category) - { - switch(category) - { - case slang::ConstantBuffer: - case slang::ShaderResource: - case slang::UnorderedAccess: - case slang::SamplerState: - return true; - default: - return false; - } - } - }; - struct PostEmitMetadata : public RefObject { List<ShaderBindingRange> usedBindings; diff --git a/source/slang/slang-module-library.cpp b/source/slang/slang-module-library.cpp index 75450d7b3..b7290008b 100644 --- a/source/slang/slang-module-library.cpp +++ b/source/slang/slang-module-library.cpp @@ -15,9 +15,12 @@ namespace Slang { void* ModuleLibrary::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || uuid == IArtifactRepresentation::getTypeGuid()) + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ICastable::getTypeGuid() || + uuid == IArtifactRepresentation::getTypeGuid() || + uuid == IModuleLibrary::getTypeGuid()) { - return static_cast<IArtifactRepresentation*>(this); + return static_cast<IModuleLibrary*>(this); } return nullptr; } @@ -36,9 +39,10 @@ void* ModuleLibrary::castAs(const Guid& guid) return getObject(guid); } -SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary) +SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary) { - RefPtr<ModuleLibrary> library = new ModuleLibrary; + auto library = new ModuleLibrary; + ComPtr<IModuleLibrary> scopeLibrary(library); // Load up the module MemoryStreamBase memoryStream(FileAccess::Read, inBytes, bytesCount); @@ -85,13 +89,13 @@ SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCo } } - outLibrary = library; + outLibrary.swap(scopeLibrary); return SLANG_OK; } -SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& outLibrary) +SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outLibrary) { - if (auto foundLibrary = findRepresentation<ModuleLibrary>(artifact)) + if (auto foundLibrary = findRepresentation<IModuleLibrary>(artifact)) { outLibrary = foundLibrary; return SLANG_OK; @@ -102,7 +106,7 @@ SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCo SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); // Load the module - RefPtr<ModuleLibrary> library; + ComPtr<IModuleLibrary> library; SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)blob->getBufferPointer(), blob->getBufferSize(), req, library)); if (canKeep(keep)) @@ -110,7 +114,7 @@ SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCo artifact->addRepresentation(library); } - outLibrary = library; + outLibrary.swap(library); return SLANG_OK; } diff --git a/source/slang/slang-module-library.h b/source/slang/slang-module-library.h index 40e655e85..dd74193a4 100644 --- a/source/slang/slang-module-library.h +++ b/source/slang/slang-module-library.h @@ -9,11 +9,16 @@ namespace Slang { +class IModuleLibrary : public IArtifactRepresentation +{ + SLANG_COM_INTERFACE(0x8f630911, 0xea96, 0x4075, { 0xbf, 0x6b, 0xd2, 0xae, 0x96, 0xbe, 0xb6, 0xde }); +}; + // Class to hold information serialized in from a -r slang-lib/slang-module -class ModuleLibrary : public ComObject, public IArtifactRepresentation +class ModuleLibrary : public ComBaseObject, public IModuleLibrary { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL + SLANG_COM_BASE_IUNKNOWN_ALL SLANG_CLASS_GUID(0x2f7412bd, 0x6154, 0x40a9, { 0x89, 0xb3, 0x62, 0xe0, 0x24, 0x17, 0x24, 0xa1 }); @@ -31,10 +36,10 @@ public: void* getObject(const Guid& uuid); }; -SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module); +SlangResult loadModuleLibrary(const Byte* inBytes, size_t bytesCount, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule); // Given a product make available as a module -SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, RefPtr<ModuleLibrary>& module); +SlangResult loadModuleLibrary(ArtifactKeep keep, IArtifact* artifact, EndToEndCompileRequest* req, ComPtr<IModuleLibrary>& outModule); } // namespace Slang diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 6351ffbd4..c40e5d16c 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -1484,7 +1484,7 @@ struct OptionsParser const String name = ArtifactDescUtil::getBaseNameFromPath(desc, path.getUnownedSlice()); // Create the artifact - ComPtr<IArtifact> artifact(new Artifact(desc, name)); + auto artifact = Artifact::create(desc, name); // There is a problem here if I want to reference a library that is a 'system' library or is not directly a file // In that case the path shouldn't be set and the name should completely define the library. diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 684b0660d..c0c7c4f5a 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -4485,9 +4485,15 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac if (desc.kind == ArtifactKind::Library && desc.payload == ArtifactPayload::SlangIR) { - RefPtr<ModuleLibrary> library; + ComPtr<IModuleLibrary> libraryIntf; - SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, artifact, req, library)); + SLANG_RETURN_ON_FAIL(loadModuleLibrary(ArtifactKeep::Yes, artifact, req, libraryIntf)); + + auto library = as<ModuleLibrary>(libraryIntf); + if (!library) + { + return SLANG_FAIL; + } FrontEndCompileRequest* frontEndRequest = req->getFrontEndReq(); frontEndRequest->m_extraEntryPoints.addRange(library->m_entryPoints.getBuffer(), library->m_entryPoints.getCount()); @@ -4508,13 +4514,12 @@ SlangResult _addLibraryReference(EndToEndCompileRequest* req, IArtifact* artifac SlangResult EndToEndCompileRequest::addLibraryReference(const void* libData, size_t libDataSize) { // We need to deserialize and add the modules - RefPtr<ModuleLibrary> library; - SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)libData, libDataSize, this, library)); + ComPtr<IModuleLibrary> library; - const auto desc = ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); + SLANG_RETURN_ON_FAIL(loadModuleLibrary((const Byte*)libData, libDataSize, this, library)); // Create an artifact without any name (as one is not provided) - ComPtr<IArtifact> artifact(new Artifact(desc, String())); + auto artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR)); artifact->addRepresentation(library); return _addLibraryReference(this, artifact); |
