summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-03-18 15:16:15 -0700
committerGitHub <noreply@github.com>2024-03-18 15:16:15 -0700
commit7f6e95917bb1929115b4cffa2ed9035aa8710ee4 (patch)
tree8a84264fe3d7e0c103c5a69446d3b3059f1d52da
parent2d41012ed2649093a58433eae60419d24073da90 (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-xsource/slang/slang-compiler.h6
-rw-r--r--source/slang/slang-mangle.cpp18
-rw-r--r--source/slang/slang-serialize-container.cpp81
-rw-r--r--source/slang/slang.cpp33
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);