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