diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-16 03:39:41 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-16 00:39:41 -0700 |
| commit | ac71724c03392b429e44641a3641b2bcf7cc55fc (patch) | |
| tree | 8f7ffa61329dd24bc9be551e293840b6b94aab36 /source/compiler-core | |
| parent | 786f48d32340c36a06865a333ff9066033b5b2bc (diff) | |
Remove CompileResult to use IArtifact (#2357)
* #include an absolute path didn't work - because paths were taken to always be relative.
* WIP with hierarchical enums.
* Some small fixes and improvements around artifact desc related types.
* Improvements around hierarchical enum.
* Fixes to get Artifact types refactor to be able to execute tests.
* Attempt to better categorize PTX.
* Work around for potentially unused function warning.
* Typo fix.
* Simplify Artifact header.
* Small improvements around Artifact kind/payload/style.
* Added IDestroyable/ICastable
* Add IArtifactList.
* First impl of IArtifactUtil.
* Use the ICastable interface for IArtifactRepresentation.
* Added IArtifactRepresentation & IArtifactAssociated.
* Add SLANG_OVERRIDE to avoid gcc/clang warning.
* Fix calling convention issue on win32.
* Fix missing SLANG_OVERRIDE.
* First attempt at file abstraction around Artifact.
* Added creation of lock file.
* Move functionality for determining file paths to the IArtifactUtil.
Add casting to ICastable.
* Added some casting/finding mechanisms.
* Simplify IArtifact interface, and use Items for file reps.
* Fix problem with libraries on DXIL.
* Split out ArtifactRepresentation.
* Move ArtifactDesc functionality to ArtifactDescUtil. ArtifactInfoUtil becomes ArtifactDescUtil.
* Split implementations from the interfaces for Artifact.
* Use TypeTextUtil for target name outputting.
* Add artifact impls.
* Add ICastableList
* Added UnknownCastableAdapter
* Make ISlangSharedLibrary derive from ICastable, and remain backwards compatible with slang-llvm.
* Refactor Representation on Artifact.
* Make our ISlangBlobs also derive from ICastable.
Make ISlangBlob atomic ref counted.
* Split out CastableList and related types, and placed in core.
* Small fixes around IArtifact.
Improve IArtifact docs.
First impl of getChildren for IArtifact.
* Documentation improvements for Artifact related types.
* Fix typo.
* Special case adding a ICastableList to a LazyCastableList.
* Small simplification of LazyCastableList, by adding State member.
* Removed the ILockFile interface because IFileArtifactRepresentation can be used.
* Implement DiagnosticsArtifactRepresentation.
* Added PostEmitMetadataArtifactRepresentation
* Add searching by predicate.
Added handling of accessing Artifact as ISharedLibrary
* Fix typo.
* Add find to IArtifacgtList.
Fix some missing SLANG_NO_THROW.
* Small improvements around ArtifactDesc types.
* Another small change around ArtifactKind.
* Some more shuffling of ArtifactDesc.
* Make IArtifact castable
Remove IArtifactList
Made IArtifactContainer derive from IArtifact
Made ModuleLibrary atomic ref counted/given IModuleLibrary interface.
* Must call _requireChildren before any children access.
* Fix missing SLANG_MCALL on castAs.
* Fix missing SLANG_OVERRIDE.
* Added IArtifactHandler
* Use ICastable for basis of scope/lookup.
* WIP first attempt to remove CompileResult.
* Fix support for for downstream compiler shared library adapter.
* Fix issues found when replacing CompileResult.
* Fix typo.
* Fix getting items form 'significant' member of an Artifact.
* Split out ArtifactUtil & ArtifactHandler.
* Work around for problem on Visual studio.
* Improve searching.
* Add missing files.
Diffstat (limited to 'source/compiler-core')
17 files changed, 948 insertions, 538 deletions
diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 314703c0b..2c2b177c2 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -122,7 +122,7 @@ struct HierarchicalEnumTable return true; } type = m_parents[Index(type)]; - } while (Index(type) > Index(T::Base)); + } while (Index(type) >= Index(T::Base)); return false; } @@ -620,31 +620,6 @@ UnownedStringSlice ArtifactDescUtil::getDefaultExtension(const ArtifactDesc& des return getBaseNameFromPath(desc, path); } -/* static */String ArtifactDescUtil::getBaseName(IArtifact* artifact) -{ - if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact)) - { - return getBaseName(artifact->getDesc(), fileRep); - } - // Else use the name - return artifact->getName(); -} - -/* static */String ArtifactDescUtil::getParentPath(IFileArtifactRepresentation* fileRep) -{ - UnownedStringSlice path(fileRep->getPath()); - return Path::getParentDirectory(path); -} - -/* static */String ArtifactDescUtil::getParentPath(IArtifact* artifact) -{ - if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact)) - { - return getParentPath(fileRep); - } - return String(); -} - /* static */SlangResult ArtifactDescUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath) { outPath.Clear(); @@ -690,10 +665,4 @@ 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 604d5a4ce..e3d1e6478 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -75,23 +75,29 @@ struct ArtifactDescUtil /// If there is a path set, will extract the name from that (stripping prefix, extension as necessary). /// Else if there is an explicit name set, this is returned. /// Else returns the empty string - static String getBaseName(IArtifact* artifact); + static String getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep); - /// Get the parent path (empty if there isn't one) - static String getParentPath(IArtifact* artifact); - static String getParentPath(IFileArtifactRepresentation* fileRep); - /// Given a desc, and a basePath returns a suitable path for a entity of specified desc static SlangResult calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath); - /// Make ArtifactDesc from target + /// Given a target returns the ArtifactDesc static ArtifactDesc makeDescFromCompileTarget(SlangCompileTarget target); - /// Create an empty container which is compatible with the desc - static ComPtr<IArtifactContainer> createContainer(const ArtifactDesc& desc); + /// Make ArtifactDesc from target + static bool isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from); }; +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +inline /* static */bool ArtifactDescUtil::isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from) +{ + // TODO(JS): Currently this ignores flags in desc. That may or may not be right + // long term. + return isDerivedFrom(desc.kind, from.kind) && + isDerivedFrom(desc.payload, from.payload) && + isDerivedFrom(desc.style, from.style); +} + } // namespace Slang #endif diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp new file mode 100644 index 000000000..c93a4907b --- /dev/null +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -0,0 +1,380 @@ +// slang-artifact-handler-impl.cpp +#include "slang-artifact-handler-impl.h" + +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" + +#include "slang-artifact-desc-util.h" + +#include "slang-artifact-helper.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" + +// For workaround for DownstreamResult +#include "slang-downstream-compiler.h" + +namespace Slang { + +// A temporary class that adapts `ISlangSharedLibrary_Dep1` to ISlangSharedLibrary + +class SharedLibraryDep1Adapter : public ComBaseObject, public ISlangSharedLibrary +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; + + // ISlangSharedLibrary + virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) SLANG_OVERRIDE { return m_contained->findSymbolAddressByName(name); } + + SharedLibraryDep1Adapter(ISlangSharedLibrary_Dep1* dep1) : + m_contained(dep1) + { + } + +protected: + void* getInterface(const Guid& guid) + { + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == ISlangSharedLibrary::getTypeGuid()) + { + return static_cast<ISlangSharedLibrary*>(this); + } + return nullptr; + } + void* getObject(const Guid& guid) + { + SLANG_UNUSED(guid); + return nullptr; + } + + ComPtr<ISlangSharedLibrary_Dep1> m_contained; +}; + +void* SharedLibraryDep1Adapter::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +/* Hack to take into account downstream compilers shared library interface might need an adapter */ +static SlangResult _getDownstreamSharedLibrary(DownstreamCompileResult* downstreamResult, ComPtr<ISlangSharedLibrary>& outSharedLibrary) +{ + ComPtr<ISlangSharedLibrary> lib; + SLANG_RETURN_ON_FAIL(downstreamResult->getHostCallableSharedLibrary(lib)); + + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary::getTypeGuid(), (void**)outSharedLibrary.writeRef()))) + { + return SLANG_OK; + } + + ComPtr<ISlangSharedLibrary_Dep1> libDep1; + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary_Dep1::getTypeGuid(), (void**)libDep1.writeRef()))) + { + // Okay, we need to adapt for now + outSharedLibrary = new SharedLibraryDep1Adapter(libDep1); + return SLANG_OK; + } + return SLANG_E_NOT_FOUND; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; + +SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) +{ + if (auto ptr = getInterface(uuid)) + { + addRef(); + *outObject = static_cast<IArtifactHandler*>(this); + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; +} + +void* DefaultArtifactHandler::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + +void* DefaultArtifactHandler::getInterface(const Guid& uuid) +{ + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ICastable::getTypeGuid() || + uuid == IArtifactHandler::getTypeGuid()) + { + return static_cast<IArtifactHandler*>(this); + } + + return nullptr; +} + +void* DefaultArtifactHandler::getObject(const Guid& uuid) +{ + SLANG_UNUSED(uuid); + return nullptr; +} + +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) +{ + 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); +} + +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +{ + SLANG_ASSERT(castable); + + if (canKeep(keep)) + { + artifact->addRepresentation(castable); + } + + castable->addRef(); + *outCastable = castable; + return SLANG_OK; +} + +SlangResult DefaultArtifactHandler::expandChildren(IArtifactContainer* container) +{ + SlangResult res = container->getExpandChildrenResult(); + if (res != SLANG_E_UNINITIALIZED) + { + // It's already expanded + return res; + } + + // 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; +} + + + +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; + } + } + } + + // TODO(JS): Temporary whilst DownstreamCompileResult is + // Special handling for DownstreamCompileResult + if (auto downstreamResult = findRepresentation<DownstreamCompileResult>(artifact)) + { + if (guid == ISlangBlob::getTypeGuid()) + { + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(downstreamResult->getBinary(blob)); + return _addRepresentation(artifact, keep, blob, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr<ISlangSharedLibrary> lib; + SLANG_RETURN_ON_FAIL(_getDownstreamSharedLibrary(downstreamResult, lib)); + return _addRepresentation(artifact, keep, lib, outCastable); + } + } + + // Normal construction + 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); + } + + return SLANG_E_NOT_AVAILABLE; +} + +static bool _isFileSystemFile(ICastable* castable, void* data) +{ + if (auto fileRep = as<IFileArtifactRepresentation>(castable)) + { + ISlangMutableFileSystem* fileSystem = (ISlangMutableFileSystem*)data; + if (fileRep->getFileSystem() == fileSystem) + { + return true; + } + } + return false; +} + +SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) +{ + // See if we already have it + if (auto fileRep = as<IFileArtifactRepresentation>(artifact->findRepresentationWithPredicate(&_isFileSystemFile, fileSystem))) + { + fileRep->addRef(); + *outFileRep = fileRep; + return SLANG_OK; + } + + auto helper = DefaultArtifactHelper::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(getIntermediateKeep(keep), blob.writeRef())); + + // Okay we need to store as a temporary. Get a lock file. + ComPtr<IFileArtifactRepresentation> lockFile; + SLANG_RETURN_ON_FAIL(helper->createLockFile(artifact->getName(), fileSystem, lockFile.writeRef())); + + // Now we need the appropriate name for this item + ComPtr<ISlangBlob> pathBlob; + SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef())); + + const auto path = StringUtil::getString(pathBlob); + + // Write the contents + SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + + ComPtr<IFileArtifactRepresentation> fileRep; + + // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed + // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path + // might mean the lock file and the rep have the same path. + // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile + + // If the paths are identical, we can just use the lock file for the rep + if (UnownedStringSlice(lockFile->getPath()) == path.getUnownedSlice()) + { + fileRep.swap(lockFile); + } + else + { + // Create a new rep that references the lock file + fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, lockFile->getFileSystem()); + } + + // Create the rep + if (canKeep(keep)) + { + artifact->addRepresentation(fileRep); + } + + // Return the file + *outFileRep = fileRep.detach(); + return SLANG_OK; +} + +SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) +{ + // 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 DefaultArtifactHandler::_loadBlob(IArtifact* artifact, ArtifactKeep keep, ISlangBlob** outBlob) +{ + 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; + } + } + } + + // Wasn't able to construct + if (!blob) + { + return SLANG_E_NOT_FOUND; + } + + *outBlob = blob.detach(); + return SLANG_OK; +} + +} // namespace Slang diff --git a/source/compiler-core/slang-artifact-handler-impl.h b/source/compiler-core/slang-artifact-handler-impl.h new file mode 100644 index 000000000..c7861b598 --- /dev/null +++ b/source/compiler-core/slang-artifact-handler-impl.h @@ -0,0 +1,45 @@ +// slang-artifact-handler-impl.h +#ifndef SLANG_ARTIFACT_HANDLER_IMPL_H +#define SLANG_ARTIFACT_HANDLER_IMPL_H + +#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; +}; + +} // namespace Slang + +#endif diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp new file mode 100644 index 000000000..ce6fab7d9 --- /dev/null +++ b/source/compiler-core/slang-artifact-helper.cpp @@ -0,0 +1,124 @@ +// slang-artifact-helper.cpp +#include "slang-artifact-helper.h" + +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" + +#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 { + + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHelper !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */DefaultArtifactHelper DefaultArtifactHelper::g_singleton; + +SlangResult DefaultArtifactHelper::queryInterface(SlangUUID const& uuid, void** outObject) +{ + if (auto intf = getInterface(uuid)) + { + *outObject = intf; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; +} + +void* DefaultArtifactHelper::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + +void* DefaultArtifactHelper::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == IArtifactHelper::getTypeGuid()) + { + return static_cast<IArtifactHelper*>(this); + } + return nullptr; +} + +void* DefaultArtifactHelper::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +SlangResult DefaultArtifactHelper::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +{ + *outArtifact = inName ? + Artifact::create(desc, inName).detach() : + Artifact::create(desc).detach(); + + return SLANG_OK; +} + +SlangResult DefaultArtifactHelper::createArtifactContainer(const ArtifactDesc& desc, const char* inName, IArtifactContainer** outArtifactContainer) +{ + *outArtifactContainer = inName ? + ArtifactContainer::create(desc, inName).detach() : + ArtifactContainer::create(desc).detach(); + + return SLANG_OK; +} + +ArtifactKind DefaultArtifactHelper::getKindParent(ArtifactKind kind) { return getParent(kind); } +UnownedStringSlice DefaultArtifactHelper::getKindName(ArtifactKind kind) { return getName(kind); } +bool DefaultArtifactHelper::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } + +ArtifactPayload DefaultArtifactHelper::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } +UnownedStringSlice DefaultArtifactHelper::getPayloadName(ArtifactPayload payload) { return getName(payload); } +bool DefaultArtifactHelper::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } + +ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) { return getParent(style); } +UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) { return getName(style); } +bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } + +SlangResult DefaultArtifactHelper::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 DefaultArtifactHelper::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 DefaultArtifactHelper::makeDescFromCompileTarget(SlangCompileTarget target) +{ + return ArtifactDescUtil::makeDescFromCompileTarget(target); +} + +} // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h new file mode 100644 index 000000000..41bf0f2c9 --- /dev/null +++ b/source/compiler-core/slang-artifact-helper.h @@ -0,0 +1,84 @@ +// slang-artifact-helper.h +#ifndef SLANG_ARTIFACT_HELPER_H +#define SLANG_ARTIFACT_HELPER_H + +#include "slang-artifact.h" +#include "slang-artifact-representation.h" + +#include "../core/slang-com-object.h" + +namespace Slang +{ + +class IArtifactHelper : public ICastable +{ + 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 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; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) = 0; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; + virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) = 0; + + /// 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; + + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) = 0; +}; + +class DefaultArtifactHelper : public IArtifactHelper +{ +public: + // ISlangUnknown + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactInterface + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL 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; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; + + static IArtifactHelper* getSingleton() { return &g_singleton; } + +protected: + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); + + static DefaultArtifactHelper g_singleton; +}; + +} // namespace Slang + +#endif diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index 061aa9ee7..ed952e72c 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -6,10 +6,21 @@ #include "slang-artifact-util.h" #include "slang-artifact-desc-util.h" +#include "slang-artifact-handler-impl.h" + #include "../core/slang-castable-list-impl.h" namespace Slang { +static bool _checkSelf(IArtifact::FindStyle findStyle) +{ + return Index(findStyle) <= Index(IArtifact::FindStyle::SelfOrChildren); +} + +static bool _checkChildren(IArtifact::FindStyle findStyle) +{ + return Index(findStyle) >= Index(IArtifact::FindStyle::SelfOrChildren); +} /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -187,6 +198,26 @@ ICastableList* Artifact::getRepresentationList() return m_representations.requireList(); } +IArtifact* Artifact::findArtifactByDerivedDesc(FindStyle findStyle, const ArtifactDesc& from) +{ + return (_checkSelf(findStyle) && ArtifactDescUtil::isDescDerivedFrom(m_desc, from)) ? this : nullptr; +} + +IArtifact* Artifact::findArtifactByPredicate(FindStyle findStyle, FindFunc func, void* data) +{ + return (_checkSelf(findStyle) && func(this, data)) ? this : nullptr; +} + +IArtifact* Artifact::findArtifactByName(FindStyle findStyle, const char* name) +{ + return (_checkSelf(findStyle) && m_name == name) ? this : nullptr; +} + +IArtifact* Artifact::findArtifactByDesc(FindStyle findStyle, const ArtifactDesc& desc) +{ + return (_checkSelf(findStyle) && m_desc == desc) ? this : nullptr; +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactContainer !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* ArtifactContainer::getInterface(const Guid& guid) @@ -267,67 +298,79 @@ void ArtifactContainer::clearChildren() m_children.clearAndDeallocate(); } -IArtifact* ArtifactContainer::findChildByDesc(const ArtifactDesc& desc) +static bool _isDerivedDesc(IArtifact* artifact, void* data) { - _requireChildren(); - - for (IArtifact* artifact : m_children) - { - if (artifact->getDesc() == desc) - { - return artifact; - } - } - return nullptr; + const ArtifactDesc& from = *(const ArtifactDesc*)data; + return ArtifactDescUtil::isDescDerivedFrom(artifact->getDesc(), from); } -IArtifact* ArtifactContainer::findChildByDerivedDesc(const ArtifactDesc& desc) +static bool _isDesc(IArtifact* artifact, void* data) { - _requireChildren(); + const ArtifactDesc& desc = *(const ArtifactDesc*)data; + return desc == artifact->getDesc(); +} - for (IArtifact* artifact : m_children) +static bool _isName(IArtifact* artifact, void* data) +{ + const char* name = (const char*)data; + const char* artifactName = artifact->getName(); + if (artifactName == nullptr) { - 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 false; } - return nullptr; + return ::strcmp(name, artifactName) == 0; } -IArtifact* ArtifactContainer::findChildByName(const char* name) + +IArtifact* ArtifactContainer::findArtifactByDerivedDesc(FindStyle findStyle, const ArtifactDesc& from) { - _requireChildren(); + return findArtifactByPredicate(findStyle, _isDerivedDesc, const_cast<ArtifactDesc*>(&from)); +} - for (IArtifact* artifact : m_children) - { - const char* artifactName = artifact->getName(); +IArtifact* ArtifactContainer::findArtifactByName(FindStyle findStyle, const char* name) +{ + return findArtifactByPredicate(findStyle, _isName, const_cast<char*>(name)); +} - if (artifactName == name || - ::strcmp(artifactName, name) == 0) - { - return artifact; - } - } - return nullptr; +IArtifact* ArtifactContainer::findArtifactByDesc(FindStyle findStyle, const ArtifactDesc& desc) +{ + return findArtifactByPredicate(findStyle, _isDesc, const_cast<ArtifactDesc*>(&desc)); } -IArtifact* ArtifactContainer::findChildByPredicate(FindFunc func, void* data) +IArtifact* ArtifactContainer::findArtifactByPredicate(FindStyle findStyle, FindFunc func, void* data) { - _requireChildren(); + if (_checkSelf(findStyle) && func(this, data)) + { + return this; + } - for (IArtifact* artifact : m_children) + if (_checkChildren(findStyle)) { - if (func(artifact, data)) + auto children = getChildren(); + + // First search the children + for (auto child : children) { - return artifact; + if (func(child, data)) + { + return child; + } + } + + // Then the childrens recursively + if (findStyle == FindStyle::Recursive || + findStyle == FindStyle::ChildrenRecursive) + { + for (auto child : children) + { + if (auto found = child->findArtifactByPredicate(FindStyle::ChildrenRecursive, func, data)) + { + return found; + } + } } } + return nullptr; } diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index 8b15d0664..e0a976929 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -61,18 +61,20 @@ public: 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; + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() SLANG_OVERRIDE { return Slice<IArtifact*>(nullptr, 0); } + + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDerivedDesc(FindStyle findStyle, const ArtifactDesc& desc) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByPredicate(FindStyle findStyle, FindFunc func, void* data) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByName(FindStyle findStyle, const char* name) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDesc(FindStyle findStyle, const ArtifactDesc& desc) 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)); } @@ -115,19 +117,21 @@ public: /// ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + /// IArtifact + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDerivedDesc(FindStyle findStyle, const ArtifactDesc& desc) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByPredicate(FindStyle findStyle, FindFunc func, void* data) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByName(FindStyle findStyle, const char* name) SLANG_OVERRIDE; + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDesc(FindStyle findStyle, const ArtifactDesc& desc) 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)); } diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 6ae2d646f..32ec055d8 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -178,10 +178,58 @@ void* PostEmitMetadataArtifactRepresentation::getObject(const Guid& uuid) return nullptr; } +void* PostEmitMetadataArtifactRepresentation::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + + Slice<ShaderBindingRange> PostEmitMetadataArtifactRepresentation::getBindingRanges() { - return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount()); + return Slice<ShaderBindingRange>(m_metadata.usedBindings.getBuffer(), m_metadata.usedBindings.getCount()); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ObjectArtifactRepresentation::castAs(const Guid& guid) +{ + + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + +void* ObjectArtifactRepresentation::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactRepresentation::getTypeGuid()) + { + return static_cast<IArtifactRepresentation*>(this); + } + return nullptr; +} + +void* ObjectArtifactRepresentation::getObject(const Guid& guid) +{ + if (guid == getTypeGuid()) + { + return this; + } + + // If matches the guid saved in the object, we return that + if (m_object && m_typeGuid == guid) + { + return m_object; + } + + return nullptr; } - } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index 00d36ab49..fb2e37c76 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -10,8 +10,6 @@ #include "../core/slang-com-object.h" #include "../core/slang-memory-arena.h" -//#include "../core/slang-string-slice-pool.h" - namespace Slang { @@ -172,7 +170,10 @@ struct ShaderBindingRange } }; -typedef List<ShaderBindingRange> ShaderBindingRanges; +struct PostEmitMetadata +{ + List<ShaderBindingRange> usedBindings; +}; class PostEmitMetadataArtifactRepresentation : public ComBaseObject, public IPostEmitMetadataArtifactRepresentation { @@ -184,15 +185,45 @@ public: // 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; + SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** outBlob) SLANG_OVERRIDE { SLANG_UNUSED(outBlob); return SLANG_E_NOT_AVAILABLE; } + SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return true; } // 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; + PostEmitMetadata m_metadata; +}; + +/* This allows wrapping any object to be an artifact representation. + +NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI bounday remains risky! +*/ +class ObjectArtifactRepresentation : public ComBaseObject, public IArtifactRepresentation +{ +public: + SLANG_CLASS_GUID(0xb9d5af57, 0x725b, 0x45f8, { 0xac, 0xed, 0x18, 0xf4, 0xa8, 0x4b, 0xf4, 0x73 }) + + 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** outBlob) SLANG_OVERRIDE { SLANG_UNUSED(outBlob); return SLANG_E_NOT_AVAILABLE; } + SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return m_object; } + + ObjectArtifactRepresentation(const Guid& typeGuid, RefObject* obj): + m_typeGuid(typeGuid), + m_object(obj) + { + } + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + Guid m_typeGuid; ///< Will return m_object if a cast to m_typeGuid is given + RefPtr<RefObject> m_object; ///< The object }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 366ab4111..f93924afb 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -8,370 +8,100 @@ #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 { -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ - -/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; - -SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) -{ - if (auto ptr = getInterface(uuid)) - { - addRef(); - *outObject = static_cast<IArtifactHandler*>(this); - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; -} - -void* DefaultArtifactHandler::castAs(const Guid& guid) -{ - if (auto ptr = getInterface(guid)) - { - return ptr; - } - return getObject(guid); -} - -void* DefaultArtifactHandler::getInterface(const Guid& uuid) -{ - if (uuid == ISlangUnknown::getTypeGuid() || - uuid == ICastable::getTypeGuid() || - uuid == IArtifactHandler::getTypeGuid()) - { - return static_cast<IArtifactHandler*>(this); - } - - return nullptr; -} - -void* DefaultArtifactHandler::getObject(const Guid& uuid) -{ - SLANG_UNUSED(uuid); - return nullptr; -} - -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) -{ - 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); -} - -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +/* static */ComPtr<IArtifactContainer> ArtifactUtil::createContainer(const ArtifactDesc& desc) { - SLANG_ASSERT(castable); - - if (canKeep(keep)) - { - artifact->addRepresentation(castable); - } - - castable->addRef(); - *outCastable = castable; - return SLANG_OK; + const auto containerDesc = ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::CompileResults, desc.style); + return ArtifactContainer::create(containerDesc); } -SlangResult DefaultArtifactHandler::expandChildren(IArtifactContainer* container) +/* static */ComPtr<IArtifactContainer> ArtifactUtil::createResultsContainer() { - SlangResult res = container->getExpandChildrenResult(); - if (res != SLANG_E_UNINITIALIZED) - { - // It's already expanded - return res; - } - - // 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; + return ArtifactContainer::create(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::CompileResults)); } -SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) +/* static */ComPtr<IArtifact> ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget target) { - - // 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; - } - } - } + auto desc = ArtifactDescUtil::makeDescFromCompileTarget(target); - 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); - } + if (isDerivedFrom(desc.kind, ArtifactKind::Container)) + { + auto container = ArtifactContainer::create(desc); - return SLANG_E_NOT_AVAILABLE; + ComPtr<IArtifact> artifact; + artifact.attach(container.detach()); + return artifact; + } + else + { + return Artifact::create(desc); + } } -static bool _isFileSystemFile(ICastable* castable, void* data) +/* static */bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data) { - if (auto fileRep = as<IFileArtifactRepresentation>(castable)) - { - ISlangMutableFileSystem* fileSystem = (ISlangMutableFileSystem*)data; - if (fileRep->getFileSystem() == fileSystem) - { - return true; - } - } - return false; -} - -SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) -{ - // See if we already have it - if (auto fileRep = as<IFileArtifactRepresentation>(artifact->findRepresentationWithPredicate(&_isFileSystemFile, fileSystem))) - { - fileRep->addRef(); - *outFileRep = fileRep; - return SLANG_OK; - } - - auto util = ArtifactUtilImpl::getSingleton(); + SLANG_UNUSED(data); - // 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(getIntermediateKeep(keep), blob.writeRef())); + const auto desc = artifact->getDesc(); - // Okay we need to store as a temporary. Get a lock file. - ComPtr<IFileArtifactRepresentation> lockFile; - SLANG_RETURN_ON_FAIL(util->createLockFile(artifact->getName(), fileSystem, lockFile.writeRef())); + // Containers are not significant as of themselves, they may contain something tho + if (isDerivedFrom(desc.kind, ArtifactKind::Container)) + { + return false; + } - // Now we need the appropriate name for this item - ComPtr<ISlangBlob> pathBlob; - SLANG_RETURN_ON_FAIL(util->calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef())); + // If it has no payload.. we are done + if (desc.payload == ArtifactPayload::None || + desc.payload == ArtifactPayload::Invalid) + { + return false; + } - const auto path = StringUtil::getString(pathBlob); + // If it's binary like or assembly/source we it's significant + if (isDerivedFrom(desc.kind, ArtifactKind::BinaryLike) || + desc.kind == ArtifactKind::Assembly || + desc.kind == ArtifactKind::Source) + { + return true; + } - // Write the contents - SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + /* Hmm, we might want to have a base class for 'signifiant' payloads, + where signifiance here means somewhat approximately 'the meat' of a compilation result, + as contrasted with 'meta data', 'diagnostics etc'*/ + if (isDerivedFrom(desc.payload, ArtifactPayload::MetaData)) + { + return false; + } - ComPtr<IFileArtifactRepresentation> fileRep; - - // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed - // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path - // might mean the lock file and the rep have the same path. - // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile - - // If the paths are identical, we can just use the lock file for the rep - if (UnownedStringSlice(lockFile->getPath()) == path.getUnownedSlice()) - { - fileRep.swap(lockFile); - } - else - { - // Create a new rep that references the lock file - fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, lockFile->getFileSystem()); - } - - // Create the rep - if (canKeep(keep)) - { - artifact->addRepresentation(fileRep); - } - - // Return the file - *outFileRep = fileRep.detach(); - return SLANG_OK; + return true; } -SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) +/* static */String ArtifactUtil::getBaseName(IArtifact* artifact) { - // 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 DefaultArtifactHandler::_loadBlob(IArtifact* artifact, ArtifactKeep keep, ISlangBlob** outBlob) -{ - 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; - } - } - } - - // Wasn't able to construct - if (!blob) - { - 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; -} - -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; + if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact)) + { + return ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep); + } + // Else use the name + return artifact->getName(); } -SlangResult ArtifactUtilImpl::calcArtifactPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) +/* static */String ArtifactUtil::getParentPath(IFileArtifactRepresentation* fileRep) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); - *outPath = StringBlob::create(path).detach(); - return SLANG_OK; + UnownedStringSlice path(fileRep->getPath()); + return Path::getParentDirectory(path); } -ArtifactDesc ArtifactUtilImpl::makeDescFromCompileTarget(SlangCompileTarget target) +/* static */String ArtifactUtil::getParentPath(IArtifact* artifact) { - return ArtifactDescUtil::makeDescFromCompileTarget(target); + if (auto fileRep = findRepresentation<IFileArtifactRepresentation>(artifact)) + { + return getParentPath(fileRep); + } + return String(); } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h index 5e44b7565..541a1f058 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -5,104 +5,35 @@ #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 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; - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; - - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) = 0; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) = 0; - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; - - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) = 0; - - /// 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; - - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) = 0; -}; - -class ArtifactUtilImpl : public IArtifactUtil +struct ArtifactUtil { -public: - // ISlangUnknown - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - - // IArtifactInterface - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL 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; - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; + /// Get the base name of this artifact. + /// If there is a path set, will extract the name from that (stripping prefix, extension as necessary). + /// Else if there is an explicit name set, this is returned. + /// Else returns the empty string + static String getBaseName(IArtifact* artifact); - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; + /// Get the parent path (empty if there isn't one) + static String getParentPath(IArtifact* artifact); + static String getParentPath(IFileArtifactRepresentation* fileRep); - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescFromCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; + /// Create an empty container which is compatible with the desc + static ComPtr<IArtifactContainer> createContainer(const ArtifactDesc& desc); - static IArtifactUtil* getSingleton() { return &g_singleton; } + /// Create a generic container + static ComPtr<IArtifactContainer> createResultsContainer(); -protected: - void* getInterface(const Guid& guid); + /// Creates an empty artifact for a type + static ComPtr<IArtifact> createArtifactForCompileTarget(SlangCompileTarget target); - static ArtifactUtilImpl g_singleton; + /// Returns true if an artifact is 'significant' + static bool isSignificant(IArtifact* artifact, void* data = nullptr); + /// Find a significant artifact + static IArtifact* findSignificant(IArtifact* artifact) { return artifact->findArtifactByPredicate(IArtifact::FindStyle::SelfOrChildren, &isSignificant, nullptr); } }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index e399578a9..bde7f9a08 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -307,6 +307,16 @@ class IArtifact : public ICastable public: SLANG_COM_INTERFACE(0x57375e20, 0xbed, 0x42b6, { 0x9f, 0x5e, 0x59, 0x4f, 0x6, 0x2b, 0xe6, 0x90 }) + typedef bool (*FindFunc)(IArtifact* artifact, void* data); + enum class FindStyle : uint8_t + { + Self, ///< Just on self + SelfOrChildren, ///< Self, or if container just the children + Recursive, ///< On self plus any children recursively + Children, ///< Only on children + ChildrenRecursive, ///< Only on children recursively + }; + typedef ArtifactDesc Desc; typedef ArtifactKind Kind; @@ -361,6 +371,18 @@ public: /// 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; + + /// Get the children, will only remain valid if no mutation of children list + virtual SLANG_NO_THROW Slice<IArtifact*> SLANG_MCALL getChildren() = 0; + + /// Find an artifact that matches desc allowing derivations. Flags is ignored + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDerivedDesc(FindStyle findStyle, const ArtifactDesc& desc) = 0; + /// Find an artifact that predicate matches + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByPredicate(FindStyle findStyle, FindFunc func, void* data) = 0; + /// Find by name + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByName(FindStyle findStyle, const char* name) = 0; + /// Find by desc exactly + virtual SLANG_NO_THROW IArtifact* SLANG_MCALL findArtifactByDesc(FindStyle findStyle, const ArtifactDesc& desc) = 0; }; class IArtifactContainer : public IArtifact @@ -368,30 +390,19 @@ 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> diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 9d58f6678..666ca5568 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -120,7 +120,8 @@ struct DownstreamDiagnostics class DownstreamCompileResult : public RefObject { public: - + SLANG_CLASS_GUID(0xdfc5d318, 0x8675, 0x40ef, { 0xbd, 0x7b, 0x4, 0xa4, 0xff, 0x66, 0x11, 0x30 }) + virtual SlangResult getHostCallableSharedLibrary(ComPtr<ISlangSharedLibrary>& outLibrary) = 0; virtual SlangResult getBinary(ComPtr<ISlangBlob>& outBlob) = 0; diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 8467cbbdc..771aa870a 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -19,7 +19,7 @@ #include "../core/slang-shared-library.h" -#include "../compiler-core/slang-artifact-desc-util.h" +#include "../compiler-core/slang-artifact-util.h" // Enable calling through to `dxc` to // generate code on Windows. @@ -83,7 +83,7 @@ static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlic static UnownedStringSlice _addName(IArtifact* artifact, StringSlicePool& pool) { - return _addName(ArtifactDescUtil::getBaseName(artifact).getUnownedSlice(), pool); + return _addName(ArtifactUtil::getBaseName(artifact).getUnownedSlice(), pool); } class DxcIncludeHandler : public IDxcIncludeHandler diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 3a0217d86..c1e6e8fbc 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -11,6 +11,7 @@ #include "../core/slang-string-slice-pool.h" #include "slang-artifact-desc-util.h" +#include "slang-artifact-util.h" namespace Slang { @@ -649,7 +650,7 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse // Get the name and path (can be empty) to the library SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); - libPathPool.add(ArtifactDescUtil::getParentPath(fileRep)); + libPathPool.add(ArtifactUtil::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 43c991337..21db9570a 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -12,7 +12,9 @@ #endif #include "../core/slang-io.h" + #include "slang-artifact-desc-util.h" +#include "slang-artifact-util.h" namespace Slang { @@ -270,7 +272,7 @@ namespace Slang ComPtr<IFileArtifactRepresentation> fileRep; SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); - libPathPool.add(ArtifactDescUtil::getParentPath(fileRep)); + libPathPool.add(ArtifactUtil::getParentPath(fileRep)); // We need the extension for windows cmdLine.addArg(ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep) + ".lib"); } |
