diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-08-16 03:39:41 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-16 00:39:41 -0700 |
| commit | ac71724c03392b429e44641a3641b2bcf7cc55fc (patch) | |
| tree | 8f7ffa61329dd24bc9be551e293840b6b94aab36 /source/compiler-core/slang-artifact-handler-impl.cpp | |
| parent | 786f48d32340c36a06865a333ff9066033b5b2bc (diff) | |
Remove CompileResult to use IArtifact (#2357)
* #include an absolute path didn't work - because paths were taken to always be relative.
* WIP with hierarchical enums.
* Some small fixes and improvements around artifact desc related types.
* Improvements around hierarchical enum.
* Fixes to get Artifact types refactor to be able to execute tests.
* Attempt to better categorize PTX.
* Work around for potentially unused function warning.
* Typo fix.
* Simplify Artifact header.
* Small improvements around Artifact kind/payload/style.
* Added IDestroyable/ICastable
* Add IArtifactList.
* First impl of IArtifactUtil.
* Use the ICastable interface for IArtifactRepresentation.
* Added IArtifactRepresentation & IArtifactAssociated.
* Add SLANG_OVERRIDE to avoid gcc/clang warning.
* Fix calling convention issue on win32.
* Fix missing SLANG_OVERRIDE.
* First attempt at file abstraction around Artifact.
* Added creation of lock file.
* Move functionality for determining file paths to the IArtifactUtil.
Add casting to ICastable.
* Added some casting/finding mechanisms.
* Simplify IArtifact interface, and use Items for file reps.
* Fix problem with libraries on DXIL.
* Split out ArtifactRepresentation.
* Move ArtifactDesc functionality to ArtifactDescUtil. ArtifactInfoUtil becomes ArtifactDescUtil.
* Split implementations from the interfaces for Artifact.
* Use TypeTextUtil for target name outputting.
* Add artifact impls.
* Add ICastableList
* Added UnknownCastableAdapter
* Make ISlangSharedLibrary derive from ICastable, and remain backwards compatible with slang-llvm.
* Refactor Representation on Artifact.
* Make our ISlangBlobs also derive from ICastable.
Make ISlangBlob atomic ref counted.
* Split out CastableList and related types, and placed in core.
* Small fixes around IArtifact.
Improve IArtifact docs.
First impl of getChildren for IArtifact.
* Documentation improvements for Artifact related types.
* Fix typo.
* Special case adding a ICastableList to a LazyCastableList.
* Small simplification of LazyCastableList, by adding State member.
* Removed the ILockFile interface because IFileArtifactRepresentation can be used.
* Implement DiagnosticsArtifactRepresentation.
* Added PostEmitMetadataArtifactRepresentation
* Add searching by predicate.
Added handling of accessing Artifact as ISharedLibrary
* Fix typo.
* Add find to IArtifacgtList.
Fix some missing SLANG_NO_THROW.
* Small improvements around ArtifactDesc types.
* Another small change around ArtifactKind.
* Some more shuffling of ArtifactDesc.
* Make IArtifact castable
Remove IArtifactList
Made IArtifactContainer derive from IArtifact
Made ModuleLibrary atomic ref counted/given IModuleLibrary interface.
* Must call _requireChildren before any children access.
* Fix missing SLANG_MCALL on castAs.
* Fix missing SLANG_OVERRIDE.
* Added IArtifactHandler
* Use ICastable for basis of scope/lookup.
* WIP first attempt to remove CompileResult.
* Fix support for for downstream compiler shared library adapter.
* Fix issues found when replacing CompileResult.
* Fix typo.
* Fix getting items form 'significant' member of an Artifact.
* Split out ArtifactUtil & ArtifactHandler.
* Work around for problem on Visual studio.
* Improve searching.
* Add missing files.
Diffstat (limited to 'source/compiler-core/slang-artifact-handler-impl.cpp')
| -rw-r--r-- | source/compiler-core/slang-artifact-handler-impl.cpp | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp new file mode 100644 index 000000000..c93a4907b --- /dev/null +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -0,0 +1,380 @@ +// slang-artifact-handler-impl.cpp +#include "slang-artifact-handler-impl.h" + +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" + +#include "slang-artifact-desc-util.h" + +#include "slang-artifact-helper.h" + +#include "../core/slang-castable-list-impl.h" + +#include "../core/slang-file-system.h" +#include "../core/slang-io.h" +#include "../core/slang-shared-library.h" + +// For workaround for DownstreamResult +#include "slang-downstream-compiler.h" + +namespace Slang { + +// A temporary class that adapts `ISlangSharedLibrary_Dep1` to ISlangSharedLibrary + +class SharedLibraryDep1Adapter : public ComBaseObject, public ISlangSharedLibrary +{ +public: + SLANG_COM_BASE_IUNKNOWN_ALL + + // ICastable + virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; + + // ISlangSharedLibrary + virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) SLANG_OVERRIDE { return m_contained->findSymbolAddressByName(name); } + + SharedLibraryDep1Adapter(ISlangSharedLibrary_Dep1* dep1) : + m_contained(dep1) + { + } + +protected: + void* getInterface(const Guid& guid) + { + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == ISlangSharedLibrary::getTypeGuid()) + { + return static_cast<ISlangSharedLibrary*>(this); + } + return nullptr; + } + void* getObject(const Guid& guid) + { + SLANG_UNUSED(guid); + return nullptr; + } + + ComPtr<ISlangSharedLibrary_Dep1> m_contained; +}; + +void* SharedLibraryDep1Adapter::castAs(const SlangUUID& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +/* Hack to take into account downstream compilers shared library interface might need an adapter */ +static SlangResult _getDownstreamSharedLibrary(DownstreamCompileResult* downstreamResult, ComPtr<ISlangSharedLibrary>& outSharedLibrary) +{ + ComPtr<ISlangSharedLibrary> lib; + SLANG_RETURN_ON_FAIL(downstreamResult->getHostCallableSharedLibrary(lib)); + + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary::getTypeGuid(), (void**)outSharedLibrary.writeRef()))) + { + return SLANG_OK; + } + + ComPtr<ISlangSharedLibrary_Dep1> libDep1; + if (SLANG_SUCCEEDED(lib->queryInterface(ISlangSharedLibrary_Dep1::getTypeGuid(), (void**)libDep1.writeRef()))) + { + // Okay, we need to adapt for now + outSharedLibrary = new SharedLibraryDep1Adapter(libDep1); + return SLANG_OK; + } + return SLANG_E_NOT_FOUND; +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; + +SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) +{ + if (auto ptr = getInterface(uuid)) + { + addRef(); + *outObject = static_cast<IArtifactHandler*>(this); + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; +} + +void* DefaultArtifactHandler::castAs(const Guid& guid) +{ + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); +} + +void* DefaultArtifactHandler::getInterface(const Guid& uuid) +{ + if (uuid == ISlangUnknown::getTypeGuid() || + uuid == ICastable::getTypeGuid() || + uuid == IArtifactHandler::getTypeGuid()) + { + return static_cast<IArtifactHandler*>(this); + } + + return nullptr; +} + +void* DefaultArtifactHandler::getObject(const Guid& uuid) +{ + SLANG_UNUSED(uuid); + return nullptr; +} + +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) +{ + SLANG_ASSERT(rep); + + // See if it implements ICastable + { + ComPtr<ICastable> castable; + if (SLANG_SUCCEEDED(rep->queryInterface(ICastable::getTypeGuid(), (void**)castable.writeRef())) && castable) + { + return _addRepresentation(artifact, keep, castable, outCastable); + } + } + + // We have to wrap + ComPtr<IUnknownCastableAdapter> adapter(new UnknownCastableAdapter(rep)); + return _addRepresentation(artifact, keep, adapter, outCastable); +} + +SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +{ + SLANG_ASSERT(castable); + + if (canKeep(keep)) + { + artifact->addRepresentation(castable); + } + + castable->addRef(); + *outCastable = castable; + return SLANG_OK; +} + +SlangResult DefaultArtifactHandler::expandChildren(IArtifactContainer* container) +{ + SlangResult res = container->getExpandChildrenResult(); + if (res != SLANG_E_UNINITIALIZED) + { + // It's already expanded + return res; + } + + // For the generic container type, we just expand as empty + const auto desc = container->getDesc(); + if (desc.kind == ArtifactKind::Container) + { + container->setChildren(nullptr, 0); + return SLANG_OK; + } + // TODO(JS): + // Proper implementation should (for example) be able to expand a Zip file etc. + return SLANG_E_NOT_IMPLEMENTED; +} + + + +SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) +{ + // See if we already have a rep of this type + { + for (ICastable* rep : artifact->getRepresentations()) + { + if (rep->castAs(guid)) + { + rep->addRef(); + *outCastable = rep; + return SLANG_OK; + } + } + } + + // TODO(JS): Temporary whilst DownstreamCompileResult is + // Special handling for DownstreamCompileResult + if (auto downstreamResult = findRepresentation<DownstreamCompileResult>(artifact)) + { + if (guid == ISlangBlob::getTypeGuid()) + { + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(downstreamResult->getBinary(blob)); + return _addRepresentation(artifact, keep, blob, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr<ISlangSharedLibrary> lib; + SLANG_RETURN_ON_FAIL(_getDownstreamSharedLibrary(downstreamResult, lib)); + return _addRepresentation(artifact, keep, lib, outCastable); + } + } + + // Normal construction + if (guid == ISlangBlob::getTypeGuid()) + { + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(_loadBlob(artifact, keep, blob.writeRef())); + return _addRepresentation(artifact, keep, blob, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr<ISlangSharedLibrary> sharedLib; + SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, keep, sharedLib.writeRef())); + return _addRepresentation(artifact, keep, sharedLib, outCastable); + } + + return SLANG_E_NOT_AVAILABLE; +} + +static bool _isFileSystemFile(ICastable* castable, void* data) +{ + if (auto fileRep = as<IFileArtifactRepresentation>(castable)) + { + ISlangMutableFileSystem* fileSystem = (ISlangMutableFileSystem*)data; + if (fileRep->getFileSystem() == fileSystem) + { + return true; + } + } + return false; +} + +SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) +{ + // See if we already have it + if (auto fileRep = as<IFileArtifactRepresentation>(artifact->findRepresentationWithPredicate(&_isFileSystemFile, fileSystem))) + { + fileRep->addRef(); + *outFileRep = fileRep; + return SLANG_OK; + } + + auto helper = DefaultArtifactHelper::getSingleton(); + + // If we are going to access as a file we need to be able to write it, and to do that we need a blob + ComPtr<ISlangBlob> blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); + + // Okay we need to store as a temporary. Get a lock file. + ComPtr<IFileArtifactRepresentation> lockFile; + SLANG_RETURN_ON_FAIL(helper->createLockFile(artifact->getName(), fileSystem, lockFile.writeRef())); + + // Now we need the appropriate name for this item + ComPtr<ISlangBlob> pathBlob; + SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact->getDesc(), lockFile->getPath(), pathBlob.writeRef())); + + const auto path = StringUtil::getString(pathBlob); + + // Write the contents + SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + + ComPtr<IFileArtifactRepresentation> fileRep; + + // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed + // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path + // might mean the lock file and the rep have the same path. + // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile + + // If the paths are identical, we can just use the lock file for the rep + if (UnownedStringSlice(lockFile->getPath()) == path.getUnownedSlice()) + { + fileRep.swap(lockFile); + } + else + { + // Create a new rep that references the lock file + fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Owned, path, lockFile, lockFile->getFileSystem()); + } + + // Create the rep + if (canKeep(keep)) + { + artifact->addRepresentation(fileRep); + } + + // Return the file + *outFileRep = fileRep.detach(); + return SLANG_OK; +} + +SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) +{ + // If it is 'shared library' for a CPU like thing, we can try and load it + const auto desc = artifact->getDesc(); + if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || + isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + // Get as a file represenation on the OS file system + ComPtr<IFileArtifactRepresentation> fileRep; + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::No, nullptr, fileRep.writeRef())); + + // We requested on the OS file system, just check that's what we got... + SLANG_ASSERT(fileRep->getFileSystem() == nullptr); + + // Try loading the shared library + SharedLibrary::Handle handle; + if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) + { + return SLANG_FAIL; + } + + // The ScopeSharedLibrary will keep the fileRep in scope as long as is needed + auto sharedLibrary = new ScopeSharedLibrary(handle, fileRep); + + if (canKeep(keep)) + { + // We want to keep the fileRep, as that is necessary for the sharedLibrary to even work + artifact->addRepresentation(fileRep); + // Keep the shared library + artifact->addRepresentation(sharedLibrary); + } + + // Output + sharedLibrary->addRef(); + *outSharedLibrary = sharedLibrary; + + return SLANG_OK; + } + + return SLANG_FAIL; +} + +SlangResult DefaultArtifactHandler::_loadBlob(IArtifact* artifact, ArtifactKeep keep, ISlangBlob** outBlob) +{ + SLANG_UNUSED(keep); + + ComPtr<ISlangBlob> blob; + + // Look for a representation that we can serialize into a blob + for (auto rep : artifact->getRepresentations()) + { + if (auto artifactRep = as<IArtifactRepresentation>(rep)) + { + SlangResult res = artifactRep->writeToBlob(blob.writeRef()); + if (SLANG_SUCCEEDED(res) && blob) + { + break; + } + } + } + + // Wasn't able to construct + if (!blob) + { + return SLANG_E_NOT_FOUND; + } + + *outBlob = blob.detach(); + return SLANG_OK; +} + +} // namespace Slang |
