summaryrefslogtreecommitdiffstats
path: root/source/compiler-core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-08-09 10:31:22 -0400
committerGitHub <noreply@github.com>2022-08-09 10:31:22 -0400
commitc0733be56dc24ef0eb67b26fe0c49d3419e75773 (patch)
treee094e31981c69e887ff9df84df07defe9eb77bf5 /source/compiler-core
parent2db8c15c04f2aade49636e42f0adee636afb3b73 (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.cpp75
-rw-r--r--source/compiler-core/slang-artifact-info.h6
-rw-r--r--source/compiler-core/slang-artifact-util.cpp90
-rw-r--r--source/compiler-core/slang-artifact-util.h15
-rw-r--r--source/compiler-core/slang-artifact.cpp325
-rw-r--r--source/compiler-core/slang-artifact.h186
-rw-r--r--source/compiler-core/slang-gcc-compiler-util.cpp8
-rw-r--r--source/compiler-core/slang-visual-studio-compiler-util.cpp7
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");
}
}