Serialization: apply the SDK build version as part of the cache hash

The SDK build version is a decent heuristic for expected changes in the
SDK. Any change in SDK, to clang headers in particular, can break
references from cached swiftmodules.

Track the SDK build version as part of the swiftmodule cache hash. This
will ensure we rebuild from swiftinterfaces on SDK updates.

rdar://122655978
This commit is contained in:
Alexis Laferrière
2024-02-12 11:09:18 -08:00
parent 8bb6846285
commit 86ea594f21
7 changed files with 108 additions and 12 deletions

View File

@@ -1064,6 +1064,7 @@ class ModuleInterfaceLoaderImpl {
llvm::SmallString<256> cachedOutputPath;
StringRef CacheHash;
astDelegate.computeCachedOutputPath(moduleName, interfacePath,
ctx.SearchPathOpts.getSDKPath(),
cachedOutputPath, CacheHash);
// Try to find the right module for this interface, either alongside it,
@@ -1144,7 +1145,9 @@ class ModuleInterfaceLoaderImpl {
Identifier realName = ctx.getRealModuleName(ctx.getIdentifier(moduleName));
ImplicitModuleInterfaceBuilder builder(
ctx.SourceMgr, diagsToUse,
astDelegate, interfacePath, realName.str(), cacheDir,
astDelegate, interfacePath,
ctx.SearchPathOpts.getSDKPath(),
realName.str(), cacheDir,
prebuiltCacheDir, backupInterfaceDir, StringRef(),
Opts.disableInterfaceLock,
ctx.IgnoreAdjacentModules, diagnosticLoc,
@@ -1177,7 +1180,9 @@ class ModuleInterfaceLoaderImpl {
// Set up a builder if we need to build the module. It'll also set up
// the genericSubInvocation we'll need to use to compute the cache paths.
ImplicitModuleInterfaceBuilder fallbackBuilder(
ctx.SourceMgr, &ctx.Diags, astDelegate, backupPath, moduleName, cacheDir,
ctx.SourceMgr, &ctx.Diags, astDelegate, backupPath,
ctx.SearchPathOpts.getSDKPath(),
moduleName, cacheDir,
prebuiltCacheDir, backupInterfaceDir, StringRef(),
Opts.disableInterfaceLock,
ctx.IgnoreAdjacentModules, diagnosticLoc,
@@ -1390,6 +1395,7 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
SerializeDependencyHashes, TrackSystemDependencies,
RequireOSSAModules, RequireNCGenerics);
ImplicitModuleInterfaceBuilder builder(SourceMgr, &Diags, astDelegate, InPath,
SearchPathOpts.getSDKPath(),
ModuleName, CacheDir, PrebuiltCacheDir,
BackupInterfaceDir, ABIOutputPath,
LoaderOpts.disableInterfaceLock,
@@ -1409,6 +1415,7 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
assert(failed);
assert(!backInPath.empty());
ImplicitModuleInterfaceBuilder backupBuilder(SourceMgr, &Diags, astDelegate, backInPath,
SearchPathOpts.getSDKPath(),
ModuleName, CacheDir, PrebuiltCacheDir,
BackupInterfaceDir, ABIOutputPath,
LoaderOpts.disableInterfaceLock,
@@ -1865,13 +1872,14 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
StringRef moduleName,
StringRef useInterfacePath,
StringRef sdkPath,
llvm::SmallString<256> &OutPath,
StringRef &CacheHash) {
OutPath = genericSubInvocation.getClangModuleCachePath();
llvm::sys::path::append(OutPath, moduleName);
OutPath.append("-");
auto hashStart = OutPath.size();
OutPath.append(getCacheHash(useInterfacePath));
OutPath.append(getCacheHash(useInterfacePath, sdkPath));
CacheHash = OutPath.str().substr(hashStart);
OutPath.append(".");
auto OutExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
@@ -1890,9 +1898,11 @@ StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
/// with dead entries -- when other factors change, such as the contents of
/// the .swiftinterface input or its dependencies.
std::string
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
StringRef sdkPath) {
auto normalizedTargetTriple =
getTargetSpecificModuleTriple(genericSubInvocation.getLangOptions().Target);
std::string sdkBuildVersion = getSDKBuildVersion(sdkPath);
llvm::hash_code H = hash_combine(
// Start with the compiler version (which will be either tag names or
@@ -1918,6 +1928,10 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
// include it.
genericSubInvocation.getSDKPath(),
// The SDK build version may identify differences in headers
// that affects references serialized in the cached file.
sdkBuildVersion,
// Whether or not we're tracking system dependencies affects the
// invalidation behavior of this cache item.
genericSubInvocation.getFrontendOptions().shouldTrackSystemDependencies(),
@@ -1934,11 +1948,12 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
std::error_code
InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
StringRef interfacePath,
StringRef sdkPath,
StringRef outputPath,
SourceLoc diagLoc,
llvm::function_ref<std::error_code(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
ArrayRef<StringRef>, StringRef)> action) {
return runInSubCompilerInstance(moduleName, interfacePath, outputPath,
return runInSubCompilerInstance(moduleName, interfacePath, sdkPath, outputPath,
diagLoc, /*silenceErrors=*/false,
[&](SubCompilerInstanceInfo &info){
return action(info.Instance->getASTContext(),
@@ -1952,6 +1967,7 @@ InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
std::error_code
InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
StringRef interfacePath,
StringRef sdkPath,
StringRef outputPath,
SourceLoc diagLoc,
bool silenceErrors,
@@ -1981,8 +1997,8 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
// Calculate output path of the module.
llvm::SmallString<256> buffer;
StringRef CacheHash;
auto hashedOutput = computeCachedOutputPath(moduleName, interfacePath, buffer,
CacheHash);
auto hashedOutput = computeCachedOutputPath(moduleName, interfacePath,
sdkPath, buffer, CacheHash);
// If no specific output path is given, use the hashed output path.
if (outputPath.empty()) {
outputPath = hashedOutput;