diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-09 10:31:22 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-09 10:31:22 -0400 |
| commit | c0733be56dc24ef0eb67b26fe0c49d3419e75773 (patch) | |
| tree | e094e31981c69e887ff9df84df07defe9eb77bf5 /source/compiler-core | |
| parent | 2db8c15c04f2aade49636e42f0adee636afb3b73 (diff) | |
Support for Items on IArtifact (#2347)
* #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.
Diffstat (limited to 'source/compiler-core')
| -rw-r--r-- | source/compiler-core/slang-artifact-info.cpp | 75 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-info.h | 6 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-util.cpp | 90 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-util.h | 15 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact.cpp | 325 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact.h | 186 | ||||
| -rw-r--r-- | source/compiler-core/slang-gcc-compiler-util.cpp | 8 | ||||
| -rw-r--r-- | source/compiler-core/slang-visual-studio-compiler-util.cpp | 7 |
8 files changed, 488 insertions, 224 deletions
diff --git a/source/compiler-core/slang-artifact-info.cpp b/source/compiler-core/slang-artifact-info.cpp index f76bf45f0..1d309e3c7 100644 --- a/source/compiler-core/slang-artifact-info.cpp +++ b/source/compiler-core/slang-artifact-info.cpp @@ -342,33 +342,80 @@ UnownedStringSlice ArtifactInfoUtil::getDefaultExtension(const ArtifactDesc& des return name; } -/* static */String ArtifactInfoUtil::getBaseName(IArtifact* artifact) +/* static */String ArtifactInfoUtil::getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep) { - const auto pathType = artifact->getPathType(); + UnownedStringSlice path(fileRep->getPath()); + return getBaseNameFromPath(desc, path); +} - // If we have a path, get the base name from that - if (pathType != ArtifactPathType::None) +/* static */String ArtifactInfoUtil::getBaseName(IArtifact* artifact) +{ + if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact)) { - UnownedStringSlice path(artifact->getPath()); - const auto desc = artifact->getDesc(); - - return getBaseNameFromPath(desc, path); + return getBaseName(artifact->getDesc(), fileRep); } - // Else use the name return artifact->getName(); } +/* static */String ArtifactInfoUtil::getParentPath(IFileArtifactRepresentation* fileRep) +{ + UnownedStringSlice path(fileRep->getPath()); + return Path::getParentDirectory(path); +} + /* static */String ArtifactInfoUtil::getParentPath(IArtifact* artifact) { - const auto pathType = artifact->getPathType(); - const auto path = artifact->getPath(); - - if (pathType != ArtifactPathType::None && *path != 0) + if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact)) { - return Path::getParentDirectory(path); + return getParentPath(fileRep); } return String(); } +/* static */SlangResult ArtifactInfoUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath) +{ + outPath.Clear(); + + UnownedStringSlice baseName; + + // Append the directory + Index pos = Path::findLastSeparatorIndex(basePath); + if (pos >= 0) + { + outPath.append(basePath.head(pos)); + outPath.append(Path::kPathDelimiter); + + baseName = basePath.tail(pos + 1); + } + + if (baseName.getLength() == 0) + { + baseName = toSlice("unknown"); + } + + if (ArtifactInfoUtil::isCpuBinary(desc) && + (desc.kind == ArtifactKind::SharedLibrary || + desc.kind == ArtifactKind::Library)) + { + const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; + if (isSharedLibraryPrefixPlatform) + { + outPath << "lib"; + outPath << baseName; + } + } + + // If there is an extension append it + const UnownedStringSlice ext = ArtifactInfoUtil::getDefaultExtension(desc); + + if (ext.getLength()) + { + outPath.appendChar('.'); + outPath.append(ext); + } + + return SLANG_OK; +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-info.h b/source/compiler-core/slang-artifact-info.h index 393771a6f..9f741cbbe 100644 --- a/source/compiler-core/slang-artifact-info.h +++ b/source/compiler-core/slang-artifact-info.h @@ -52,9 +52,15 @@ struct ArtifactInfoUtil /// 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); + }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 3ca10446c..5c1641f7f 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -3,8 +3,13 @@ #include "slang-artifact-info.h" +#include "../core/slang-file-system.h" +#include "../core/slang-io.h" + namespace Slang { +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtilImpl !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* static */ArtifactUtilImpl ArtifactUtilImpl::g_singleton; SlangResult ArtifactUtilImpl::queryInterface(SlangUUID const& uuid, void** outObject) @@ -60,4 +65,89 @@ ArtifactStyle ArtifactUtilImpl::getStyleParent(ArtifactStyle style) { return get 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, ILockFile** 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<ILockFile> lockFile(new LockFile(lockPath, 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(ArtifactInfoUtil::calcPathForDesc(desc, basePath, path)); + + auto blob = new StringBlob(path); + blob->addRef(); + *outPath = blob; + return SLANG_OK; +} + +SlangResult ArtifactUtilImpl::requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFile) +{ + // See if we already have it + if (auto fileRep = findItem<IFileArtifactRepresentation>(artifact)) + { + fileRep->addRef(); + *outFile = fileRep; + return SLANG_OK; + } + + // 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())); + + // Okay we need to store as a temporary. Get a lock file. + ComPtr<ILockFile> lockFile; + SLANG_RETURN_ON_FAIL(createLockFile(artifact->getName(), nullptr, 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())); + + const auto path = StringUtil::getString(pathBlob); + + // Write the contents + SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + + // If the paths are identical we don't need a lock file + if (UnownedStringSlice(lockFile->getPath()) == path.getUnownedSlice()) + { + // Make the lockFile no longer own the file + lockFile->disown(); + // We no longer need the lock file + lockFile.setNull(); + } + + // Create the rep + IFileArtifactRepresentation* fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, nullptr); + if (canKeep(keep)) + { + artifact->addItem(fileRep); + } + + // Return it + fileRep->addRef(); + *outFile = fileRep; + return SLANG_OK; +} + } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h index 2b006fd78..f60578d14 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -26,10 +26,19 @@ class IArtifactUtil : public ISlangUnknown 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, ILockFile** 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; + + /// Default implementation of getting + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFileRep) = 0; }; class ArtifactUtilImpl : public IArtifactUtil { +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; } @@ -52,6 +61,12 @@ class ArtifactUtilImpl : public IArtifactUtil 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, ILockFile** 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 SlangResult SLANG_MCALL requireFileDefaultImpl(IArtifact* artifact, ArtifactKeep keep, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + static IArtifactUtil* getSingleton() { return &g_singleton; } protected: diff --git a/source/compiler-core/slang-artifact.cpp b/source/compiler-core/slang-artifact.cpp index cb77f5140..cefb8d753 100644 --- a/source/compiler-core/slang-artifact.cpp +++ b/source/compiler-core/slang-artifact.cpp @@ -3,10 +3,14 @@ #include "slang-artifact-info.h" +#include "../core/slang-file-system.h" + #include "../core/slang-type-text-util.h" #include "../core/slang-io.h" #include "../core/slang-array-view.h" +#include "slang-artifact-util.h" + namespace Slang { namespace { // anonymous @@ -276,6 +280,139 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL SLANG_UNEXPECTED("Unhandled type"); } +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* FileArtifactRepresentation::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactRepresentation::getTypeGuid() || + guid == IFileArtifactRepresentation::getTypeGuid()) + { + return static_cast<IFileArtifactRepresentation*>(this); + } + return nullptr; +} + +void* FileArtifactRepresentation::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +ISlangMutableFileSystem* FileArtifactRepresentation::_getFileSystem() +{ + return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton(); +} + +void* FileArtifactRepresentation::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +SlangResult FileArtifactRepresentation::writeToBlob(ISlangBlob** blob) +{ + if (m_kind == Kind::NameOnly) + { + // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. + return SLANG_E_NOT_AVAILABLE; + } + + auto fileSystem = _getFileSystem(); + return fileSystem->loadFile(m_path.getBuffer(), blob); +} + +bool FileArtifactRepresentation::exists() +{ + // TODO(JS): + // If it's a name only it's hard to know what exists should do. It can't *check* because it relies on the 'system' doing + // the actual location. We could ask the IArtifactUtil, and that could change the behavior. + // For now we just assume it does. + if (m_kind == Kind::NameOnly) + { + return true; + } + + auto fileSystem = _getFileSystem(); + + SlangPathType pathType; + const auto res = fileSystem->getPathType(m_path.getBuffer(), &pathType); + + // It exists if it is a file + return SLANG_SUCCEEDED(res) && pathType == SLANG_PATH_TYPE_FILE; +} + +FileArtifactRepresentation::~FileArtifactRepresentation() +{ + if (m_kind == Kind::Owned) + { + auto fileSystem = _getFileSystem(); + fileSystem->remove(m_path.getBuffer()); + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LockFile !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* LockFile::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == ILockFile::getTypeGuid()) + { + return static_cast<ILockFile*>(this); + } + return nullptr; +} + +void* LockFile::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +ISlangMutableFileSystem* LockFile::_getFileSystem() +{ + return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton(); +} + +void* LockFile::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +const char* LockFile::getPath() +{ + return (m_path.getLength() > 0) ? m_path.getBuffer() : nullptr; +} + +ISlangMutableFileSystem* LockFile::getFileSystem() +{ + return m_fileSystem; +} + +LockFile::~LockFile() +{ + if (m_path.getLength() > 0) + { + auto fileSystem = _getFileSystem(); + fileSystem->remove(m_path.getBuffer()); + } +} + +void LockFile::disown() +{ + m_path = String(); + m_fileSystem.setNull(); +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactList !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* ArtifactList::getInterface(const Guid& guid) @@ -358,35 +495,15 @@ void* Artifact::getInterface(const Guid& uuid) return nullptr; } -Artifact::~Artifact() -{ - // Remove the temporary - if (m_pathType == PathType::Temporary) - { - File::remove(m_path); - } - // If there is a temporary lock path, remove that - if (m_temporaryLockPath.getLength()) - { - File::remove(m_temporaryLockPath); - } -} - bool Artifact::exists() { - // If we have a blob it exists - if (m_blob) - { - return true; - } - for (ISlangUnknown* item : m_items) { ComPtr<ICastable> castable; if (SLANG_SUCCEEDED(item->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) { - auto rep = (IArtifactRepresentation*)castable->castAs(IArtifactRepresentation::getTypeGuid()); + auto rep = as<IArtifactRepresentation>(castable); if (rep) { // It is a rep and it exists @@ -397,7 +514,7 @@ bool Artifact::exists() continue; } // Associated types don't encapsulate an artifact representation, so don't signal existance - if (castable->castAs(IArtifactAssociated::getTypeGuid())) + if (as<IArtifactAssociated>(castable)) { continue; } @@ -407,17 +524,9 @@ bool Artifact::exists() return true; } - // If we don't have a path then it can't exist - if (m_pathType == PathType::None) - { - return false; - } - - // If the file exists we assume it exists - return File::exists(m_path); + return false; } - void Artifact::addItem(ISlangUnknown* intf) { SLANG_ASSERT(intf); @@ -432,7 +541,6 @@ void Artifact::removeItemAt(Index i) m_items.removeAt(i); } - void* Artifact::findItemInterface(const Guid& guid) { for (ISlangUnknown* intf : m_items) @@ -471,157 +579,48 @@ void* Artifact::findItemObject(const Guid& classGuid) return nullptr; } -SlangResult Artifact::requireFileLike(Keep keep) +SlangResult Artifact::requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) { - // If there is no path set and no blob we still need a name. - // If the artifact is a library we can assume it's a system level library, - // or it can be found by appropriate search paths. - if (m_pathType == PathType::None && - m_blob == nullptr && - (m_desc.kind == ArtifactKind::Library || - m_desc.kind == ArtifactKind::SharedLibrary)) - { - if (m_name.getLength() > 0) - { - return SLANG_OK; - } - - // TODO(JS): If we could serialize, we could turn some other representation into a file, and therefore - // a name, but currently that's not supported - return SLANG_E_NOT_FOUND; - } - - // Will turn into a file if necessary - SLANG_RETURN_ON_FAIL(requireFile(keep)); - return SLANG_OK; + auto util = ArtifactUtilImpl::getSingleton(); + return util->requireFileDefaultImpl(this, keep, outFileRep); } -SlangResult Artifact::requireFile(Keep keep) +SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) { - if (m_pathType != PathType::None) + // If we have a blob just return it + if (auto blob = findItem<ISlangBlob>(this)) { + blob->addRef(); + *outBlob = blob; return SLANG_OK; } ComPtr<ISlangBlob> blob; - // Get the contents as a blob. If we can't do that, then we can't write anything... - SLANG_RETURN_ON_FAIL(loadBlob(getIntermediateKeep(keep), blob.writeRef())); - - // If we have a name, make the generated name based on that name - // Else just use 'slang-generated' the basis - - UnownedStringSlice nameBase; - if (m_name.getLength() > 0) - { - nameBase = m_name.getUnownedSlice(); - } - else - { - nameBase = UnownedStringSlice::fromLiteral("slang-generated"); - } - - // TODO(JS): NOTE! This isn't strictly correct, as the generated filename is not guarenteed to be unique - // if we change it with an extension (or prefix). - // This doesn't change the previous behavior though. - String temporaryLockPath; - SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, temporaryLockPath)); - - String path = temporaryLockPath; - - if (ArtifactInfoUtil::isCpuBinary(m_desc) && - (m_desc.kind == ArtifactKind::SharedLibrary || - m_desc.kind == ArtifactKind::Library)) + // Look for a representation that we can serialize into a blob + for (ISlangUnknown* intf : m_items) { - const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; - if (isSharedLibraryPrefixPlatform) + ComPtr<IArtifactRepresentation> rep; + if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep) { - StringBuilder buf; - buf << "lib"; - buf << Path::getFileName(path); - - auto parentDir = Path::getParentDirectory(path); - if (parentDir.getLength()) - { - // Combine the name with path if their is a parent - path = Path::combine(parentDir, buf); - } - else + SlangResult res = rep->writeToBlob(blob.writeRef()); + if (SLANG_SUCCEEDED(res) && blob) { - // Just use the name as is - path = buf; + break; } } } - - // If there is an extension append it - const UnownedStringSlice ext = ArtifactInfoUtil::getDefaultExtension(m_desc); - - if (ext.getLength()) + + // Wasn't able to construct + if (!blob) { - path.appendChar('.'); - path.append(ext); + return SLANG_E_NOT_FOUND; } - // If the final path is different from the lock path save that path - if (path != temporaryLockPath) + // Put in cache + if (canKeep(keep)) { - m_temporaryLockPath = temporaryLockPath; - } - - // Write the contents - SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); - - // Okay we can now add this as temporary path too - _setPath(PathType::Temporary, path); - - return SLANG_OK; -} - -SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) -{ - ComPtr<ISlangBlob> blob(m_blob); - - if (!blob) - { - if (m_pathType != PathType::None) - { - // Read into a blob - ScopedAllocation alloc; - SLANG_RETURN_ON_FAIL(File::readAllBytes(m_path, alloc)); - - // Create as a blob - blob = RawBlob::moveCreate(alloc); - } - else - { - // Look for a representation that we can serialize into a blob - for (ISlangUnknown* intf : m_items) - { - - ComPtr<IArtifactRepresentation> rep; - if (SLANG_SUCCEEDED(intf->queryInterface(IArtifactRepresentation::getTypeGuid(), (void**)rep.writeRef())) && rep) - { - SlangResult res = rep->writeToBlob(blob.writeRef()); - if (SLANG_SUCCEEDED(res) && blob) - { - break; - } - } - } - } - - // Wasn't able to construct - if (!blob) - { - return SLANG_E_NOT_FOUND; - } - - // Put in cache - if (canKeep(keep)) - { - setBlob(blob); - } + addItem(blob); } *outBlob = blob.detach(); diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index c63ec3b67..88993773d 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -266,6 +266,45 @@ class IArtifactRepresentation : public ICastable virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; }; +/* A lock file */ +class ILockFile : public ICastable +{ + SLANG_COM_INTERFACE(0x9177ea36, 0xa608, 0x4490, { 0x87, 0xf0, 0xf3, 0x93, 0x9, 0x7d, 0x36, 0xce }) + + /// The path to a lock file. + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; + /// Optional, the file system it's on. If nullptr its on 'regular' OS file system. + virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0; + + /// Makes the lock file no longer owned. Doing so will make the path nullptr, and getFileSystem nullptr. + virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0; +}; + +/* +A representation as a file. If it is a temporary file, it will likely disappear. +A file representation does not have to be a representation of a file on the file system. +That is indicated by getFileSystem returning nullptr. Then the path is the path on the *actual* OS file system. +This distinction is important as it is sometimes necessary to have an artifact stored on the OS file system +to be usable. */ +struct IFileArtifactRepresentation : public IArtifactRepresentation +{ + enum class Kind + { + Reference, ///< References a file on the file system + Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope + NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob. + }; + + /// The the kind of file. + virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0; + /// The path (on the file system) + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; + /// Get the lock file. Return nullptr if there is no lock file. + virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() = 0; + /// Optional, the file system it's on. If nullptr its on 'regular' OS file system. + virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0; +}; + /* Interface for types that are associated with an artifact, but aren't a representation, or are only part of a representation. */ class IArtifactAssociated : public ICastable @@ -338,28 +377,7 @@ 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) = 0; - - /// Require artifact is available in file-like scenarion. - /// - /// This is similar to requireFile, but for some special cases doesn't actually require a - /// *explicit* path/file. - /// - /// For example when system libraries are specified - the library paths may be known to - /// a downstream compiler (or the path is passed in explicitly), in that case only the - /// artifact name needs to be correct. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileLike(Keep keep) = 0; - - /// Add items - virtual SLANG_NO_THROW void SLANG_MCALL setPath(PathType pathType, const char* filePath) = 0; - - /// Set the blob representing the contents of the asset - virtual SLANG_NO_THROW void SLANG_MCALL setBlob(ISlangBlob* blob) = 0; - - /// Get the path type - virtual SLANG_NO_THROW PathType SLANG_MCALL getPathType() = 0; - /// Get the path - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) = 0; /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; @@ -402,10 +420,10 @@ class IArtifactList : public ICastable virtual SLANG_NO_THROW void SLANG_MCALL clear() = 0; }; -class ArtifactList : public ComObject, public IArtifactList +class ArtifactList : public ComBaseObject, public IArtifactList { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL + SLANG_COM_BASE_IUNKNOWN_ALL // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; @@ -462,11 +480,11 @@ that handles this detail, such that we search for that first. That interface is */ /* Implementation of the IArtifact interface */ -class Artifact : public ComObject, public IArtifact +class Artifact : public ComBaseObject, public IArtifact { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL + SLANG_COM_BASE_IUNKNOWN_ALL /// IArtifact impl virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } @@ -474,12 +492,7 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL setParent(IArtifact* parent) SLANG_OVERRIDE { m_parent = parent; } virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFileLike(Keep keep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void SLANG_MCALL setPath(PathType pathType, const char* path) SLANG_OVERRIDE { _setPath(pathType, path); } - virtual SLANG_NO_THROW void SLANG_MCALL setBlob(ISlangBlob* blob) SLANG_OVERRIDE { m_blob = blob; } - virtual SLANG_NO_THROW PathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return m_pathType; } - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } virtual SLANG_NO_THROW void* SLANG_MCALL findItemInterface(const Guid& uuid) SLANG_OVERRIDE; virtual SLANG_NO_THROW void* SLANG_MCALL findItemObject(const Guid& classGuid) SLANG_OVERRIDE; @@ -494,28 +507,119 @@ public: m_name(name), m_parent(nullptr) {} - /// Dtor - ~Artifact(); protected: void* getInterface(const Guid& uuid); - void _setPath(PathType pathType, const String& path) { m_pathType = pathType; m_path = path; } - Desc m_desc; ///< Description of the artifact IArtifact* m_parent; ///< Artifact this artifact belongs to String m_name; ///< Name of this artifact - PathType m_pathType = PathType::None; ///< What the path indicates - String m_path; ///< The path - String m_temporaryLockPath; ///< The temporary lock path + List<ComPtr<ISlangUnknown>> m_items; ///< Associated items +}; - ComPtr<ISlangBlob> m_blob; ///< Blob to store result in memory +/* An implementation of ILockFile */ +class LockFile : public ComBaseObject, public ILockFile +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL - List<ComPtr<ISlangUnknown>> m_items; ///< Associated items + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // ILockFile + SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE; + SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE; + SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE; + + /// Ctor + LockFile(String path, ISlangMutableFileSystem* fileSystem): + m_path(path), + m_fileSystem(fileSystem) + { + } + + ~LockFile(); + +protected: + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + ISlangMutableFileSystem* _getFileSystem(); + + String m_path; + ComPtr<ISlangMutableFileSystem> m_fileSystem; }; +/* +A representation of an artifact that is held in a file */ +class FileArtifactRepresentation : public ComBaseObject, public IFileArtifactRepresentation +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactRepresentation + SLANG_NO_THROW SlangResult SLANG_MCALL writeToBlob(ISlangBlob** blob) SLANG_OVERRIDE; + SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; + + // IFileArtifactRepresentation + virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } + virtual SLANG_NO_THROW ILockFile* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; } + virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; } + + FileArtifactRepresentation(IFileArtifactRepresentation::Kind kind, String path, ILockFile* lockFile, ISlangMutableFileSystem* fileSystem): + m_kind(kind), + m_path(path), + m_lockFile(lockFile), + m_fileSystem(fileSystem) + { + } + + ~FileArtifactRepresentation(); + +protected: + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + ISlangMutableFileSystem* _getFileSystem(); + + IFileArtifactRepresentation::Kind m_kind; + String m_path; + ComPtr<ILockFile> m_lockFile; + ComPtr<ISlangMutableFileSystem> m_fileSystem; +}; + +// Helper template to make finding an item more simple +// There isn't a problem if we only have a forward declaration, because in that case T::getTypeGuid can't work. +SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const ISlangUnknown* intf) +{ + SLANG_UNUSED(intf); + return artifact->findItemInterface(guid); +} + +SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const ICastable* castable) +{ + SLANG_UNUSED(castable); + return artifact->findItemObject(guid); +} + +SLANG_FORCE_INLINE void* _findItemImpl(IArtifact* artifact, const Guid& guid, const void* other) +{ + SLANG_UNUSED(other); + return artifact->findItemObject(guid); +} + +template <typename T> +SLANG_FORCE_INLINE T* findItem(IArtifact* artifact) +{ + return (T*)_findItemImpl(artifact, T::getTypeGuid(), (T*)nullptr); +} + } // namespace Slang #endif diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index ca1d8e8e3..bbf9eaf26 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -637,11 +637,13 @@ static SlangResult _parseGCCFamilyLine(const UnownedStringSlice& line, LineParse // If it's a library for CPU types, try and use it if (ArtifactInfoUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library) { + ComPtr<IFileArtifactRepresentation> fileRep; + // Get the name and path (can be empty) to the library - SLANG_RETURN_ON_FAIL(artifact->requireFileLike(ArtifactKeep::No)); + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef())); - libPathPool.add(ArtifactInfoUtil::getParentPath(artifact)); - cmdLine.addPrefixPathArg("-l", ArtifactInfoUtil::getBaseName(artifact)); + libPathPool.add(ArtifactInfoUtil::getParentPath(fileRep)); + cmdLine.addPrefixPathArg("-l", ArtifactInfoUtil::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 d0f748c76..a2e9c78d1 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -267,11 +267,12 @@ namespace Slang if (ArtifactInfoUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library) { // Get the libray name and path - SLANG_RETURN_ON_FAIL(artifact->requireFileLike(ArtifactKeep::No)); + ComPtr<IFileArtifactRepresentation> fileRep; + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, fileRep.writeRef())); - libPathPool.add(ArtifactInfoUtil::getParentPath(artifact)); + libPathPool.add(ArtifactInfoUtil::getParentPath(fileRep)); // We need the extension for windows - cmdLine.addArg(ArtifactInfoUtil::getBaseName(artifact) + ".lib"); + cmdLine.addArg(ArtifactInfoUtil::getBaseName(artifact->getDesc(), fileRep) + ".lib"); } } |
