diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-18 15:16:15 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-18 15:16:15 -0700 |
| commit | 7f6e95917bb1929115b4cffa2ed9035aa8710ee4 (patch) | |
| tree | 8a84264fe3d7e0c103c5a69446d3b3059f1d52da | |
| parent | 2d41012ed2649093a58433eae60419d24073da90 (diff) | |
Fix name mangling and source file finding logic for precompiled module validation. (#3784)
* Fix name mangling.
* Fix source validation.
* Caching and search path fixes.
| -rwxr-xr-x | source/slang/slang-compiler.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-mangle.cpp | 18 | ||||
| -rw-r--r-- | source/slang/slang-serialize-container.cpp | 81 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 33 |
4 files changed, 113 insertions, 25 deletions
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index c23eddfde..14d4054c4 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1389,6 +1389,9 @@ namespace Slang virtual void buildHash(DigestBuilder<SHA1>& builder) SLANG_OVERRIDE; + void setDigest(SHA1::Digest const& digest) { m_digest = digest; } + SHA1::Digest computeDigest(); + /// Create a module (initially empty). Module(Linkage* linkage, ASTBuilder* astBuilder = nullptr); @@ -1509,6 +1512,9 @@ namespace Slang List<Module*> m_requirements; + // A digest that uniquely identifies the contents of the module. + SHA1::Digest m_digest; + // List of modules this module depends on ModuleDependencyList m_moduleDependencyList; diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp index 9431533ac..d72644c9f 100644 --- a/source/slang/slang-mangle.cpp +++ b/source/slang/slang-mangle.cpp @@ -260,6 +260,12 @@ namespace Slang for (Index i = 0; i < n; ++i) emitVal(context, modifiedType->getModifier(i)); } + else if (auto andType = as<AndType>(type)) + { + emitRaw(context, "Ta"); + emitType(context, andType->getLeft()); + emitType(context, andType->getRight()); + } else { SLANG_UNEXPECTED("unimplemented case in type mangling"); @@ -601,10 +607,18 @@ namespace Slang emitQualifiedName(context, makeDeclRef(innerDecl), true); return; } - else if (as<ForwardDerivativeRequirementDecl>(decl)) + else if (auto fwdReq = as<ForwardDerivativeRequirementDecl>(decl)) + { emitRaw(context, "FwdReq_"); - else if (as<BackwardDerivativeRequirementDecl>(decl)) + emitQualifiedName(context, fwdReq->originalRequirementDecl, true); + return; + } + else if (auto bwdReq = as<BackwardDerivativeRequirementDecl>(decl)) + { emitRaw(context, "BwdReq_"); + emitQualifiedName(context, bwdReq->originalRequirementDecl, true); + return; + } else { // TODO: handle other cases diff --git a/source/slang/slang-serialize-container.cpp b/source/slang/slang-serialize-container.cpp index f1efc7b93..2378050e6 100644 --- a/source/slang/slang-serialize-container.cpp +++ b/source/slang/slang-serialize-container.cpp @@ -80,31 +80,84 @@ namespace Slang { dstModule.irModule = module->getIRModule(); SLANG_ASSERT(dstModule.irModule); } - DigestBuilder<SHA1> digestBuilder; - auto version = String(getBuildTagString()); - digestBuilder.append(version); - module->getOptionSet().buildHash(digestBuilder); + + // Here we assume that the first file in the file dependencies is the module's file path. + // We store the module's file path as a relative path with respect to the first search + // directory that contains the module, and store the paths of dependent files as relative + // paths with respect to the module's path. + + // First, we try to extract the module's main file path from the file dependency list. auto fileDependencies = module->getFileDependencies(); String canonicalModulePath, moduleDir; - if (auto modulePath = module->getFilePath()) + if (fileDependencies.getCount() != 0) + { + IncludeSystem includeSystem( + &module->getLinkage()->getSearchDirectories(), + module->getLinkage()->getFileSystemExt(), + module->getLinkage()->getSourceManager()); + PathInfo outFoundSourcePath; + // If we can find the first file, use that as the module's path. + if (SLANG_SUCCEEDED(includeSystem.findFile(fileDependencies[0]->getPathInfo().foundPath, "", outFoundSourcePath))) + { + canonicalModulePath = outFoundSourcePath.foundPath; + Path::getCanonical(canonicalModulePath, canonicalModulePath); + moduleDir = Path::getParentDirectory(canonicalModulePath); + } + } + + // If we can't find the module's path from the file dependencies list above, + // use the file path stored on the module as a fallback. + // Note that if the module is loaded from a binary precompiled module, + // this path will be pointing to that binary file instead of the original source file. + if (!canonicalModulePath.getLength()) { - canonicalModulePath = modulePath; - Path::getCanonical(canonicalModulePath, canonicalModulePath); - moduleDir = Path::getParentDirectory(canonicalModulePath); + if (auto modulePath = module->getFilePath()) + { + canonicalModulePath = modulePath; + Path::getCanonical(canonicalModulePath, canonicalModulePath); + moduleDir = Path::getParentDirectory(canonicalModulePath); + } } + + // Find the first search directory that contains the module's main file path, + // so we can store the module's path (the first entry in the dependent files list) + // as a relative path with respect to that directory. + + String linkageRoot = "."; + if (auto linkage = module->getLinkage()) + { + for (const auto& searchDir : linkage->getSearchDirectories().searchDirectories) + { + String fullSearchDir; + Path::getCanonical(searchDir.path, fullSearchDir); + String relativePath = Path::getRelativePath(fullSearchDir, canonicalModulePath); + if (!Path::hasRelativeElement(relativePath)) + { + linkageRoot = searchDir.path; + break; + } + } + } + Path::getCanonical(linkageRoot, linkageRoot); + for (auto file : fileDependencies) { - digestBuilder.append(file->getDigest()); if (file->getPathInfo().hasFoundPath()) { - if (file->getPathInfo().foundPath == canonicalModulePath) + String canonicalFilePath = file->getPathInfo().foundPath; + Path::getCanonical(file->getPathInfo().foundPath, canonicalFilePath); + + // If the dependnet file is the same as the module's file path, store it as a relative path + // with respect to the search directory discovered above. + if (canonicalFilePath == canonicalModulePath) { - dstModule.dependentFiles.add(Path::getFileName(canonicalModulePath)); + auto relativeModulePath = Path::getRelativePath(linkageRoot, canonicalModulePath); + dstModule.dependentFiles.add(relativeModulePath); } else { - String canonicalFilePath = file->getPathInfo().foundPath; - Path::getCanonical(file->getPathInfo().foundPath, canonicalFilePath); + // For all other dependnet files, store them as relative paths with respect + // to the module's path. canonicalFilePath = Path::getRelativePath(moduleDir, canonicalFilePath); dstModule.dependentFiles.add(canonicalFilePath); } @@ -114,7 +167,7 @@ namespace Slang { dstModule.dependentFiles.add(file->getPathInfo().getMostUniqueIdentity()); } } - dstModule.digest = digestBuilder.finalize(); + dstModule.digest = module->computeDigest(); outData.modules.add(dstModule); } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 978dff7c4..241ec7f43 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -486,6 +486,7 @@ SlangResult Session::_readBuiltinModule(ISlangFileSystem* fileSystem, Scope* sco { RefPtr<Module> module(new Module(linkage, srcModule.astBuilder)); module->setName(moduleName); + module->setDigest(srcModule.digest); ModuleDecl* moduleDecl = as<ModuleDecl>(srcModule.astRootNode); // Set the module back reference on the decl @@ -3699,7 +3700,7 @@ bool Linkage::isBinaryModuleUpToDate(String fromPath, RiffContainer* container) // If we cannot find the source file from `fromPath`, // try again from the module's source file path. if (moduleHeader.dependentFiles.getCount() != 0) - sourceFile = loadSourceFile(moduleHeader.dependentFiles.getFirst(), file); + sourceFile = loadSourceFile(Path::getParentDirectory(moduleHeader.dependentFiles.getFirst()), file); } if (!sourceFile) return false; @@ -3922,7 +3923,27 @@ ISlangUnknown* Module::getInterface(const Guid& guid) void Module::buildHash(DigestBuilder<SHA1>& builder) { - SLANG_UNUSED(builder); + builder.append(computeDigest()); +} + +SHA1::Digest Module::computeDigest() +{ + if (m_digest == SHA1::Digest()) + { + DigestBuilder<SHA1> digestBuilder; + auto version = String(getBuildTagString()); + digestBuilder.append(version); + getOptionSet().buildHash(digestBuilder); + + auto fileDependencies = getFileDependencies(); + + for (auto file : fileDependencies) + { + digestBuilder.append(file->getDigest()); + } + m_digest = digestBuilder.finalize(); + } + return m_digest; } void Module::addModuleDependency(Module* module) @@ -4245,12 +4266,6 @@ SLANG_NO_THROW void SLANG_MCALL ComponentType::getEntryPointHash( // will already be reflected in the resulting hash. getLinkage()->buildHash(builder, targetIndex); - // Enumerate all file dependencies and add them to the hash. - for (SourceFile* sourceFile : getFileDependencies()) - { - builder.append(sourceFile->getDigest()); - } - buildHash(builder); // Add the name and name override for the specified entry point to the hash. @@ -5239,7 +5254,7 @@ void Linkage::prepareDeserializedModule(SerialContainerData::Module& moduleEntry } } module->setPathInfo(filePathInfo); - + module->setDigest(moduleEntry.digest); module->_collectShaderParams(); module->_discoverEntryPoints(sink); |
