summaryrefslogtreecommitdiffstats
path: root/source/compiler-core/slang-artifact-handler-impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/compiler-core/slang-artifact-handler-impl.cpp')
-rw-r--r--source/compiler-core/slang-artifact-handler-impl.cpp565
1 files changed, 297 insertions, 268 deletions
diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp
index 6fc96dc44..b19a9bd6e 100644
--- a/source/compiler-core/slang-artifact-handler-impl.cpp
+++ b/source/compiler-core/slang-artifact-handler-impl.cpp
@@ -1,340 +1,369 @@
// 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 "slang-artifact-util.h"
-
#include "../core/slang-castable.h"
-
-#include "slang-slice-allocator.h"
-
#include "../core/slang-file-system.h"
#include "../core/slang-io.h"
#include "../core/slang-shared-library.h"
-
-#include "slang-source-map.h"
-
+#include "slang-artifact-desc-util.h"
+#include "slang-artifact-helper.h"
+#include "slang-artifact-impl.h"
+#include "slang-artifact-representation-impl.h"
+#include "slang-artifact-util.h"
#include "slang-json-source-map-util.h"
+#include "slang-slice-allocator.h"
+#include "slang-source-map.h"
-namespace Slang {
+namespace Slang
+{
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton;
+/* static */ DefaultArtifactHandler DefaultArtifactHandler::g_singleton;
SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject)
{
- if ([[maybe_unused]] auto ptr = getInterface(uuid))
- {
+ if ([[maybe_unused]] auto ptr = getInterface(uuid))
+ {
SLANG_ASSERT(ptr == this);
- addRef();
- *outObject = static_cast<IArtifactHandler*>(this);
- return SLANG_OK;
- }
- return SLANG_E_NO_INTERFACE;
+ 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);
+ 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;
+ 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;
+ SLANG_UNUSED(uuid);
+ return nullptr;
}
-SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable)
+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(SLANG_IID_PPV_ARGS(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);
+ SLANG_ASSERT(rep);
+
+ // See if it implements ICastable
+ {
+ ComPtr<ICastable> castable;
+ if (SLANG_SUCCEEDED(rep->queryInterface(SLANG_IID_PPV_ARGS(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)
+SlangResult DefaultArtifactHandler::_addRepresentation(
+ IArtifact* artifact,
+ ArtifactKeep keep,
+ ICastable* castable,
+ ICastable** outCastable)
{
- SLANG_ASSERT(castable);
+ SLANG_ASSERT(castable);
- if (canKeep(keep))
- {
- artifact->addRepresentation(castable);
- }
+ if (canKeep(keep))
+ {
+ artifact->addRepresentation(castable);
+ }
- castable->addRef();
- *outCastable = castable;
- return SLANG_OK;
+ castable->addRef();
+ *outCastable = castable;
+ return SLANG_OK;
}
SlangResult DefaultArtifactHandler::expandChildren(IArtifact* container)
{
- // First check if it has already been expanded
- 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();
+ // First check if it has already been expanded
+ 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)
{
// If it's just a generic container, we can assume it's expanded, and be done
return SLANG_OK;
}
- if (isDerivedFrom(desc.kind, ArtifactKind::Container))
- {
+ if (isDerivedFrom(desc.kind, ArtifactKind::Container))
+ {
// TODO(JS):
// Proper implementation should (for example) be able to expand a Zip file etc.
// For now we just set that there are no children, and be done
- container->setChildren(nullptr, 0);
- return SLANG_E_NOT_IMPLEMENTED;
- }
+ container->setChildren(nullptr, 0);
+ return SLANG_E_NOT_IMPLEMENTED;
+ }
// We can't expand non container like types, so we just make sure it's empty
container->setChildren(nullptr, 0);
- return SLANG_OK;
+ return SLANG_OK;
}
-static SlangResult _loadSourceMap(IArtifact* artifact, ArtifactKeep intermediateKeep, SourceMap& outSourceMap)
+static SlangResult _loadSourceMap(
+ IArtifact* artifact,
+ ArtifactKeep intermediateKeep,
+ SourceMap& outSourceMap)
{
- const auto desc = artifact->getDesc();
- if (isDerivedFrom(desc.kind, ArtifactKind::Json) &&
- isDerivedFrom(desc.payload, ArtifactPayload::SourceMap))
- {
- ComPtr<ISlangBlob> blob;
- SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef()));
-
- SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap));
- return SLANG_OK;
- }
-
- return SLANG_FAIL;
+ const auto desc = artifact->getDesc();
+ if (isDerivedFrom(desc.kind, ArtifactKind::Json) &&
+ isDerivedFrom(desc.payload, ArtifactPayload::SourceMap))
+ {
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef()));
+
+ SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap));
+ return SLANG_OK;
+ }
+
+ return SLANG_FAIL;
}
-SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable)
+SlangResult DefaultArtifactHandler::getOrCreateRepresentation(
+ IArtifact* artifact,
+ const Guid& guid,
+ ArtifactKeep keep,
+ ICastable** outCastable)
{
- const auto reps = artifact->getRepresentations();
-
- // See if we already have a rep of this type
- for (ICastable* rep : reps)
- {
- if (rep->castAs(guid))
- {
- rep->addRef();
- *outCastable = rep;
- return SLANG_OK;
- }
- }
-
- // We can ask each representation if they can do the conversion to the type, if they can we just use that
- for (ICastable* castable : reps)
- {
- if (auto rep = as<IArtifactRepresentation>(castable))
- {
- ComPtr<ICastable> created;
- if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef())))
- {
- SLANG_ASSERT(created);
- // Add the rep
- return _addRepresentation(artifact, keep, created, outCastable);
- }
- }
- }
-
- // Special cases
- if (guid == SourceMap::getTypeGuid())
- {
- // Blob -> SourceMap
- ComPtr<IBoxValue<SourceMap>> sourceMap(new BoxValue<SourceMap>);
- SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get()));
- return _addRepresentation(artifact, keep, sourceMap, outCastable);
- }
- else if (guid == ISlangSharedLibrary::getTypeGuid())
- {
- ComPtr<ISlangSharedLibrary> sharedLib;
- SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef()));
- return _addRepresentation(artifact, keep, sharedLib, outCastable);
- }
- else if (guid == IOSFileArtifactRepresentation::getTypeGuid())
- {
- ComPtr<IOSFileArtifactRepresentation> fileRep;
- SLANG_RETURN_ON_FAIL(_createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef()));
- return _addRepresentation(artifact, keep, fileRep, outCastable);
- }
-
- // Handle known conversion to blobs
- if (guid == ISlangBlob::getTypeGuid())
- {
- if (auto sourceMap = findRepresentation<SourceMap>(artifact))
- {
- // SourceMap -> Blob
- ComPtr<ISlangBlob> blob;
- SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob));
- // Add the rep
- return _addRepresentation(artifact, keep, blob, outCastable);
- }
- }
-
- return SLANG_E_NOT_AVAILABLE;
+ const auto reps = artifact->getRepresentations();
+
+ // See if we already have a rep of this type
+ for (ICastable* rep : reps)
+ {
+ if (rep->castAs(guid))
+ {
+ rep->addRef();
+ *outCastable = rep;
+ return SLANG_OK;
+ }
+ }
+
+ // We can ask each representation if they can do the conversion to the type, if they can we just
+ // use that
+ for (ICastable* castable : reps)
+ {
+ if (auto rep = as<IArtifactRepresentation>(castable))
+ {
+ ComPtr<ICastable> created;
+ if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef())))
+ {
+ SLANG_ASSERT(created);
+ // Add the rep
+ return _addRepresentation(artifact, keep, created, outCastable);
+ }
+ }
+ }
+
+ // Special cases
+ if (guid == SourceMap::getTypeGuid())
+ {
+ // Blob -> SourceMap
+ ComPtr<IBoxValue<SourceMap>> sourceMap(new BoxValue<SourceMap>);
+ SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get()));
+ return _addRepresentation(artifact, keep, sourceMap, outCastable);
+ }
+ else if (guid == ISlangSharedLibrary::getTypeGuid())
+ {
+ ComPtr<ISlangSharedLibrary> sharedLib;
+ SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef()));
+ return _addRepresentation(artifact, keep, sharedLib, outCastable);
+ }
+ else if (guid == IOSFileArtifactRepresentation::getTypeGuid())
+ {
+ ComPtr<IOSFileArtifactRepresentation> fileRep;
+ SLANG_RETURN_ON_FAIL(
+ _createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef()));
+ return _addRepresentation(artifact, keep, fileRep, outCastable);
+ }
+
+ // Handle known conversion to blobs
+ if (guid == ISlangBlob::getTypeGuid())
+ {
+ if (auto sourceMap = findRepresentation<SourceMap>(artifact))
+ {
+ // SourceMap -> Blob
+ ComPtr<ISlangBlob> blob;
+ SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob));
+ // Add the rep
+ return _addRepresentation(artifact, keep, blob, outCastable);
+ }
+ }
+
+ return SLANG_E_NOT_AVAILABLE;
}
-SlangResult DefaultArtifactHandler::_createOSFile(IArtifact* artifact, ArtifactKeep keep, IOSFileArtifactRepresentation** outFileRep)
+SlangResult DefaultArtifactHandler::_createOSFile(
+ IArtifact* artifact,
+ ArtifactKeep keep,
+ IOSFileArtifactRepresentation** outFileRep)
{
- // Look if we have an IExtFile representation, as we might already have a OS file associated with that
- if (auto extRep = findRepresentation<IExtFileArtifactRepresentation>(artifact))
- {
- auto system = extRep->getFileSystem();
-
- String path;
- switch (system->getOSPathKind())
- {
- case OSPathKind::Direct:
- {
- path = UnownedStringSlice(extRep->getPath());
- break;
- }
- case OSPathKind::OperatingSystem:
- {
- ComPtr<ISlangBlob> osPathBlob;
- if (SLANG_SUCCEEDED(system->getPath(PathKind::OperatingSystem, extRep->getPath(), osPathBlob.writeRef())))
- {
- path = StringUtil::getString(osPathBlob);
- }
- break;
- }
- default: break;
- }
-
- if (path.getLength())
- {
- auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice() , nullptr);
- // As a sanity check make sure it exists!
- if (fileRep->exists())
- {
- *outFileRep = fileRep.detach();
- return SLANG_OK;
- }
- }
- }
-
- // Okay looks like we will need to generate a temporary file
- 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()));
-
- // Find some name associated
- auto name = ArtifactUtil::findName(artifact);
- if (name.getLength() == 0)
- {
- name = toSlice("unknown");
- }
-
- // Okay we need to store as a temporary. Get a lock file.
- ComPtr<IOSFileArtifactRepresentation> lockFile;
- SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef()));
-
- // Now we need the appropriate name for this item
- ComPtr<ISlangBlob> pathBlob;
- SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef()));
-
- const auto path = StringUtil::getSlice(pathBlob);
-
- // Write the contents
- SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize()));
- if(artifact->getDesc().kind == ArtifactKind::Executable)
+ // Look if we have an IExtFile representation, as we might already have a OS file associated
+ // with that
+ if (auto extRep = findRepresentation<IExtFileArtifactRepresentation>(artifact))
+ {
+ auto system = extRep->getFileSystem();
+
+ String path;
+ switch (system->getOSPathKind())
+ {
+ case OSPathKind::Direct:
+ {
+ path = UnownedStringSlice(extRep->getPath());
+ break;
+ }
+ case OSPathKind::OperatingSystem:
+ {
+ ComPtr<ISlangBlob> osPathBlob;
+ if (SLANG_SUCCEEDED(system->getPath(
+ PathKind::OperatingSystem,
+ extRep->getPath(),
+ osPathBlob.writeRef())))
+ {
+ path = StringUtil::getString(osPathBlob);
+ }
+ break;
+ }
+ default: break;
+ }
+
+ if (path.getLength())
+ {
+ auto fileRep = OSFileArtifactRepresentation::create(
+ IOSFileArtifactRepresentation::Kind::Reference,
+ path.getUnownedSlice(),
+ nullptr);
+ // As a sanity check make sure it exists!
+ if (fileRep->exists())
+ {
+ *outFileRep = fileRep.detach();
+ return SLANG_OK;
+ }
+ }
+ }
+
+ // Okay looks like we will need to generate a temporary file
+ 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()));
+
+ // Find some name associated
+ auto name = ArtifactUtil::findName(artifact);
+ if (name.getLength() == 0)
+ {
+ name = toSlice("unknown");
+ }
+
+ // Okay we need to store as a temporary. Get a lock file.
+ ComPtr<IOSFileArtifactRepresentation> lockFile;
+ SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef()));
+
+ // Now we need the appropriate name for this item
+ ComPtr<ISlangBlob> pathBlob;
+ SLANG_RETURN_ON_FAIL(
+ helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef()));
+
+ const auto path = StringUtil::getSlice(pathBlob);
+
+ // Write the contents
+ SLANG_RETURN_ON_FAIL(
+ File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize()));
+ if (artifact->getDesc().kind == ArtifactKind::Executable)
{
SLANG_RETURN_ON_FAIL(File::makeExecutable(path));
}
- ComPtr<IOSFileArtifactRepresentation> 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)
- {
- fileRep.swap(lockFile);
- }
- else
- {
- // Create a new rep that references the lock file
- fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Owned, path, lockFile);
- }
-
- // Return the file
- *outFileRep = fileRep.detach();
- return SLANG_OK;
+ ComPtr<IOSFileArtifactRepresentation> 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)
+ {
+ fileRep.swap(lockFile);
+ }
+ else
+ {
+ // Create a new rep that references the lock file
+ fileRep = new OSFileArtifactRepresentation(
+ IOSFileArtifactRepresentation::Kind::Owned,
+ path,
+ lockFile);
+ }
+
+ // Return the file
+ *outFileRep = fileRep.detach();
+ return SLANG_OK;
}
-SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary)
+SlangResult DefaultArtifactHandler::_loadSharedLibrary(
+ IArtifact* artifact,
+ 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<IOSFileArtifactRepresentation> fileRep;
-
- // We want to keep the file representation, otherwise every request, could produce a new file
- // and that seems like a bad idea.
- SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef()));
-
- // Try loading the shared library
- SharedLibrary::Handle handle;
- if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle)))
- {
- return SLANG_FAIL;
- }
-
- // Output
- *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach();
- return SLANG_OK;
- }
-
- return SLANG_FAIL;
+ // 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<IOSFileArtifactRepresentation> fileRep;
+
+ // We want to keep the file representation, otherwise every request, could produce a new
+ // file and that seems like a bad idea.
+ SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef()));
+
+ // Try loading the shared library
+ SharedLibrary::Handle handle;
+ if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle)))
+ {
+ return SLANG_FAIL;
+ }
+
+ // Output
+ *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach();
+ return SLANG_OK;
+ }
+
+ return SLANG_FAIL;
}
} // namespace Slang