diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-09-01 15:38:17 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-01 15:38:17 -0400 |
| commit | be8497804f803c02cfab1aa2c54d921042e90ec9 (patch) | |
| tree | c9451382ba2bf112848441f9d61470a90ed764ee /source | |
| parent | 174048f26c147e31a6f72907a3af5dfafeedb877 (diff) | |
Remove artifact from SourceFile (#2384)
* #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.
* Remove artifact from SourceFile.
Lazily generate SourceFile from artifacts as needed.
* Fix some small bugs.
* Remove maybeAddArtifact.
* Load artifacts if repro capture is enabled.
* Remove adding by string, because doing so means source will be allocated twice or there is a potential race around ref counting to the contained String.
* Add built in source as a blob.
* Fix warning.
* Make StringBlob own the contents if moved.
Fix some compilation issues.
* Share StringBlob uniqueness code.
* Do move unique on Ctor.
* Change MoveUnique to not have any values.
* MoveUnique can more sensibly be a struct.
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/compiler-core/slang-artifact-representation-impl.cpp | 2 | ||||
| -rw-r--r-- | source/compiler-core/slang-artifact-representation-impl.h | 2 | ||||
| -rw-r--r-- | source/compiler-core/slang-include-system.cpp | 3 | ||||
| -rw-r--r-- | source/compiler-core/slang-source-loc.cpp | 63 | ||||
| -rw-r--r-- | source/compiler-core/slang-source-loc.h | 12 | ||||
| -rw-r--r-- | source/core/slang-blob.cpp | 29 | ||||
| -rw-r--r-- | source/core/slang-blob.h | 20 | ||||
| -rw-r--r-- | source/slang/slang-compiler.cpp | 50 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 56 | ||||
| -rw-r--r-- | source/slang/slang-preprocessor.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-reflection-api.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-repro.cpp | 19 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 273 |
13 files changed, 328 insertions, 206 deletions
diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 9a5c13311..950ce5d7d 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -23,7 +23,7 @@ void* ExtFileArtifactRepresentation::getInterface(const Guid& guid) guid == IPathArtifactRepresentation::getTypeGuid() || guid == IExtFileArtifactRepresentation::getTypeGuid()) { - return static_cast<IPathArtifactRepresentation*>(this); + return static_cast<IExtFileArtifactRepresentation*>(this); } return nullptr; } diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index da21e30bc..880a90c18 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -108,7 +108,7 @@ protected: /* 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! +NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI boundary remains risky! */ class ObjectArtifactRepresentation : public ComBaseObject, public IArtifactRepresentation { diff --git a/source/compiler-core/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp index 9cd193ec6..ebfc8db05 100644 --- a/source/compiler-core/slang-include-system.cpp +++ b/source/compiler-core/slang-include-system.cpp @@ -132,8 +132,6 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob> sourceFile = m_sourceManager->createSourceFileWithBlob(pathInfo, foundSourceBlob); m_sourceManager->addSourceFile(pathInfo.uniqueIdentity, sourceFile); - sourceFile->maybeAddArtifact(nullptr, m_fileSystemExt); - outBlob = foundSourceBlob; return SLANG_OK; } @@ -152,7 +150,6 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr<ISlangBlob> } sourceFile->setContents(foundSourceBlob); - 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 6b4c5654d..ac6589e76 100644 --- a/source/compiler-core/slang-source-loc.cpp +++ b/source/compiler-core/slang-source-loc.cpp @@ -434,69 +434,6 @@ String SourceFile::calcVerbosePath() const return m_pathInfo.foundPath; } -void SourceFile::maybeAddArtifact(const ArtifactDesc* inArtifactDesc, ISlangFileSystemExt* ext) -{ - if (!m_contentBlob) - { - return; - } - - // If there already is an artifact, we don't need to create one - if (m_artifact) - { - // Check it has a blob and the blob is the same as the content blob - SLANG_ASSERT(m_contentBlob == findRepresentation<ISlangBlob>(m_artifact)); - return; - } - - ArtifactDesc artifactDesc; - - if (inArtifactDesc) - { - artifactDesc = *inArtifactDesc; - } - else - { - // Set the default - artifactDesc = ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Unknown, ArtifactStyle::Unknown); - - // Let's work out from the - // We could try and work it out - if (getPathInfo().foundPath.getLength()) - { - // Let's work out what kind of source it is from the this - auto desc = ArtifactDescUtil::getDescFromPath(getPathInfo().foundPath.getUnownedSlice()); - - // If found something just use that - if (desc.kind == ArtifactKind::Source) - { - 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()) - { - m_artifact->setName(name.getBuffer()); - } -} - /* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ void SourceManager::initialize( diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h index 29ed9dfbb..66e4c0475 100644 --- a/source/compiler-core/slang-source-loc.h +++ b/source/compiler-core/slang-source-loc.h @@ -9,8 +9,6 @@ #include "../../slang-com-ptr.h" #include "../../slang.h" -#include "slang-artifact-representation.h" - namespace Slang { /** Overview: @@ -236,20 +234,11 @@ public: /// Get path info const PathInfo& getPathInfo() const { return m_pathInfo; } - /// Get the (optional) assoicated artifact. Note its desc might be Source/Unknown - IArtifact* getArtifact() const { return m_artifact; } - /// Set the artifact - void setArtifact(IArtifact* artifact) { m_artifact = artifact; } - /// Set the content as a blob void setContents(ISlangBlob* blob); /// Set the content as a string void setContents(const String& content); - /// 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; @@ -266,7 +255,6 @@ public: SourceManager* m_sourceManager; ///< The source manager this belongs to PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span. - ComPtr<IArtifact> m_artifact; ///< Optional artifact ComPtr<ISlangBlob> m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents UnownedStringSlice m_content; ///< The actual contents of the file. size_t m_contentSize; ///< The size of the actual contents diff --git a/source/core/slang-blob.cpp b/source/core/slang-blob.cpp index 6cf5214cc..a4acb98cb 100644 --- a/source/core/slang-blob.cpp +++ b/source/core/slang-blob.cpp @@ -35,6 +35,25 @@ void* BlobBase::castAs(const SlangUUID& guid) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +StringBlob::StringBlob(MoveUnique, String& in) +{ + auto rep = in.getStringRepresentation(); + if (rep && !rep->isUniquelyReferenced()) + { + // Make a new unique copy + m_string = in.getUnownedSlice(); + + // Move out of in + String tmp; + tmp.swapWith(in); + } + else + { + // Must either not have a rep or be unique + m_string.swapWith(in); + } +} + void* StringBlob::castAs(const SlangUUID& guid) { if (auto intf = getInterface(guid)) @@ -59,6 +78,16 @@ void* StringBlob::getObject(const Guid& guid) return nullptr; } +/* static */ComPtr<ISlangBlob> StringBlob::moveCreate(String& in) +{ + return ComPtr<ISlangBlob>(new StringBlob(MoveUnique{}, in)); +} + +/* static */ComPtr<ISlangBlob> StringBlob::moveCreate(String&& in) +{ + return ComPtr<ISlangBlob>(new StringBlob(MoveUnique{}, in)); +} + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RawBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* RawBlob::castAs(const SlangUUID& guid) diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h index 1acf279ef..e528f55a8 100644 --- a/source/core/slang-blob.h +++ b/source/core/slang-blob.h @@ -50,17 +50,25 @@ public: SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_string.getLength(); } static ComPtr<ISlangBlob> create(const String& in) { return ComPtr<ISlangBlob>(new StringBlob(in)); } - static ComPtr<ISlangBlob> moveCreate(String& in) - { - auto blob = new StringBlob; - blob->m_string.swapWith(in); - return ComPtr<ISlangBlob>(blob); - } + + /// Moves from in into the created blob. + /// NOTE! That will only use the representation from in, if it is *unique* + /// otherwise it will make a new copy. + /// This is so that StringBlob won't hold a reference count via a string held externally. + /// In contrast StringBlob::create *may* share the representation. + static ComPtr<ISlangBlob> moveCreate(String& in); + static ComPtr<ISlangBlob> moveCreate(String&& in); protected: + /// A type that is only used to differentiate a constructor. Can construct with + /// MoveUnique{} + struct MoveUnique {}; + explicit StringBlob(String const& string) : m_string(string) {} + + StringBlob(MoveUnique, String& string); StringBlob() {} /// Get the contained string diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index ce380681e..06cc9d759 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -578,6 +578,22 @@ namespace Slang } } + SlangResult CodeGenContext::requireTranslationUnitSourceFiles() + { + if (auto endToEndReq = isPassThroughEnabled()) + { + for (auto entryPointIndex : getEntryPointIndices()) + { + auto translationUnit = getPassThroughTranslationUnit(endToEndReq, entryPointIndex); + SLANG_ASSERT(translationUnit); + /// Make sure we have the source files + SLANG_RETURN_ON_FAIL(translationUnit->requireSourceFiles()); + } + } + + return SLANG_OK; + } + #if SLANG_VC // TODO(JS): This is a workaround // In debug VS builds there is a warning on line about it being unreachable. @@ -587,9 +603,11 @@ namespace Slang # pragma warning(disable:4702) #endif SlangResult CodeGenContext::emitEntryPointsSource(ComPtr<IArtifact>& outArtifact) - { + { outArtifact.setNull(); + SLANG_RETURN_ON_FAIL(requireTranslationUnitSourceFiles()); + auto endToEndReq = isPassThroughEnabled(); if(endToEndReq) { @@ -597,6 +615,10 @@ namespace Slang { auto translationUnit = getPassThroughTranslationUnit(endToEndReq, entryPointIndex); SLANG_ASSERT(translationUnit); + + /// Make sure we have the source files + SLANG_RETURN_ON_FAIL(translationUnit->requireSourceFiles()); + // Generate a string that includes the content of // the source file(s), along with a line directive // to ensure that we get reasonable messages @@ -835,23 +857,7 @@ namespace Slang if (compiler->isFileBased()) { // It can only have *one* source file as otherwise we have to combine to make a new source file anyway - const auto& sourceFiles = translationUnit->getSourceFiles(); - - // The *assumption* here is that if it's file based that assuming it can find the file with the same contents - // it can compile directly without having to save off as a file - if (sourceFiles.getCount() == 1) - { - const SourceFile* sourceFile = sourceFiles[0]; - // We need the path to be found and set - // - // NOTE! That the downstream compiler can determine if the path and contents match such that it can be used - // without writing file - const PathInfo& pathInfo = sourceFile->getPathInfo(); - if ((pathInfo.type == PathInfo::Type::FoundPath || pathInfo.type == PathInfo::Type::Normal) && pathInfo.foundPath.getLength()) - { - return false; - } - } + return translationUnit->getSourceArtifacts().getCount() != 1; } return true; } @@ -1066,12 +1072,10 @@ namespace Slang else { // Special case if we have a single file, so that we pass the path, and the contents as is. - const auto& sourceFiles = translationUnit->getSourceFiles(); - SLANG_ASSERT(sourceFiles.getCount() == 1); - - SourceFile* sourceFile = sourceFiles[0]; + const auto& sourceArtifacts = translationUnit->getSourceArtifacts(); + SLANG_ASSERT(sourceArtifacts.getCount() == 1); - sourceArtifact = sourceFile->getArtifact(); + sourceArtifact = sourceArtifacts[0]; SLANG_ASSERT(sourceArtifact); } } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 4c6b0a6b1..8aba89677 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1381,19 +1381,33 @@ namespace Slang // The parent compile request FrontEndCompileRequest* compileRequest = nullptr; - // The language in which the source file(s) - // are assumed to be written + // The language in which the source file(s) + // are assumed to be written SourceLanguage sourceLanguage = SourceLanguage::Unknown; - // The source file(s) that will be compiled to form this translation unit - // - // Usually, for HLSL or GLSL there will be only one file. - List<SourceFile*> m_sourceFiles; + /// Makes any source artifact available as a SourceFile. + /// If successful any of the source artifacts will be represented by the same index + /// of sourceArtifacts + SlangResult requireSourceFiles(); + + /// Get the source files. + /// Since lazily evaluated requires calling requireSourceFiles to know it's in sync + /// with sourceArtifacts. + List<SourceFile*> const& getSourceFiles(); + + /// Get the source artifacts associated + const List<ComPtr<IArtifact>>& getSourceArtifacts() const { return m_sourceArtifacts; } + + /// Clear all of the source + void clearSource() { m_sourceArtifacts.clear(); m_sourceFiles.clear(); } + + /// Add a source artifact + void addSourceArtifact(IArtifact* sourceArtifact); - List<SourceFile*> const& getSourceFiles() { return m_sourceFiles; } - void addSourceFile(SourceFile* sourceFile); + /// Add both the artifact and the sourceFile. + void addSource(IArtifact* sourceArtifact, SourceFile* sourceFile); - // The entry points associated with this translation unit + // The entry points associated with this translation unit List<RefPtr<EntryPoint>> const& getEntryPoints() { return module->getEntryPoints(); } void _addEntryPoint(EntryPoint* entryPoint) { module->_addEntryPoint(entryPoint); } @@ -1414,6 +1428,17 @@ namespace Slang Session* getSession(); NamePool* getNamePool(); SourceManager* getSourceManager(); + + protected: + void _addSourceFile(SourceFile* sourceFile); + + List<ComPtr<IArtifact>> m_sourceArtifacts; + // The source file(s) that will be compiled to form this translation unit + // + // Usually, for HLSL or GLSL there will be only one file. + // NOTE! This member is generated lazily from m_sourceArtifacts + // it is *necessary* to call requireSourceFiles to ensure it's in sync. + List<SourceFile*> m_sourceFiles; }; enum class FloatingPointMode : SlangFloatingPointModeIntegral @@ -2007,20 +2032,15 @@ namespace Slang int addTranslationUnit(TranslationUnitRequest* translationUnit); - void addTranslationUnitSourceFile( + void addTranslationUnitSourceArtifact( int translationUnitIndex, - SourceFile* sourceFile); + IArtifact* sourceArtifact); void addTranslationUnitSourceBlob( int translationUnitIndex, String const& path, ISlangBlob* sourceBlob); - void addTranslationUnitSourceString( - int translationUnitIndex, - String const& path, - String const& source); - void addTranslationUnitSourceFile( int translationUnitIndex, String const& path); @@ -2386,6 +2406,8 @@ namespace Slang bool isSpecializationDisabled(); + SlangResult requireTranslationUnitSourceFiles(); + // SlangResult emitEntryPoints(ComPtr<IArtifact>& outArtifact); @@ -2890,7 +2912,7 @@ namespace Slang void addBuiltinSource( Scope* scope, String const& path, - String const& source); + ISlangBlob* sourceBlob); ~Session(); void addDownstreamCompileTime(double time) { m_downstreamCompileTime += time; } diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp index 739860915..fca8f5029 100644 --- a/source/slang/slang-preprocessor.cpp +++ b/source/slang/slang-preprocessor.cpp @@ -3057,9 +3057,6 @@ static void HandleIncludeDirective(PreprocessorDirectiveContext* context) sourceFile = sourceManager->createSourceFileWithBlob(filePathInfo, foundSourceBlob); - auto fileSystemExt = context->m_preprocessor->fileSystem; - sourceFile->maybeAddArtifact(nullptr, fileSystemExt); - sourceManager->addSourceFile(filePathInfo.uniqueIdentity, sourceFile); } diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index ae43f9113..eb2b9aff9 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -1245,7 +1245,7 @@ namespace Slang auto access = resourceType->getAccess(); auto mutableFlag = access != SLANG_RESOURCE_ACCESS_READ ? SLANG_BINDING_TYPE_MUTABLE_FLAG : 0; - switch( shape ) + switch(SlangResourceShape(shape )) { default: return SlangBindingType(SLANG_BINDING_TYPE_TEXTURE | mutableFlag); diff --git a/source/slang/slang-repro.cpp b/source/slang/slang-repro.cpp index aa4dc92fc..1597366d6 100644 --- a/source/slang/slang-repro.cpp +++ b/source/slang/slang-repro.cpp @@ -10,6 +10,9 @@ #include "slang-options.h" +#include "../compiler-core/slang-artifact-util.h" +#include "../compiler-core/slang-artifact-desc-util.h" + #include "../compiler-core/slang-source-loc.h" namespace Slang { @@ -996,15 +999,25 @@ struct LoadContext dstTranslationUnit->moduleName = moduleName; const auto& srcSourceFiles = srcTranslationUnit.sourceFiles; - auto& dstSourceFiles = dstTranslationUnit->m_sourceFiles; - dstSourceFiles.clear(); + dstTranslationUnit->clearSource(); + + const auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(asExternal(dstTranslationUnit->sourceLanguage)); for (Index j = 0; j < srcSourceFiles.getCount(); ++j) { + // Create the source file SourceFile* sourceFile = context.getSourceFile(base.asRaw(base.asRaw(srcSourceFiles[i]))); + + // Create the artifact + auto sourceArtifact = ArtifactUtil::createArtifact(sourceDesc, sourceFile->getPathInfo().getName().getBuffer()); + if (sourceFile->getContentBlob()) + { + sourceArtifact->addRepresentationUnknown(sourceFile->getContentBlob()); + } + // Add to translation unit - dstTranslationUnit->addSourceFile(sourceFile); + dstTranslationUnit->addSource(sourceArtifact, sourceFile); } } } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index a7a4fc8dc..18b9b3c99 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -249,13 +249,15 @@ void Session::_initCodeGenTransitionMap() void Session::addBuiltins( char const* sourcePath, - char const* sourceString) + char const* source) { + auto sourceBlob = StringBlob::moveCreate(String(source)); + // TODO(tfoley): Add ability to directly new builtins to the appropriate scope addBuiltinSource( coreLanguageScope, sourcePath, - sourceString); + sourceBlob); } void Session::setSharedLibraryLoader(ISlangSharedLibraryLoader* loader) @@ -295,9 +297,9 @@ SlangResult Session::compileStdLib(slang::CompileStdLibFlags compileFlags) } // TODO(JS): Could make this return a SlangResult as opposed to exception - addBuiltinSource(coreLanguageScope, "core", getCoreLibraryCode()); - addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode()); - addBuiltinSource(autodiffLanguageScope, "diff", getAutodiffLibraryCode()); + addBuiltinSource(coreLanguageScope, "core", StringBlob::moveCreate(getCoreLibraryCode())); + addBuiltinSource(hlslLanguageScope, "hlsl", StringBlob::moveCreate(getHLSLLibraryCode())); + addBuiltinSource(autodiffLanguageScope, "diff", StringBlob::moveCreate(getAutodiffLibraryCode())); if (compileFlags & slang::CompileStdLibFlag::WriteDocumentation) { @@ -1489,7 +1491,120 @@ SourceManager* TranslationUnitRequest::getSourceManager() return compileRequest->getSourceManager(); } -void TranslationUnitRequest::addSourceFile(SourceFile* sourceFile) +void TranslationUnitRequest::addSourceArtifact(IArtifact* sourceArtifact) +{ + SLANG_ASSERT(sourceArtifact); + m_sourceArtifacts.add(ComPtr<IArtifact>(sourceArtifact)); +} + + +void TranslationUnitRequest::addSource(IArtifact* sourceArtifact, SourceFile* sourceFile) +{ + SLANG_ASSERT(sourceArtifact && sourceFile); + // Must be in sync! + SLANG_ASSERT(m_sourceFiles.getCount() == m_sourceArtifacts.getCount()); + + addSourceArtifact(sourceArtifact); + _addSourceFile(sourceFile); +} + +SlangResult TranslationUnitRequest::requireSourceFiles() +{ + SLANG_ASSERT(m_sourceFiles.getCount() <= m_sourceArtifacts.getCount()); + + if (m_sourceFiles.getCount() == m_sourceArtifacts.getCount()) + { + return SLANG_OK; + } + + auto sink = compileRequest->getSink(); + SourceManager* sourceManager = compileRequest->getSourceManager(); + + // Get he linkage file system + //ISlangFileSystemExt* linkageFileSystem = compileRequest->getLinkage()->getFileSystemExt(); + + for (Index i = m_sourceFiles.getCount(); i < m_sourceArtifacts.getCount(); ++i) + { + IArtifact* artifact = m_sourceArtifacts[i]; + + PathInfo pathInfo = PathInfo::makeUnknown(); + + if (auto extRep = findRepresentation<IExtFileArtifactRepresentation>(artifact)) + { + auto extFileSystem = extRep->getFileSystem(); + + // TODO(JS): + // Ideally we'd confirm that the file system was the same, such we could know that the unique + // identity is appropriate for the current file system. + // + // We just assume compatibility for the moment, because repro will be a different file system + // but we need to use the unique identity that is there. + + //if (extFileSystem == linkageFileSystem) + { + // Get the unique identity + ComPtr<ISlangBlob> uniqueIdentityBlob; + if (SLANG_SUCCEEDED(extFileSystem->getFileUniqueIdentity(extRep->getPath(), uniqueIdentityBlob.writeRef())) && uniqueIdentityBlob) + { + auto uniqueIdentity = StringUtil::getString(uniqueIdentityBlob); + + // See if this an already loaded source file + if (auto sourceFile = sourceManager->findSourceFileRecursively(uniqueIdentity)) + { + // If the source file has a blob, and the artifact doesn't copy over that representation + if (sourceFile->getContentBlob() && findRepresentation<ISlangBlob>(artifact) == nullptr) + { + artifact->addRepresentationUnknown(sourceFile->getContentBlob()); + } + + _addSourceFile(sourceFile); + continue; + } + + pathInfo = PathInfo::makeNormal(extRep->getPath(), uniqueIdentity); + } + else + { + pathInfo = PathInfo::makePath(extRep->getPath()); + } + } + } + + if (pathInfo.type == PathInfo::Type::Unknown) + { + const auto path = ArtifactUtil::findPath(artifact); + + // If has a path representation we'll make it a FoundPath + if (findRepresentation<IPathArtifactRepresentation>(artifact)) + { + pathInfo = PathInfo::makePath(path); + } + else + { + // Otherwise we'll assume it's created from a 'String' even if that's not quite the case + pathInfo = PathInfo::makeFromString(path); + } + } + + ComPtr<ISlangBlob> blob; + const SlangResult blobRes = artifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()); + if (SLANG_FAILED(blobRes)) + { + // Report couldn't load + sink->diagnose(SourceLoc(), + Diagnostics::cannotOpenFile, + pathInfo.getName()); + return blobRes; + } + + auto sourceFile = sourceManager->createSourceFileWithBlob(pathInfo, blob); + _addSourceFile(sourceFile); + } + + return SLANG_OK; +} + +void TranslationUnitRequest::_addSourceFile(SourceFile* sourceFile) { m_sourceFiles.add(sourceFile); @@ -1505,6 +1620,12 @@ void TranslationUnitRequest::addSourceFile(SourceFile* sourceFile) } } +List<SourceFile*> const& TranslationUnitRequest::getSourceFiles() +{ + SLANG_ASSERT(m_sourceArtifacts.getCount() == m_sourceFiles.getCount()); + return m_sourceFiles; +} + EndToEndCompileRequest::~EndToEndCompileRequest() { // Flush any writers associated with the request @@ -2246,8 +2367,11 @@ SlangResult FrontEndCompileRequest::executeActionsInner() // We currently allow GlSL files on the command line so that we can // drive our "pass-through" mode, but we really want to issue an error // message if the user is seriously asking us to compile them. - for (auto& translationUnit : translationUnits) + for (TranslationUnitRequest* translationUnit : translationUnits) { + // Make sure SourceFile representation is available for all translationUnits + SLANG_RETURN_ON_FAIL(translationUnit->requireSourceFiles()); + switch(translationUnit->sourceLanguage) { default: @@ -2261,9 +2385,9 @@ SlangResult FrontEndCompileRequest::executeActionsInner() // Parse everything from the input files requested - for (auto& translationUnit : translationUnits) + for (TranslationUnitRequest* translationUnit : translationUnits) { - parseTranslationUnit(translationUnit.Ptr()); + parseTranslationUnit(translationUnit); } if (outputPreprocessor) @@ -2559,47 +2683,14 @@ int FrontEndCompileRequest::addTranslationUnit(TranslationUnitRequest* translati return (int) result; } - -void FrontEndCompileRequest::addTranslationUnitSourceFile( +void FrontEndCompileRequest::addTranslationUnitSourceArtifact( int translationUnitIndex, - SourceFile* sourceFile) + IArtifact* sourceArtifact) { 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); + translationUnit->addSourceArtifact(sourceArtifact); } void FrontEndCompileRequest::addTranslationUnitSourceBlob( @@ -2607,21 +2698,13 @@ void FrontEndCompileRequest::addTranslationUnitSourceBlob( String const& path, ISlangBlob* sourceBlob) { - // The path specified may or may not be a file path - mark as being constructed 'FromString'. - SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(PathInfo::makeFromString(path), sourceBlob); - - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); -} + auto translationUnit = translationUnits[translationUnitIndex]; + auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(asExternal(translationUnit->sourceLanguage)); -void FrontEndCompileRequest::addTranslationUnitSourceString( - int translationUnitIndex, - String const& path, - String const& source) -{ - // The path specified may or may not be a file path - mark as being constructed 'FromString'. - SourceFile* sourceFile = getSourceManager()->createSourceFileWithString(PathInfo::makeFromString(path), source); + auto artifact = ArtifactUtil::createArtifact(sourceDesc, path.getBuffer()); + artifact->addRepresentationUnknown(sourceBlob); - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); + translationUnit->addSourceArtifact(artifact); } void FrontEndCompileRequest::addTranslationUnitSourceFile( @@ -2636,11 +2719,35 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile( // paths were not taken into account by this function. // - PathInfo pathInfo; + auto fileSystemExt = getLinkage()->getFileSystemExt(); + auto translationUnit = getTranslationUnit(translationUnitIndex); + + auto sourceDesc = ArtifactDescUtil::makeDescForSourceLanguage(asExternal(translationUnit->sourceLanguage)); + + auto sourceArtifact = ArtifactUtil::createArtifact(sourceDesc); - ComPtr<ISlangBlob> sourceBlob; - SlangResult result = loadFile(path, pathInfo, sourceBlob.writeRef()); - if(SLANG_FAILED(result)) + auto extRep = new ExtFileArtifactRepresentation(path.getUnownedSlice(), fileSystemExt); + sourceArtifact->addRepresentation(extRep); + + SlangResult existsRes = SLANG_OK; + + // If we require caching, we demand it's loaded here. + // + // In practice this probably means repro capture is enabled. So we want to + // load the blob such that it's in the cache, even if it doesn't actually + // have to be loaded for the compilation. + if (getLinkage()->m_requireCacheFileSystem) + { + ComPtr<ISlangBlob> blob; + // If we can load the blob, then it exists + existsRes = sourceArtifact->loadBlob(ArtifactKeep::Yes, blob.writeRef()); + } + else + { + existsRes = sourceArtifact->exists() ? SLANG_OK : SLANG_E_NOT_FOUND; + } + + if (SLANG_FAILED(existsRes)) { // Emit a diagnostic! getSink()->diagnose( @@ -2650,10 +2757,7 @@ void FrontEndCompileRequest::addTranslationUnitSourceFile( return; } - // Was loaded from the specified path - SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(pathInfo, sourceBlob); - - addTranslationUnitSourceFile(translationUnitIndex, sourceFile); + translationUnit->addSourceArtifact(sourceArtifact); } int FrontEndCompileRequest::addEntryPoint( @@ -2808,10 +2912,29 @@ RefPtr<Module> Linkage::loadModule( name, srcLoc); + // Create an artifact for the source + auto sourceArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Source, ArtifactPayload::Slang, ArtifactStyle::Unknown)); + // Create with the 'friendly' name - SourceFile* sourceFile = getSourceManager()->createSourceFileWithBlob(filePathInfo, sourceBlob); - - translationUnit->addSourceFile(sourceFile); + if (filePathInfo.type == PathInfo::Type::Normal || + filePathInfo.type == PathInfo::Type::FoundPath) + { + // We create that it was loaded from the file system + sourceArtifact->addRepresentation(new ExtFileArtifactRepresentation(filePathInfo.foundPath.getUnownedSlice(), getFileSystemExt())); + } + else + { + // Else we say we don't know and just add the blob + sourceArtifact->addRepresentationUnknown(sourceBlob); + } + + translationUnit->addSourceArtifact(sourceArtifact); + + if (SLANG_FAILED(translationUnit->requireSourceFiles())) + { + // Some problem accessing source files + return nullptr; + } int errorCountBefore = sink->getErrorCount(); frontEndReq->parseTranslationUnit(translationUnit); @@ -4234,7 +4357,7 @@ RefPtr<Module> findOrImportModule( void Session::addBuiltinSource( Scope* scope, String const& path, - String const& source) + ISlangBlob* sourceBlob) { SourceManager* sourceManager = getBuiltinSourceManager(); @@ -4254,10 +4377,10 @@ void Session::addBuiltinSource( Name* moduleName = getNamePool()->getName(path); auto translationUnitIndex = compileRequest->addTranslationUnit(SourceLanguage::Slang, moduleName); - compileRequest->addTranslationUnitSourceString( + compileRequest->addTranslationUnitSourceBlob( translationUnitIndex, path, - source); + sourceBlob); SlangResult res = compileRequest->executeActionsInner(); if (SLANG_FAILED(res)) @@ -4637,7 +4760,11 @@ void EndToEndCompileRequest::addTranslationUnitSourceStringSpan(int translationU if (!path) path = ""; - frontEndReq->addTranslationUnitSourceString(translationUnitIndex, path, UnownedStringSlice(sourceBegin, sourceEnd)); + const auto slice = UnownedStringSlice(sourceBegin, sourceEnd); + + auto blob = RawBlob::create(slice.begin(), slice.getLength()); + + frontEndReq->addTranslationUnitSourceBlob(translationUnitIndex, path, blob); } void EndToEndCompileRequest::addTranslationUnitSourceBlob(int translationUnitIndex, char const* path, ISlangBlob* sourceBlob) |
