diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-file-system.cpp | 110 | ||||
| -rw-r--r-- | source/slang/slang-file-system.h | 17 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 33 | ||||
| -rw-r--r-- | source/slang/slang-state-serialize.cpp | 159 | ||||
| -rw-r--r-- | source/slang/slang-state-serialize.h | 4 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 27 |
6 files changed, 264 insertions, 86 deletions
diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp index 7d6d6df66..c6bee28e1 100644 --- a/source/slang/slang-file-system.cpp +++ b/source/slang/slang-file-system.cpp @@ -203,18 +203,35 @@ SLANG_NO_THROW SlangResult SLANG_MCALL CacheFileSystem::queryInterface(SlangUUID } -CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle) : - m_fileSystem(fileSystem), - m_uniqueIdentityMode(uniqueIdentityMode), - m_pathStyle(pathStyle) +CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle) { + setInnerFileSystem(fileSystem, uniqueIdentityMode, pathStyle); +} + +CacheFileSystem::~CacheFileSystem() +{ + for (const auto& pair : m_uniqueIdentityMap) + { + delete pair.Value; + } +} + +void CacheFileSystem::setInnerFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle) +{ + m_fileSystem = fileSystem; + + m_uniqueIdentityMode = uniqueIdentityMode; + m_pathStyle = pathStyle; + + m_fileSystemExt.setNull(); + if (fileSystem) { // Try to get the more sophisticated interface fileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef()); } - switch (uniqueIdentityMode) + switch (m_uniqueIdentityMode) { case UniqueIdentityMode::Default: case UniqueIdentityMode::FileSystemExt: @@ -226,29 +243,22 @@ CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMod default: break; } - if (m_fileSystemExt) - { - // We just defer to the m_fileSystem, so we mark as unknown - m_pathStyle = PathStyle::Unknown; - } - else if (m_pathStyle == PathStyle::Default) + if (pathStyle == PathStyle::Default) { // We'll assume it's simplify-able m_pathStyle = PathStyle::Simplifiable; + // If we have fileSystemExt, we defer to that + if (m_fileSystemExt) + { + // We just defer to the m_fileSystem + m_pathStyle = PathStyle::FileSystemExt; + } } // It can't be default SLANG_ASSERT(m_uniqueIdentityMode != UniqueIdentityMode::Default); } -CacheFileSystem::~CacheFileSystem() -{ - for (const auto& pair : m_uniqueIdentityMap) - { - delete pair.Value; - } -} - void CacheFileSystem::clearCache() { for (const auto& pair : m_uniqueIdentityMap) @@ -450,14 +460,17 @@ SlangResult CacheFileSystem::getFileUniqueIdentity(const char* path, ISlangBlob* SlangResult CacheFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) { // Just defer to contained implementation - if (m_fileSystemExt) - { - return m_fileSystemExt->calcCombinedPath(fromPathType, fromPath, path, pathOut); - } - else + switch (m_pathStyle) { - // Just use the default implementation - return _calcCombinedPath(fromPathType, fromPath, path, pathOut); + case PathStyle::FileSystemExt: + { + return m_fileSystemExt->calcCombinedPath(fromPathType, fromPath, path, pathOut); + } + default: + { + // Just use the default implementation + return _calcCombinedPath(fromPathType, fromPath, path, pathOut); + } } } @@ -498,34 +511,24 @@ SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* path SlangResult CacheFileSystem::getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath) { // If we have a ISlangFileSystemExt we can just pass on the request to it - if (m_fileSystemExt) + switch (m_pathStyle) { - return m_fileSystemExt->getSimplifiedPath(path, outSimplifiedPath); - } - else - { - // Use the path style to see what we can do with it - switch (m_pathStyle) + case PathStyle::FileSystemExt: { - case PathStyle::Simplifiable: - { - String simplifiedPath = Path::simplify(_fixPathDelimiters(path)); - *outSimplifiedPath = StringUtil::createStringBlob(simplifiedPath).detach(); - return SLANG_OK; - } - default: return SLANG_E_NOT_IMPLEMENTED; + return m_fileSystemExt->getSimplifiedPath(path, outSimplifiedPath); } + case PathStyle::Simplifiable: + { + String simplifiedPath = Path::simplify(_fixPathDelimiters(path)); + *outSimplifiedPath = StringUtil::createStringBlob(simplifiedPath).detach(); + return SLANG_OK; + } + default: return SLANG_E_NOT_IMPLEMENTED; } } SlangResult CacheFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) { - // If we don't have a backing full file system, we can't produce a canonical path with just ISlangFileSystem::loadFile - if (!m_fileSystemExt) - { - return SLANG_E_NOT_IMPLEMENTED; - } - // A file must exist to get a canonical path... PathInfo* info = _resolvePathCacheInfo(path); if (!info) @@ -536,6 +539,11 @@ SlangResult CacheFileSystem::getCanonicalPath(const char* path, ISlangBlob** out // We don't have this -> so read it ... if (info->m_getCanonicalPathResult == CompressedResult::Uninitialized) { + if (!m_fileSystemExt) + { + return SLANG_E_NOT_IMPLEMENTED; + } + // Try getting the canonicalPath by asking underlying file system ComPtr<ISlangBlob> canonicalPathBlob; SlangResult res = m_fileSystemExt->getCanonicalPath(path, canonicalPathBlob.writeRef()); @@ -576,7 +584,15 @@ ISlangUnknown* RelativeFileSystem::getInterface(const Guid& guid) SlangResult RelativeFileSystem::_getFixedPath(const char* path, String& outPath) { ComPtr<ISlangBlob> blob; - SLANG_RETURN_ON_FAIL(m_fileSystem->calcCombinedPath(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), path, blob.writeRef())); + if (m_stripPath) + { + String strippedPath = Path::getFileName(path); + SLANG_RETURN_ON_FAIL(m_fileSystem->calcCombinedPath(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), strippedPath.getBuffer(), blob.writeRef())); + } + else + { + SLANG_RETURN_ON_FAIL(m_fileSystem->calcCombinedPath(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), path, blob.writeRef())); + } outPath = StringUtil::getString(blob); return SLANG_OK; diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h index 71596be5b..3d2bfe3c1 100644 --- a/source/slang/slang-file-system.h +++ b/source/slang/slang-file-system.h @@ -117,8 +117,8 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject enum class PathStyle { Default, ///< Pass to say use the default - Unknown, ///< It's an unknown type of path Simplifiable, ///< It can be simplified by Path::Simplify + FileSystemExt, ///< Use file system }; enum UniqueIdentityMode @@ -216,6 +216,14 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject return SLANG_E_NOT_IMPLEMENTED; } + /// Get the unique identity mode + UniqueIdentityMode getUniqueIdentityMode() const { return m_uniqueIdentityMode; } + /// Get the path style + PathStyle getPathStyle() const { return m_pathStyle; } + + /// Set the inner file system + void setInnerFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default, PathStyle pathStyle = PathStyle::Default); + /// Ctor CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode = UniqueIdentityMode::Default, PathStyle pathStyle = PathStyle::Default); /// Dtor @@ -291,9 +299,10 @@ public: virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE; - RelativeFileSystem(ISlangFileSystemExt* fileSystem, const String& relativePath): + RelativeFileSystem(ISlangFileSystemExt* fileSystem, const String& relativePath, bool stripPath = false): m_fileSystem(fileSystem), - m_relativePath(relativePath) + m_relativePath(relativePath), + m_stripPath(stripPath) { } @@ -303,6 +312,8 @@ protected: ISlangUnknown* getInterface(const Guid& guid); + bool m_stripPath; + ComPtr<ISlangFileSystemExt> m_fileSystem; String m_relativePath; }; diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index b17e35d69..ad1d27114 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -563,6 +563,39 @@ struct OptionsParser return SLANG_OK; } + else if (argStr == "-repro-file-system") + { + String reproName; + SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, reproName)); + + List<uint8_t> buffer; + SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(reproName, buffer)); + + auto requestState = StateSerializeUtil::getRequest(buffer); + MemoryOffsetBase base; + base.set(buffer.getBuffer(), buffer.getCount()); + + // If we can find a directory, that exists, we will set up a file system to load from that directory + ComPtr<ISlangFileSystem> dirFileSystem; + String dirPath; + if (SLANG_SUCCEEDED(StateSerializeUtil::calcDirectoryPathFromFilename(reproName, dirPath))) + { + SlangPathType pathType; + if (SLANG_SUCCEEDED(Path::getPathType(dirPath, &pathType)) && pathType == SLANG_PATH_TYPE_DIRECTORY) + { + dirFileSystem = new RelativeFileSystem(OSFileSystemExt::getSingleton(), dirPath, true); + } + } + + RefPtr<CacheFileSystem> cacheFileSystem; + SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadFileSystem(base, requestState, dirFileSystem, cacheFileSystem)); + + // I might want to make the dir file system the fallback file system... + cacheFileSystem->setInnerFileSystem(dirFileSystem, cacheFileSystem->getUniqueIdentityMode(), cacheFileSystem->getPathStyle()); + + // Set as the file system + spSetFileSystem(compileRequest, cacheFileSystem); + } else if (argStr == "-serial-ir") { requestImpl->getFrontEndReq()->useSerialIRBottleneck = true; diff --git a/source/slang/slang-state-serialize.cpp b/source/slang/slang-state-serialize.cpp index c373c5fcc..369c433ca 100644 --- a/source/slang/slang-state-serialize.cpp +++ b/source/slang/slang-state-serialize.cpp @@ -631,16 +631,18 @@ struct LoadContext typedef StateSerializeUtil::FileState FileState; typedef StateSerializeUtil::PathInfoState PathInfoState; - ISlangBlob* getFileBlob(FileState* file) + CacheFileSystem::PathInfo* getPathInfoFromFile(FileState* file) { if (!file) { return nullptr; } - ComPtr<ISlangBlob> blob; - if (!m_fileToBlobMap.TryGetValue(file, blob)) + CacheFileSystem::PathInfo* dstInfo = nullptr; + if (!m_fileToPathInfoMap.TryGetValue(file, dstInfo)) { + ComPtr<ISlangBlob> blob; + if (m_fileSystem && file->uniqueName) { // Try loading from the file system @@ -653,11 +655,39 @@ struct LoadContext blob = new StringBlob(m_base->asRaw(file->contents)->getSlice()); } + dstInfo = new CacheFileSystem::PathInfo(String()); + + if (file->uniqueIdentity) + { + String uniqueIdentity = m_base->asRaw(file->uniqueIdentity)->getSlice(); + dstInfo->m_uniqueIdentity = new StringBlob(uniqueIdentity); + } + + if (file->canonicalPath) + { + dstInfo->m_canonicalPath = new StringBlob(m_base->asRaw(file->canonicalPath)->getSlice()); + } + + if (blob) + { + dstInfo->m_loadFileResult = CacheFileSystem::CompressedResult::Ok; + dstInfo->m_getPathTypeResult = CacheFileSystem::CompressedResult::Ok; + dstInfo->m_pathType = SLANG_PATH_TYPE_FILE; + } + + dstInfo->m_fileBlob = blob; + // Add to map, even if the blob is nullptr (say from a failed read) - m_fileToBlobMap.Add(file, blob); + m_fileToPathInfoMap.Add(file, dstInfo); } - return blob; + return dstInfo; + } + + ISlangBlob* getFileBlobFromFile(FileState* file) + { + CacheFileSystem::PathInfo* pathInfo = getPathInfoFromFile(file); + return pathInfo ? pathInfo->m_fileBlob.get() : nullptr; } SourceFile* getSourceFile(SourceFileState* sourceFile) @@ -671,7 +701,7 @@ struct LoadContext if (!m_sourceFileMap.TryGetValue(sourceFile, dstFile)) { FileState* file = m_base->asRaw(sourceFile->file); - ISlangBlob* blob = getFileBlob(file); + ISlangBlob* blob = getFileBlobFromFile(file); PathInfo pathInfo; @@ -711,22 +741,18 @@ struct LoadContext return pathInfo; } - CacheFileSystem::PathInfo* dstInfo = new CacheFileSystem::PathInfo(String()); FileState* file = m_base->asRaw(srcInfo->file); + CacheFileSystem::PathInfo* dstInfo; + if (file) { - if (file->uniqueIdentity) - { - String uniqueIdentity = m_base->asRaw(file->uniqueIdentity)->getSlice(); - dstInfo->m_uniqueIdentity = new StringBlob(uniqueIdentity); - } - - if (file->canonicalPath) - { - dstInfo->m_canonicalPath = new StringBlob(m_base->asRaw(file->canonicalPath)->getSlice()); - } - - dstInfo->m_fileBlob = getFileBlob(file); + dstInfo = getPathInfoFromFile(file); + } + else + { + // TODO(JS): Hmmm... this could end up not being cleared up + // Because it is not added to the unique set (as unique set is for files and this isn't a file) + dstInfo = new CacheFileSystem::PathInfo(String()); } dstInfo->m_getCanonicalPathResult = srcInfo->getCanonicalPathResult; @@ -773,14 +799,67 @@ struct LoadContext OffsetBase* m_base; SourceManager* m_sourceManager; + Dictionary<SourceFileState*, SourceFile*> m_sourceFileMap; - Dictionary<FileState*, ComPtr<ISlangBlob> > m_fileToBlobMap; + Dictionary<FileState*, CacheFileSystem::PathInfo*> m_fileToPathInfoMap; Dictionary<const PathInfoState*, CacheFileSystem::PathInfo*> m_pathInfoMap; }; } // anonymous +/* static */SlangResult StateSerializeUtil::loadFileSystem(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, RefPtr<CacheFileSystem>& outFileSystem) +{ + LoadContext context(nullptr, fileSystem, &base); + + RefPtr<CacheFileSystem> cacheFileSystem = new CacheFileSystem(nullptr); + auto& dstUniqueMap = cacheFileSystem->getUniqueMap(); + auto& dstPathMap = cacheFileSystem->getPathMap(); + + for (auto fileOffset : requestState->files) + { + // add the file + FileState* fileState = base.asRaw(base.asRaw(fileOffset)); + CacheFileSystem::PathInfo* pathInfo = context.getPathInfoFromFile(fileState); + + if (fileState->foundPath) + { + String foundPath = base.asRaw(fileState->foundPath)->getSlice(); + dstPathMap.AddIfNotExists(foundPath, pathInfo); + } + } + + // Put all the paths to path info + { + for (const auto& pairOffset : requestState->pathInfoMap) + { + const auto& pair = base.asRaw(pairOffset); + CacheFileSystem::PathInfo* pathInfo = context.addPathInfo(base.asRaw(pair.pathInfo)); + dstPathMap.AddIfNotExists(base.asRaw(pair.path)->getSlice(), pathInfo); + } + } + + // Put all the path infos in the cache system + { + for (const auto& pair : context.m_fileToPathInfoMap) + { + CacheFileSystem::PathInfo* pathInfo = pair.Value; + SLANG_ASSERT(pathInfo->m_uniqueIdentity); + dstUniqueMap.Add(pathInfo->m_uniqueIdentity->getString(), pathInfo); + + // Add canonical paths too.. + if (pathInfo->m_canonicalPath) + { + String canonicalPath = pathInfo->m_canonicalPath->getString(); + + dstPathMap.AddIfNotExists(canonicalPath, pathInfo); + } + } + } + + outFileSystem = cacheFileSystem; + return SLANG_OK; +} /* static */SlangResult StateSerializeUtil::load(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, EndToEndCompileRequest* request) { @@ -947,7 +1026,7 @@ struct LoadContext } // Put all the path infos in the cache system { - for (const auto& pair : context.m_pathInfoMap) + for (const auto& pair : context.m_fileToPathInfoMap) { CacheFileSystem::PathInfo* pathInfo = pair.Value; SLANG_ASSERT(pathInfo->m_uniqueIdentity); @@ -1076,6 +1155,21 @@ struct LoadContext return extractFiles(base, requestState, &relFileSystem); } +static void _calcPreprocessorDefines(OffsetBase& base, const Offset32Array<StateSerializeUtil::StringPair>& srcDefines, CommandLine& cmd) +{ + for (const auto& define : srcDefines) + { + StringBuilder builder; + builder << "-D" << base.asRaw(base.asRaw(define).first)->getSlice(); + if (base.asRaw(define).second) + { + builder << "=" << base.asRaw(base.asRaw(define).second)->getSlice(); + } + + cmd.addArg(builder); + } +} + static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::RequestState* requestState, CommandLine& cmd) { typedef StateSerializeUtil::TargetRequestState TargetRequestState; @@ -1086,15 +1180,17 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques while (flags) { // Extract a bit - SlangCompileFlags newFlags = flags & (flags - 1); - SlangCompileFlags flag = newFlags ^ flags; + const SlangCompileFlags isolatedBit = flags & SlangCompileFlags(-int(flags)); - switch (flag) + switch (isolatedBit) { case SLANG_COMPILE_FLAG_NO_MANGLING: cmd.addArg("-no-mangle"); break; case SLANG_COMPILE_FLAG_NO_CODEGEN: cmd.addArg("-no-codegen"); break; default: break; } + + // Remove the bit + flags &= ~isolatedBit; } //spSetDumpIntermediates(externalRequest, int(requestState->shouldDumpIntermediates)); @@ -1220,17 +1316,7 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques } } - { - for (const auto& define : requestState->preprocessorDefinitions) - { - StringBuilder builder; - builder << "-D" << base.asRaw(base.asRaw(define).first)->getSlice(); - if (base.asRaw(define).second) - { - builder << "=" << base.asRaw(base.asRaw(define).second)->getSlice(); - } - } - } + _calcPreprocessorDefines(base, requestState->preprocessorDefinitions, cmd); { const auto& srcTranslationUnits = requestState->translationUnits; @@ -1239,8 +1325,9 @@ static SlangResult _calcCommandLine(OffsetBase& base, StateSerializeUtil::Reques { const auto& srcTranslationUnit = base.asRaw(srcTranslationUnits[i]); - //context.loadDefines(srcTranslationUnit.preprocessorDefinitions, dstTranslationUnit->preprocessorDefinitions); + _calcPreprocessorDefines(base, srcTranslationUnit.preprocessorDefinitions, cmd); + #if 0 if (srcTranslationUnit.moduleName) { diff --git a/source/slang/slang-state-serialize.h b/source/slang/slang-state-serialize.h index 1a4c9b227..9a404138e 100644 --- a/source/slang/slang-state-serialize.h +++ b/source/slang/slang-state-serialize.h @@ -163,6 +163,10 @@ struct StateSerializeUtil static SlangResult saveState(EndToEndCompileRequest* request, Stream* stream); + /// Create a cache file system that uses contents of the request state. + /// The passed in fileSystem is used for accessing any file accesses not found in the cache + static SlangResult loadFileSystem(OffsetBase& base, RequestState* requestState, ISlangFileSystem* fileSystem, RefPtr<CacheFileSystem>& outFileSystem); + /// Load the requestState into request /// The fileSystem is optional and can be passed as nullptr. If set, as each file is loaded /// it will attempt to load from fileSystem the *uniqueName* diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index c7171d835..946d7337b 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -3574,6 +3574,33 @@ SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproDat return StateSerializeUtil::extractFiles(base, requestState, fileSystem); } +SLANG_API SlangResult spLoadReproAsFileSystem( + SlangSession* session, + const void* reproData, + size_t reproDataSize, + ISlangFileSystem* replaceFileSystem, + ISlangFileSystemExt** outFileSystem) +{ + using namespace Slang; + + SLANG_UNUSED(session); + + MemoryStreamBase stream(FileAccess::Read, reproData, reproDataSize); + + List<uint8_t> buffer; + SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(&stream, buffer)); + + auto requestState = StateSerializeUtil::getRequest(buffer); + MemoryOffsetBase base; + base.set(buffer.getBuffer(), buffer.getCount()); + + RefPtr<CacheFileSystem> cacheFileSystem; + SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadFileSystem(base, requestState, replaceFileSystem, cacheFileSystem)); + + *outFileSystem = cacheFileSystem.detach(); + return SLANG_OK; +} + // Reflection API SLANG_API SlangResult spCompileRequest_getProgram( |
