From 3c0177134d126956336865623ea3d6861be59cfa Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 1 Sep 2022 10:06:19 -0400 Subject: Make FileSystem files and OS files distinct (#2383) * #include an absolute path didn't work - because paths were taken to always be relative. * Make DownstreamCompileOptions use POD types. * CharSliceAllocator -> SliceAllocator Added SliceConverter CharSliceCaster -> SliceCaster * First attempt at zero terminating around blobs. * Fix clang warning. * Add SlangTerminatedChars Make Blob implementations support it. Make most blobs 'terminated'. * Fix bug setting up sourceFiles for CommandLineDownstreamCompiler. * Traffic in TerminatedCharSlice for sourceFiles. Use ArtifactDesc to generate temporary file names for source. * Fix typo in testing for shared library/C++. * Working with source being passed as artifacts to DownstreamCompiler. * Use artifacts in SourceManager/SourceFile. * Support infering extension from the original file extension. * * Infer extension if can't determine from the artifact type * Split IOSFile/IExtFile representations * Move responsibility for creating OS file to the handler. * Disable the check memory path. --- source/compiler-core/slang-artifact-desc-util.cpp | 29 +++-- source/compiler-core/slang-artifact-desc-util.h | 12 +-- .../compiler-core/slang-artifact-handler-impl.cpp | 87 +++++++++------ source/compiler-core/slang-artifact-handler-impl.h | 6 +- source/compiler-core/slang-artifact-helper.cpp | 38 +++---- source/compiler-core/slang-artifact-helper.h | 20 ++-- source/compiler-core/slang-artifact-impl.cpp | 14 ++- source/compiler-core/slang-artifact-impl.h | 2 +- .../slang-artifact-representation-impl.cpp | 77 +++++++++++-- .../slang-artifact-representation-impl.h | 69 +++++++++--- .../compiler-core/slang-artifact-representation.h | 39 ++++--- source/compiler-core/slang-artifact-util.cpp | 119 +++++---------------- source/compiler-core/slang-artifact-util.h | 22 +--- source/compiler-core/slang-artifact.h | 8 +- source/compiler-core/slang-downstream-compiler.cpp | 32 +++--- source/compiler-core/slang-downstream-compiler.h | 2 +- source/compiler-core/slang-dxc-compiler.cpp | 2 +- source/compiler-core/slang-gcc-compiler-util.cpp | 18 ++-- source/compiler-core/slang-gcc-compiler-util.h | 4 +- source/compiler-core/slang-include-system.cpp | 4 +- source/compiler-core/slang-source-loc.cpp | 76 ++++++------- source/compiler-core/slang-source-loc.h | 5 +- .../slang-visual-studio-compiler-util.cpp | 19 ++-- .../slang-visual-studio-compiler-util.h | 4 +- source/slang/slang-compiler.cpp | 9 +- source/slang/slang-compiler.h | 2 + source/slang/slang-options.cpp | 6 +- source/slang/slang-preprocessor.cpp | 2 +- source/slang/slang.cpp | 43 ++++++-- tools/slang-test/slang-test-main.cpp | 23 +++- 30 files changed, 446 insertions(+), 347 deletions(-) diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 7534e1265..7e274794f 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -704,7 +704,13 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S /* static */String ArtifactDescUtil::getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path) { - String name = Path::getFileName(path); + const String name = Path::getFileName(path); + return getBaseNameFromName(desc, name.getUnownedSlice()); +} + +/* static */String ArtifactDescUtil::getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& inName) +{ + String name(inName); const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; if (isSharedLibraryPrefixPlatform) @@ -723,16 +729,19 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } - // Strip any extension + // Strip any extension { StringBuilder descExt; - - appendDefaultExtension(desc, descExt); - - // Strip the extension if it's a match - if (descExt.getLength() && - Path::getPathExt(name) == descExt) + if (SLANG_SUCCEEDED(appendDefaultExtension(desc, descExt)) && + descExt.getLength()) { + // TODO(JS): + // It has an extension. We could check if they are the same + // but if they are not that might be fine, because of case insensitivity + // or perhaps there are multiple valid extensions. So for now we just strip + // and don't bother confirming with something like.. + // if (Path::getPathExt(name) == descExt)) + name = Path::getFileNameWithoutExt(name); } } @@ -740,9 +749,9 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return name; } -/* static */String ArtifactDescUtil::getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep) +/* static */String ArtifactDescUtil::getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* pathRep) { - UnownedStringSlice path(fileRep->getPath()); + UnownedStringSlice path(pathRep->getPath()); return getBaseNameFromPath(desc, path); } diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h index b700fa465..6aa5c321e 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -68,12 +68,12 @@ struct ArtifactDescUtil /// Given a desc and a path returns the base name (stripped of prefix and extension) static String getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path); - /// Get the base name of this artifact. - /// If there is a path set, will extract the name from that (stripping prefix, extension as necessary). - /// Else if there is an explicit name set, this is returned. - /// Else returns the empty string - - static String getBaseName(const ArtifactDesc& desc, IFileArtifactRepresentation* fileRep); + /// Given a desc and a name returns the base name (stripped of prefix and extension) + static String getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& path); + + /// Get the base name of the fileRep + /// If no base name is found will return an empty slice + static String getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* 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); diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index 94e6fb6f7..d7c3f02b6 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -7,9 +7,12 @@ #include "slang-artifact-desc-util.h" #include "slang-artifact-helper.h" +#include "slang-artifact-util.h" #include "../core/slang-castable-util.h" +#include "slang-slice-allocator.h" + #include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-shared-library.h" @@ -148,42 +151,72 @@ SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifac SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); return _addRepresentation(artifact, keep, sharedLib, outCastable); } + else if (guid == IOSFileArtifactRepresentation::getTypeGuid()) + { + ComPtr fileRep; + SLANG_RETURN_ON_FAIL(_createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); + return _addRepresentation(artifact, keep, fileRep, outCastable); + } return SLANG_E_NOT_AVAILABLE; } -static bool _isFileSystemFile(ICastable* castable, void* data) +SlangResult DefaultArtifactHandler::_createOSFile(IArtifact* artifact, ArtifactKeep keep, IOSFileArtifactRepresentation** outFileRep) { - if (auto fileRep = as(castable)) + // Look if we have an IExtFile representation, as we might already have a OS file associated with that + if (auto extRep = findRepresentation(artifact)) { - ISlangMutableFileSystem* fileSystem = (ISlangMutableFileSystem*)data; - if (fileRep->getFileSystem() == fileSystem) + auto system = extRep->getFileSystem(); + + String path; + switch (system->getOSPathKind()) { - return true; + case OSPathKind::Direct: + { + path = UnownedStringSlice(extRep->getPath()); + break; + } + case OSPathKind::Canonical: + { + ComPtr canonicalPathBlob; + if (SLANG_SUCCEEDED(system->getCanonicalPath(extRep->getPath(), canonicalPathBlob.writeRef()))) + { + path = StringUtil::getString(canonicalPathBlob); + } + break; + } + default: break; } - } - return false; -} -SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) -{ - // See if we already have it - if (auto fileRep = as(artifact->findRepresentationWithPredicate(&_isFileSystemFile, fileSystem))) - { - fileRep->addRef(); - *outFileRep = fileRep; - return SLANG_OK; + 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 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 lockFile; - SLANG_RETURN_ON_FAIL(helper->createLockFile(artifact->getName(), fileSystem, lockFile.writeRef())); + ComPtr lockFile; + SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef())); // Now we need the appropriate name for this item ComPtr pathBlob; @@ -194,7 +227,7 @@ SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* art // Write the contents SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); - ComPtr fileRep; + ComPtr 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 @@ -209,13 +242,7 @@ SlangResult DefaultArtifactHandler::getOrCreateFileRepresentation(IArtifact* art 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); + fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Owned, path, lockFile); } // Return the file @@ -232,14 +259,11 @@ SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ISla isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) { // Get as a file represenation on the OS file system - ComPtr fileRep; + ComPtr 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, nullptr, fileRep.writeRef())); - - // We requested on the OS file system, just check that's what we got... - SLANG_ASSERT(fileRep->getFileSystem() == nullptr); + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); // Try loading the shared library SharedLibrary::Handle handle; @@ -247,6 +271,7 @@ SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ISla { return SLANG_FAIL; } + // Output *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach(); return SLANG_OK; diff --git a/source/compiler-core/slang-artifact-handler-impl.h b/source/compiler-core/slang-artifact-handler-impl.h index 88be93f55..a46005a33 100644 --- a/source/compiler-core/slang-artifact-handler-impl.h +++ b/source/compiler-core/slang-artifact-handler-impl.h @@ -23,13 +23,13 @@ public: // IArtifactHandler SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifactContainer* container) SLANG_OVERRIDE; SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; - SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; - + static IArtifactHandler* getSingleton() { return &g_singleton; } protected: SlangResult _loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary); - + SlangResult _createOSFile(IArtifact* artifact, ArtifactKeep intermediateKeep, IOSFileArtifactRepresentation** outFileRep); + void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp index 27965b0cc..c3b007d28 100644 --- a/source/compiler-core/slang-artifact-helper.cpp +++ b/source/compiler-core/slang-artifact-helper.cpp @@ -87,26 +87,12 @@ ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) { retur UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) { return getName(style); } bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } -SlangResult DefaultArtifactHelper::createLockFile(const char* inNameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) +SlangResult DefaultArtifactHelper::createLockFile(const CharSlice& inNameBase, IOSFileArtifactRepresentation** 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"); - + const UnownedStringSlice nameBase = inNameBase.count ? asStringSlice(inNameBase) : UnownedStringSlice("unknown"); String lockPath; SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); - - ComPtr lockFile(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Lock, lockPath.getUnownedSlice(), nullptr, fileSystem)); - - *outLockFile = lockFile.detach(); + *outLockFile = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Lock, lockPath.getUnownedSlice(), nullptr).detach(); return SLANG_OK; } @@ -151,22 +137,26 @@ SlangResult DefaultArtifactHelper::createCastableList(const Guid& guid, ICastabl return SLANG_E_NO_INTERFACE; } -SlangResult DefaultArtifactHelper::createFileArtifactRepresentation( - IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep) +SlangResult DefaultArtifactHelper::createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) { - *outRep = FileArtifactRepresentation::create(kind, asStringSlice(path), lockFile, fileSystem).detach(); + *outRep = OSFileArtifactRepresentation::create(kind, asStringSlice(path), lockFile).detach(); return SLANG_OK; } +SlangResult DefaultArtifactHelper::createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) +{ + *outRep = ExtFileArtifactRepresentation::create(asStringSlice(path), system).detach(); + return SLANG_OK; +} -SlangResult DefaultArtifactHelper::createFileArtifact(const ArtifactDesc& desc, const CharSlice& path, IArtifact** outArtifact) +SlangResult DefaultArtifactHelper::createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& path, IArtifact** outArtifact) { auto artifact = Artifact::create(desc); - auto fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Reference, asStringSlice(path), nullptr, nullptr); - + auto fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, asStringSlice(path), nullptr); artifact->addRepresentation(fileRep); - + *outArtifact = artifact.detach(); return SLANG_OK; } diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h index 208c80bd5..e14a67d7c 100644 --- a/source/compiler-core/slang-artifact-helper.h +++ b/source/compiler-core/slang-artifact-helper.h @@ -41,7 +41,7 @@ class IArtifactHelper : public ICastable virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; /// Create a lock file, the path of which can be used to generate other temporary files - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const char* nameBase, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outLockFile) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) = 0; /// Given a desc and a basePath returns a suitable name virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; @@ -56,14 +56,16 @@ class IArtifactHelper : public ICastable virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0; /// Create a file rep - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifactRepresentation( - IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) = 0; /// Create an empty ICastableList virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) = 0; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) = 0; }; class DefaultArtifactHelper : public IArtifactHelper @@ -93,7 +95,7 @@ public: 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, IFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; @@ -105,10 +107,12 @@ public: virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCastableList(const Guid& guid, ICastableList** outList) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifactRepresentation( - IFileArtifactRepresentation::Kind kind, const CharSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) SLANG_OVERRIDE; static IArtifactHelper* getSingleton() { return &g_singleton; } diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index 056d89a4b..bec28f3eb 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -77,10 +77,18 @@ bool Artifact::exists() return false; } -SlangResult Artifact::requireFile(Keep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) +SlangResult Artifact::requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) { auto handler = _getHandler(); - return handler->getOrCreateFileRepresentation(this, keep, fileSystem, outFileRep); + + ComPtr castable; + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, IOSFileArtifactRepresentation::getTypeGuid(), keep, castable.writeRef())); + + auto fileRep = as(castable); + fileRep->addRef(); + + *outFileRep = fileRep; + return SLANG_OK; } SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) @@ -90,7 +98,7 @@ SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** ComPtr castable; SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangSharedLibrary::getTypeGuid(), keep, castable.writeRef())); - ISlangSharedLibrary* lib = as(castable); + auto lib = as(castable); lib->addRef(); *outSharedLibrary = lib; diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index 9901b9d63..b59c700d8 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -43,7 +43,7 @@ public: 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, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 4e33f2f0c..9a5c13311 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -13,32 +13,87 @@ namespace Slang { +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExtFileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void* ExtFileArtifactRepresentation::getInterface(const Guid& guid) +{ + if (guid == ISlangUnknown::getTypeGuid() || + guid == ICastable::getTypeGuid() || + guid == IArtifactRepresentation::getTypeGuid() || + guid == IPathArtifactRepresentation::getTypeGuid() || + guid == IExtFileArtifactRepresentation::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; +} + +void* ExtFileArtifactRepresentation::getObject(const Guid& guid) +{ + SLANG_UNUSED(guid); + return nullptr; +} + +void* ExtFileArtifactRepresentation::castAs(const Guid& guid) +{ + if (auto intf = getInterface(guid)) + { + return intf; + } + return getObject(guid); +} + +SlangResult ExtFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +{ + // We can convert into a blob only, and only if we have a path + // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. + if (typeGuid != ISlangBlob::getTypeGuid()) + { + return SLANG_E_NOT_AVAILABLE; + } + + ComPtr blob; + SLANG_RETURN_ON_FAIL(m_fileSystem->loadFile(m_path.getBuffer(), blob.writeRef())); + + *outCastable = CastableUtil::getCastable(blob).detach(); + return SLANG_OK; +} + +bool ExtFileArtifactRepresentation::exists() +{ + SlangPathType pathType; + const auto res = m_fileSystem->getPathType(m_path.getBuffer(), &pathType); + // It exists if it is a file + return SLANG_SUCCEEDED(res) && pathType == getPathType(); +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void* FileArtifactRepresentation::getInterface(const Guid& guid) +void* OSFileArtifactRepresentation::getInterface(const Guid& guid) { if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || - guid == IFileArtifactRepresentation::getTypeGuid()) + guid == IPathArtifactRepresentation::getTypeGuid() || + guid == IOSFileArtifactRepresentation::getTypeGuid()) { - return static_cast(this); + return static_cast(this); } return nullptr; } -void* FileArtifactRepresentation::getObject(const Guid& guid) +void* OSFileArtifactRepresentation::getObject(const Guid& guid) { SLANG_UNUSED(guid); return nullptr; } -ISlangMutableFileSystem* FileArtifactRepresentation::_getFileSystem() +/* static */ISlangMutableFileSystem* OSFileArtifactRepresentation::_getFileSystem() { - return m_fileSystem ? m_fileSystem : OSFileSystem::getMutableSingleton(); + return OSFileSystem::getMutableSingleton(); } -void* FileArtifactRepresentation::castAs(const Guid& guid) +void* OSFileArtifactRepresentation::castAs(const Guid& guid) { if (auto intf = getInterface(guid)) { @@ -47,7 +102,7 @@ void* FileArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult FileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult OSFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) { // We can convert into a blob only, and only if we have a path // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. @@ -66,7 +121,7 @@ SlangResult FileArtifactRepresentation::createRepresentation(const Guid& typeGui return SLANG_OK; } -bool FileArtifactRepresentation::exists() +bool OSFileArtifactRepresentation::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 @@ -86,7 +141,7 @@ bool FileArtifactRepresentation::exists() return SLANG_SUCCEEDED(res) && pathType == SLANG_PATH_TYPE_FILE; } -void FileArtifactRepresentation::disown() +void OSFileArtifactRepresentation::disown() { if (_isOwned()) { @@ -94,7 +149,7 @@ void FileArtifactRepresentation::disown() } } -FileArtifactRepresentation::~FileArtifactRepresentation() +OSFileArtifactRepresentation::~OSFileArtifactRepresentation() { if (_isOwned()) { diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index 4ccd9062c..da21e30bc 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -14,10 +14,10 @@ namespace Slang { /* A representation of an artifact that is held in a file */ -class FileArtifactRepresentation : public ComBaseObject, public IFileArtifactRepresentation +class OSFileArtifactRepresentation : public ComBaseObject, public IOSFileArtifactRepresentation { public: - typedef FileArtifactRepresentation ThisType; + typedef OSFileArtifactRepresentation ThisType; SLANG_COM_BASE_IUNKNOWN_ALL @@ -28,26 +28,27 @@ public: SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) 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; } + // IPathArtifactRepresentation virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } - virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + + // IOSFileArtifactRepresentation + virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; } virtual SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE; - virtual SLANG_NO_THROW IFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; } + virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; } - FileArtifactRepresentation(Kind kind, const UnownedStringSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem): + OSFileArtifactRepresentation(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile): m_kind(kind), m_lockFile(lockFile), - m_path(path), - m_fileSystem(fileSystem) + m_path(path) { } - ~FileArtifactRepresentation(); + ~OSFileArtifactRepresentation(); - static ComPtr create(Kind kind, const UnownedStringSlice& path, IFileArtifactRepresentation* lockFile, ISlangMutableFileSystem* fileSystem) + static ComPtr create(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile) { - return ComPtr(new ThisType(kind, path, lockFile, fileSystem)); + return ComPtr(new ThisType(kind, path, lockFile)); } protected: @@ -57,14 +58,54 @@ protected: /// True if the file is owned bool _isOwned() const { return Index(m_kind) >= Index(Kind::Owned); } - ISlangMutableFileSystem* _getFileSystem(); + static ISlangMutableFileSystem* _getFileSystem(); Kind m_kind; String m_path; - ComPtr m_lockFile; + ComPtr m_lockFile; ComPtr m_fileSystem; }; +class ExtFileArtifactRepresentation : public ComBaseObject, public IExtFileArtifactRepresentation +{ +public: + typedef ExtFileArtifactRepresentation ThisType; + + 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 createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; + + // IPathArtifactRepresentation + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + + // IExtFileArtifactRepresentation + virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; } + + ExtFileArtifactRepresentation(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) : + m_path(path), + m_fileSystem(fileSystem) + { + } + + static ComPtr create(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) + { + return ComPtr(new ThisType(path, fileSystem)); + } + +protected: + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + String m_path; + ComPtr m_fileSystem; +}; + /* This allows wrapping any object to be an artifact representation. NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI bounday remains risky! diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h index 32945b0be..a345d762b 100644 --- a/source/compiler-core/slang-artifact-representation.h +++ b/source/compiler-core/slang-artifact-representation.h @@ -7,23 +7,34 @@ namespace Slang { -/* -A representation as a file. +/* Base interface for types that have a path. */ +class IPathArtifactRepresentation : public IArtifactRepresentation +{ + SLANG_COM_INTERFACE(0xcb1c188c, 0x7e48, 0x43eb, { 0xb0, 0x9a, 0xa1, 0x6e, 0xef, 0xd4, 0x9b, 0xef }); + + /// The path + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; + /// Get type + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() = 0; +}; -A file representation does not have to be a file on the OS file system, and might specify a file -contained in a virtual file system represented by ISlangMutableFileSystem. +/* Represents a path to a file held on an ISlangFileSystem. */ +class IExtFileArtifactRepresentation : public IPathArtifactRepresentation +{ + SLANG_COM_INTERFACE(0xacd65576, 0xb09d, 0x4ac9, { 0xa5, 0x93, 0xeb, 0xf8, 0x9b, 0xd7, 0x11, 0xfd }); -If `getFileSystem()` returns nullptr, then the path does specify a file on the regular OS file system otherwise -the path specifies the file contained in the virtual file system. + /// File system that holds the item along the path. + virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() = 0; +}; -This distinction is important as it is sometimes necessary to have an artifact stored on the OS file system -to be usable. */ -class IFileArtifactRepresentation : public IArtifactRepresentation +/* +A representation as a file on the OS file system. */ +class IOSFileArtifactRepresentation : public IPathArtifactRepresentation { public: SLANG_COM_INTERFACE(0xc7d7d3a4, 0x8683, 0x44b5, { 0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b }); - /* Determines ownership and other characteristics of the 'file' */ + /* Determines ownership and other characteristics of the OS 'file' */ enum class Kind { Reference, ///< References a file on the file system @@ -32,18 +43,14 @@ public: Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for a temporary file. Other files might exists based on the 'lock' path. CountOf, }; - + /// 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; - /// Optional, the file system it's on. If nullptr its on the 'regular' OS file system. - virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getFileSystem() = 0; /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become 'Reference' virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0; /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one. /// If this file is based on a 'lock file', the lock file must stay in scope at least as long as this does. - virtual SLANG_NO_THROW IFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0; + virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index 047e87db0..413bd5efe 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -95,124 +95,55 @@ namespace Slang { return artifact->findArtifactByPredicate(IArtifact::FindStyle::SelfOrChildren, &ArtifactUtil::isSignificant, nullptr); } -/* static */String ArtifactUtil::getBaseName(IArtifact* artifact) -{ - if (auto fileRep = findRepresentation(artifact)) - { - return ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep); - } - // Else use the name - return artifact->getName(); -} - -/* static */String ArtifactUtil::getParentPath(IFileArtifactRepresentation* fileRep) -{ - UnownedStringSlice path(fileRep->getPath()); - return Path::getParentDirectory(path); -} - -/* static */String ArtifactUtil::getParentPath(IArtifact* artifact) -{ - if (auto fileRep = findRepresentation(artifact)) - { - return getParentPath(fileRep); - } - return String(); -} - -/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemTemporaryFile(IArtifact* artifact) -{ - if (auto fileRep = findFileSystemFile(artifact)) - { - return fileRep->getLockFile() ? fileRep : nullptr; - } - return nullptr; -} - -/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemFile(IArtifact* artifact) +UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) { - for (auto rep : artifact->getRepresentations()) + // If a name is set we'll just use that { - if (auto fileSystemRep = as(rep)) + const UnownedStringSlice name(artifact->getName()); + if (name.getLength()) { - if (fileSystemRep->getFileSystem() == nullptr) - { - return fileSystemRep; - } + return name; } } - return nullptr; -} -/* static */IFileArtifactRepresentation* ArtifactUtil::findFileSystemPrimaryFile(IArtifact* artifact) -{ + IPathArtifactRepresentation* bestRep = nullptr; + + // Look for a rep with a path. Prefer IExtFile because a IOSFile might be a temporary file for (auto rep : artifact->getRepresentations()) { - if (auto fileRep = as(rep)) + if (auto pathRep = as(rep)) { - // If it has a file system it's not on OS - // If it has a lock file it can be assumed to be temporary - if (fileRep->getFileSystem() != nullptr || - fileRep->getLockFile()) - { - continue; - } - - // If it's a file that is persistant it will just be a reference to a pre-existing file - const auto kind = fileRep->getKind(); - if (kind != IFileArtifactRepresentation::Kind::Reference) + if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE && + (bestRep == nullptr || as(rep))) { - continue; + bestRep = pathRep; } - - return fileRep; } } - return nullptr; + + const UnownedStringSlice name = bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice(); + return name.getLength() ? name : UnownedStringSlice(); } -UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) +/* static */UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) { - // If a name is set we'll just use that - { - const char* name = artifact->getName(); - if (name && name[0] != 0) - { - return UnownedStringSlice(name); - } - } - - // Find the *first* file rep and use it's path. - // This may not be the file on the file system - but is probably the path/name the user most associated with the artifact - if (auto fileRep = findRepresentation(artifact)) + const UnownedStringSlice path = findPath(artifact); + if (path.getLength()) { - // If there isn't a lock file it is - if (fileRep->getLockFile() == nullptr) + auto ext = Path::getPathExt(UnownedStringSlice(path)); + if (ext.getLength()) { - return UnownedStringSlice(fileRep->getPath()); + return ext; } } - return UnownedStringSlice(); } -/* static */UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) +/* static */UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact) { - for (auto rep :artifact->getRepresentations()) - { - if (auto fileRep = as(rep)) - { - const char* path = fileRep->getPath(); - auto ext = Path::getPathExt(UnownedStringSlice(path)); - if (ext.getLength()) - { - return ext; - } - } - } - - // Okay lets see if the name has an extension - return Path::getPathExt(UnownedStringSlice(artifact->getName())); + const UnownedStringSlice path = findPath(artifact); + const Index pos = Path::findLastSeparatorIndex(path); + return (pos >= 0) ? path.tail(pos + 1) : path; } static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath) diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h index 16687d6a9..70b736828 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -10,16 +10,6 @@ namespace Slang struct ArtifactUtil { - /// Get the base name of this artifact. - /// If there is a path set, will extract the name from that (stripping prefix, extension as necessary). - /// Else if there is an explicit name set, this is returned. - /// Else returns the empty string - static String getBaseName(IArtifact* artifact); - - /// Get the parent path (empty if there isn't one) - static String getParentPath(IArtifact* artifact); - static String getParentPath(IFileArtifactRepresentation* fileRep); - /// Create an empty container which is compatible with the desc static ComPtr createContainer(const ArtifactDesc& desc); @@ -38,20 +28,14 @@ struct ArtifactUtil /// Find a significant artifact static IArtifact* findSignificant(IArtifact* artifact); - /// Returns the rep of the artifact that contains a temporary (identified by having a lock) on - /// the OS file system - static IFileArtifactRepresentation* findFileSystemTemporaryFile(IArtifact* artifact); - /// Returns true if the artifact contains a file on the OS file system - static IFileArtifactRepresentation* findFileSystemFile(IArtifact* artifact); - /// Returns the rep of a file system file which *isn't* temporary - static IFileArtifactRepresentation* findFileSystemPrimaryFile(IArtifact* artifact); - /// Find the path/name associated with the artifact. /// The path is *not* necessarily the path on the file system. The order of search is /// * If the artifact has a name return that - /// * If the artifact has a IFileArtifactRepresentation (that isn't temporary) return it's path + /// * If the artifact has a IPathFileArtifactRepresentation (that isn't temporary) return it's path /// * If not found return an empty slice static UnownedStringSlice findPath(IArtifact* artifact); + /// Find a name + static UnownedStringSlice findName(IArtifact* artifact); /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be interpretted in different ways /// This function uses the associated name and file representations to infer a extension. If none is found returns an empty slice. diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index 672e8d8d4..222b902a5 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -275,7 +275,9 @@ inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked) } // Forward declare -class IFileArtifactRepresentation; +class IOSFileArtifactRepresentation; +class IPathArtifactRepresentation; + class IArtifactRepresentation; // Controls what items can be kept. @@ -376,7 +378,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, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) = 0; /// Load the artifact as a shared library virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; @@ -500,8 +502,6 @@ class IArtifactHandler : public ICastable virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifactContainer* container) = 0; /// Given an artifact gets or creates a representation. virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) = 0; - /// Given an artifact gets a represenation of it on the file system. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateFileRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangMutableFileSystem* fileSystem, IFileArtifactRepresentation** outFileRep) = 0; }; } // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index f665757bb..104f1e631 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -82,7 +82,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio auto artifactList = CastableList::create(); // It may be necessary to produce a temporary file 'lock file'. - ComPtr lockFile; + ComPtr lockFile; // The allocator can be used for items that are not kept in scope by the options String modulePath; @@ -92,7 +92,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio { // We could use the path to the source, or use the source name/paths as defined on the artifact // For now we just go with a lock file based on "slang-generated". - SLANG_RETURN_ON_FAIL(helper->createLockFile("slang-generated", nullptr, lockFile.writeRef())); + SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef())); auto lockArtifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None)); lockArtifact->addRepresentation(lockFile); @@ -108,8 +108,8 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Append command line args to the end of cmdLine using the target specific function for the specified options SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); - // The 'mainArtifact' is the main product produced from the compilation - the executable/sharedlibrary/object etc - ComPtr mainArtifact; + // The 'productArtifact' is the main product produced from the compilation - the executable/sharedlibrary/object etc + ComPtr productArtifact; { List> artifacts; SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); @@ -119,17 +119,17 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // The main artifact must be in the list, so add it if we find it if (artifact->getDesc() == targetDesc) { - SLANG_ASSERT(mainArtifact == nullptr); - mainArtifact = artifact; + SLANG_ASSERT(productArtifact == nullptr); + productArtifact = artifact; } artifactList->add(artifact); } } - SLANG_ASSERT(mainArtifact); + SLANG_ASSERT(productArtifact); // Somethings gone wrong if we don't find the main artifact - if (!mainArtifact) + if (!productArtifact) { return SLANG_FAIL; } @@ -166,15 +166,15 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio { // We should find a file rep and if we do we can disown it. Disowning will mean // when scope is lost the rep won't try and delete the (apparently non existing) backing file. - if (auto fileRep = findRepresentation(artifact)) + if (auto fileRep = findRepresentation(artifact)) { fileRep->disown(); } // If the main artifact doesn't exist, we don't have a main artifact - if (artifact == mainArtifact) + if (artifact == productArtifact) { - mainArtifact.setNull(); + productArtifact.setNull(); } // Remove from the list @@ -188,9 +188,13 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Add all of the source artifacts, that are temporary on the file system, such that they can stay in scope for debugging for (auto sourceArtifact : options.sourceArtifacts) { - if (ArtifactUtil::findFileSystemTemporaryFile(sourceArtifact) && sourceArtifact->exists()) + if (auto fileRep = findRepresentation(sourceArtifact)) { - artifactList->add(sourceArtifact); + // If it has a lock file we can assume it's a temporary + if (fileRep->getLockFile()) + { + artifactList->add(sourceArtifact); + } } } @@ -207,7 +211,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Find the rep from the 'main' artifact, we'll just use the same representation on the output // artifact. Sharing is desirable, because the rep owns the file. - if (auto fileRep = mainArtifact ? findRepresentation(mainArtifact) : nullptr) + if (auto fileRep = productArtifact ? findRepresentation(productArtifact) : nullptr) { artifact->addRepresentation(fileRep); } diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index a9ef56221..a543f8e46 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -235,7 +235,7 @@ public: /// Given options determines the paths to products produced (including the 'moduleFilePath'). /// Note that does *not* guarentee all products were or should be produced. Just aims to include all that could /// be produced, such that can be removed on completion. - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts) = 0; + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) = 0; virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) = 0; diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 03ad868a8..c92eea47b 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -86,7 +86,7 @@ static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlic static UnownedStringSlice _addName(IArtifact* artifact, StringSlicePool& pool) { - return _addName(ArtifactUtil::getBaseName(artifact).getUnownedSlice(), pool); + return _addName(ArtifactUtil::findName(artifact), pool); } class DxcIncludeHandler : public IDxcIncludeHandler diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 8851477d7..f003ffb0f 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -432,7 +432,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts) +/* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -444,7 +444,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); - auto fileRep = FileArtifactRepresentation::create(IFileArtifactRepresentation::Kind::Owned, builder.getUnownedSlice(), lockFile, nullptr); + auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, builder.getUnownedSlice(), lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); @@ -615,11 +615,11 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // Files to compile, need to be on the file system. for (IArtifact* sourceArtifact : options.sourceArtifacts) { - ComPtr fileRep; + ComPtr fileRep; // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. - SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); + SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); } @@ -644,13 +644,15 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // If it's a library for CPU types, try and use it if (ArtifactDescUtil::isCpuBinary(artifactDesc) && artifactDesc.kind == ArtifactKind::Library) { - ComPtr fileRep; + ComPtr fileRep; // Get the name and path (can be empty) to the library - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); - libPathPool.add(ArtifactUtil::getParentPath(fileRep)); - cmdLine.addPrefixPathArg("-l", ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep)); + const UnownedStringSlice path(fileRep->getPath()); + libPathPool.add(Path::getParentDirectory(path)); + + cmdLine.addPrefixPathArg("-l", ArtifactDescUtil::getBaseNameFromPath(artifact->getDesc(), path)); } } diff --git a/source/compiler-core/slang-gcc-compiler-util.h b/source/compiler-core/slang-gcc-compiler-util.h index 8791930bb..6afb39ec6 100644 --- a/source/compiler-core/slang-gcc-compiler-util.h +++ b/source/compiler-core/slang-gcc-compiler-util.h @@ -22,7 +22,7 @@ struct GCCDownstreamCompilerUtil : public DownstreamCompilerUtilBase static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics); /// Given options, calculate paths to products/files produced for a compilation - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts); + static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts); /// Given the exe location, creates a DownstreamCompiler. /// Note! Invoke/s the compiler to determine the compiler version number. @@ -44,7 +44,7 @@ public: // CommandLineCPPCompiler impl - just forwards to the Util virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); } + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); } GCCDownstreamCompiler(const Desc& desc):Super(desc) {} }; diff --git a/source/compiler-core/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp index 455ecde2b..9cd193ec6 100644 --- a/source/compiler-core/slang-include-system.cpp +++ b/source/compiler-core/slang-include-system.cpp @@ -132,7 +132,7 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr sourceFile = m_sourceManager->createSourceFileWithBlob(pathInfo, foundSourceBlob); m_sourceManager->addSourceFile(pathInfo.uniqueIdentity, sourceFile); - sourceFile->maybeAddArtifact(m_fileSystemExt); + sourceFile->maybeAddArtifact(nullptr, m_fileSystemExt); outBlob = foundSourceBlob; return SLANG_OK; @@ -152,7 +152,7 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr } sourceFile->setContents(foundSourceBlob); - sourceFile->maybeAddArtifact(m_fileSystemExt); + sourceFile->maybeAddArtifact(nullptr, m_fileSystemExt); outBlob = foundSourceBlob; return SLANG_OK; diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp index c82636248..6b4c5654d 100644 --- a/source/compiler-core/slang-source-loc.cpp +++ b/source/compiler-core/slang-source-loc.cpp @@ -6,6 +6,8 @@ #include "slang-artifact-representation-impl.h" #include "slang-artifact-impl.h" +#include "slang-artifact-util.h" +#include "slang-artifact-desc-util.h" namespace Slang { @@ -432,69 +434,61 @@ String SourceFile::calcVerbosePath() const return m_pathInfo.foundPath; } -void SourceFile::maybeAddArtifact(ISlangFileSystemExt* ext) +void SourceFile::maybeAddArtifact(const ArtifactDesc* inArtifactDesc, ISlangFileSystemExt* ext) { if (!m_contentBlob) { return; } - // If there already is an artifact, or we are not using OSFile system then + // If there already is an artifact, we don't need to create one if (m_artifact) { - // TODO(JS): - // Check if it has the blob or not + // Check it has a blob and the blob is the same as the content blob SLANG_ASSERT(m_contentBlob == findRepresentation(m_artifact)); return; } - // We don't know how the source will be used - m_artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Unknown, ArtifactStyle::Unknown)); + ArtifactDesc artifactDesc; - // Add the blob as a representation. - m_artifact->addRepresentationUnknown(m_contentBlob); - - // If we have the file system see if we can set up a path too - if (ext) + if (inArtifactDesc) { - const auto osPathKind = ext->getOSPathKind(); + artifactDesc = *inArtifactDesc; + } + else + { + // Set the default + artifactDesc = ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Unknown, ArtifactStyle::Unknown); - if (osPathKind != OSPathKind::None) + // Let's work out from the + // We could try and work it out + if (getPathInfo().foundPath.getLength()) { - String path; - switch (osPathKind) - { - case OSPathKind::Canonical: - { - // Get the canonical path - ComPtr canonicalPath; - if (SLANG_SUCCEEDED(ext->getCanonicalPath(getPathInfo().foundPath.getBuffer(), canonicalPath.writeRef()))) - { - path = StringUtil::getString(canonicalPath); - } - break; - } - case OSPathKind::Direct: - { - path = getPathInfo().foundPath; - break; - } - } + // Let's work out what kind of source it is from the this + auto desc = ArtifactDescUtil::getDescFromPath(getPathInfo().foundPath.getUnownedSlice()); - if (path.getLength()) + // If found something just use that + if (desc.kind == ArtifactKind::Source) { - // We can sanity check that this works - SlangPathType pathType; - if (SLANG_SUCCEEDED(ext->getPathType(path.getBuffer(), &pathType))) - { - // We can add a file representation - FileArtifactRepresentation* fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice(), nullptr, nullptr); - m_artifact->addRepresentation(fileRep); - } + artifactDesc = desc; } } } + // We don't know how the source will be used + m_artifact = Artifact::create(artifactDesc); + + // Add the blob as a representation. + m_artifact->addRepresentationUnknown(m_contentBlob); + + // If we have the file system, set up the rep to that + if (ext) + { + // Add the representation on the file system + auto extRep = new ExtFileArtifactRepresentation(getPathInfo().foundPath.getUnownedSlice(), ext); + m_artifact->addRepresentation(extRep); + } + // Get the name auto name = getPathInfo().getName(); if (name.getLength()) diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h index 461f09e96..29ed9dfbb 100644 --- a/source/compiler-core/slang-source-loc.h +++ b/source/compiler-core/slang-source-loc.h @@ -246,8 +246,9 @@ public: /// Set the content as a string void setContents(const String& content); - /// If artifact isn't defined will try and associate one. The pathInfo must be the one associated with the PathInfo - void maybeAddArtifact(ISlangFileSystemExt* ext); + /// If the desc isn't set, will use Unknown source type + /// If artifact isn't defined will try and associate one. + void maybeAddArtifact(const ArtifactDesc* desc, ISlangFileSystemExt* ext); /// Calculate a display path -> can canonicalize if necessary String calcVerbosePath() const; diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index 17fb96ee8..2d5b37c50 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -21,16 +21,16 @@ namespace Slang { -static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifactRepresentation* lockFile, List>& outArtifacts) +static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) { - auto fileRep = FileArtifactRepresentation::create(IFileArtifactRepresentation::Kind::Owned, path.getUnownedSlice(), lockFile, nullptr); + auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, path.getUnownedSlice(), lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); outArtifacts.add(artifact); } -/* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts) +/* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -238,11 +238,11 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact // Files to compile, need to be on the file system. for (IArtifact* sourceArtifact : options.sourceArtifacts) { - ComPtr fileRep; + ComPtr fileRep; // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. - SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); + SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); } @@ -264,12 +264,13 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IFileArtifact if (ArtifactDescUtil::isCpuBinary(desc) && desc.kind == ArtifactKind::Library) { // Get the libray name and path - ComPtr fileRep; - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, nullptr, fileRep.writeRef())); + ComPtr fileRep; + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); - libPathPool.add(ArtifactUtil::getParentPath(fileRep)); + const UnownedStringSlice path(fileRep->getPath()); + libPathPool.add(Path::getParentDirectory(path)); // We need the extension for windows - cmdLine.addArg(ArtifactDescUtil::getBaseName(artifact->getDesc(), fileRep) + ".lib"); + cmdLine.addArg(ArtifactDescUtil::getBaseNameFromPath(desc, path) + ".lib"); } } diff --git a/source/compiler-core/slang-visual-studio-compiler-util.h b/source/compiler-core/slang-visual-studio-compiler-util.h index db9f9b7ac..fa1fb7c69 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.h +++ b/source/compiler-core/slang-visual-studio-compiler-util.h @@ -14,7 +14,7 @@ struct VisualStudioCompilerUtil : public DownstreamCompilerUtilBase /// Parse Visual Studio exeRes into CPPCompiler::Output static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* outOutput); - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IFileArtifactRepresentation* lockFile, List>& outArtifacts); + static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts); static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); }; @@ -28,7 +28,7 @@ public: // CommandLineDownstreamCompiler impl - just forwards to the Util virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags productFlags, IFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); } + virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags productFlags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); } VisualStudioDownstreamCompiler(const Desc& desc):Super(desc) {} }; diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 15a1ceb4b..ce380681e 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1071,13 +1071,6 @@ namespace Slang SourceFile* sourceFile = sourceFiles[0]; - // Make it have an artifact if doesn't have one already - // This is useful because it will mean any reps will be kept in scope - // - // For example if file backing is needed, the file rep will last the lifetime of the - // SourceFile - sourceFile->maybeAddArtifact(nullptr); - sourceArtifact = sourceFile->getArtifact(); SLANG_ASSERT(sourceArtifact); } @@ -1258,7 +1251,7 @@ namespace Slang // Set up the library artifact auto artifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Library, Artifact::Payload::HostCPU), toSlice("slang-rt")); - ComPtr fileRep(new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::NameOnly, toSlice("slang-rt"), nullptr, nullptr)); + ComPtr fileRep(new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::NameOnly, toSlice("slang-rt"), nullptr)); artifact->addRepresentation(fileRep); libraries.add(artifact); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 3c17d1c09..4c6b0a6b1 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -3025,6 +3025,8 @@ SLANG_FORCE_INLINE EndToEndCompileRequest* asInternal(SlangCompileRequest* reque SLANG_FORCE_INLINE SlangCompileTarget asExternal(CodeGenTarget target) { return (SlangCompileTarget)target; } +SLANG_FORCE_INLINE SlangSourceLanguage asExternal(SourceLanguage sourceLanguage) { return (SlangSourceLanguage)sourceLanguage; } + } #endif diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index f88f02221..a86cd5e6b 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -1491,15 +1491,15 @@ struct OptionsParser // Seeing as on all targets the baseName doesn't have an extension, and all library types do // if the name doesn't have an extension we can assume there is no path to it. - ComPtr fileRep; + ComPtr fileRep; if (Path::getPathExt(path).getLength() <= 0) { // If there is no extension *assume* it is the name of a system level library - fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::NameOnly, path.getUnownedSlice(), nullptr, nullptr); + fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::NameOnly, path.getUnownedSlice(), nullptr); } else { - fileRep = new FileArtifactRepresentation(IFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice(), nullptr, nullptr); + fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice(), nullptr); if (!fileRep->exists()) { sink->diagnose(referenceModuleName.loc, Diagnostics::libraryDoesNotExist, path); diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp index f1f7cffa4..739860915 100644 --- a/source/slang/slang-preprocessor.cpp +++ b/source/slang/slang-preprocessor.cpp @@ -3058,7 +3058,7 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob); auto fileSystemExt = context->m_preprocessor->fileSystem; - sourceFile->maybeAddArtifact(fileSystemExt); + sourceFile->maybeAddArtifact(nullptr, fileSystemExt); sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile); } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index a9868898e..a7a4fc8dc 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -2564,7 +2564,42 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile( int translationUnitIndex, SourceFile* sourceFile) { - translationUnits[translationUnitIndex]->addSourceFile(sourceFile); + auto translationUnit = translationUnits[translationUnitIndex]; + + // TODO(JS): + // The larger problem here is that a file on a file system *could* be interpretted in different ways. + // When the user supplies the source as a string, we use the source type specified for the translation unit. + // + // If it's on the file system it could be (say) compiled as HLSL or some other way. A *downstream* compiler + // that used the file system may care. + // + // We will assume here, that if it's loaded from the file system, it's path extension defines how it should be interpretted + // If that wasn't the case we'd have to either *copy*, or do some command line fiddling to tell it for the downstream compiler + // what the file is. + + const auto& pathInfo = sourceFile->getPathInfo(); + const auto pathType = pathInfo.type; + + switch (pathType) + { + case PathInfo::Type::FromString: + { + // Set the artifact type from the the source language type + auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(asExternal(translationUnit->sourceLanguage)); + sourceFile->maybeAddArtifact(&sourceDesc, nullptr); + break; + } + case PathInfo::Type::FoundPath: + case PathInfo::Type::Normal: + { + // We'll *not* use the source for the artifact type. Doing so will lead to the type being determined via extension + sourceFile->maybeAddArtifact(nullptr, getLinkage()->getFileSystemExt()); + break; + } + } + + // Add the source file + translationUnit->addSourceFile(sourceFile); } void FrontEndCompileRequest::addTranslationUnitSourceBlob( @@ -2575,8 +2610,6 @@ void FrontEndCompileRequest::addTranslationUnitSourceBlob( // The path specified may or may not be a file path - mark as being constructed 'FromString'. SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(PathInfo::makeFromString(path), sourceBlob); - sourceFile->maybeAddArtifact(nullptr); - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); } @@ -2588,8 +2621,6 @@ void FrontEndCompileRequest::addTranslationUnitSourceString( // The path specified may or may not be a file path - mark as being constructed 'FromString'. SourceFile* sourceFile = getSourceManager()->createSourceFileWithString(PathInfo::makeFromString(path), source); - sourceFile->maybeAddArtifact(nullptr); - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); } @@ -2622,8 +2653,6 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile( // Was loaded from the specified path SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(pathInfo, sourceBlob); - sourceFile->maybeAddArtifact(getLinkage()->getFileSystemExt()); - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); } diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index ef5d16b2c..e30b7dd8c 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -2239,7 +2239,26 @@ static TestResult runCPPCompilerSharedLibrary(TestContext* context, TestInput& i // Compile this source ComPtr sourceArtifact; - helper->createFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef()); + + // If set, we store the artifact in memory without a name. + bool checkMemory = false; + if (checkMemory) + { + helper->createArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), "", sourceArtifact.writeRef()); + + ComPtr fileRep; + // Let's just add a blob with the contents + helper->createOSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, asCharSlice(filePath.getUnownedSlice()), nullptr, fileRep.writeRef()); + + ComPtr castable; + fileRep->createRepresentation(ISlangBlob::getTypeGuid(), castable.writeRef()); + + sourceArtifact->addRepresentation(castable); + } + else + { + helper->createOSFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef()); + } TerminatedCharSlice includePaths[] = { TerminatedCharSlice(".") }; @@ -2365,7 +2384,7 @@ static TestResult runCPPCompilerExecute(TestContext* context, TestInput& input) auto helper = DefaultArtifactHelper::getSingleton(); ComPtr sourceArtifact; - helper->createFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef()); + helper->createOSFileArtifact(ArtifactDescUtil::makeDescForSourceLanguage(options.sourceLanguage), asCharSlice(filePath.getUnownedSlice()), sourceArtifact.writeRef()); // Compile this source options.sourceArtifacts = makeSlice(sourceArtifact.readRef(), 1); -- cgit v1.2.3