Skip to content

Commit cd6066d

Browse files
committed
Refactoring swift interface module's output path calculation to use new code.
1 parent 8055c1d commit cd6066d

File tree

3 files changed

+128
-169
lines changed

3 files changed

+128
-169
lines changed

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,44 @@ struct SwiftInterfaceInfo {
628628
std::optional<version::Version> CompilerToolsVersion;
629629
};
630630

631-
struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
631+
class InterfaceModuleNameExpander {
632+
public:
633+
using ArgListTy = std::vector<std::string>;
634+
struct ResultTy {
635+
llvm::SmallString<256> outputPath;
636+
637+
// Hash points to a segment of outputPath.
638+
StringRef hash;
639+
};
640+
641+
private:
642+
const StringRef moduleName;
643+
const StringRef interfacePath;
644+
const StringRef sdkPath;
645+
const CompilerInvocation &CI;
646+
647+
// This field contains the clang ExtraArgs that affect how clang types are
648+
// imported into swift module. See the constructor for how this field is set,
649+
// and see pruneExtraArgs to see how it can be updated.
650+
ArgListTy extraArgs;
651+
652+
std::unique_ptr<ResultTy> expandedName;
653+
654+
std::string getHash();
655+
656+
public:
657+
InterfaceModuleNameExpander(const StringRef moduleName,
658+
const StringRef interfacePath,
659+
const StringRef sdkPath,
660+
const CompilerInvocation &CI)
661+
: moduleName(moduleName), interfacePath(interfacePath), sdkPath(sdkPath),
662+
CI(CI), extraArgs(CI.getClangImporterOptions()
663+
.getReducedExtraArgsForSwiftModuleDependency()) {}
664+
ResultTy getExpandedName();
665+
void pruneExtraArgs(std::function<void(ArgListTy &)> filter);
666+
};
667+
668+
struct InterfaceSubContextDelegateImpl : InterfaceSubContextDelegate {
632669
private:
633670
SourceManager &SM;
634671
public:
@@ -703,48 +740,10 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
703740
~InterfaceSubContextDelegateImpl() = default;
704741

705742
/// includes a hash of relevant key data.
706-
StringRef computeCachedOutputPath(StringRef moduleName,
707-
StringRef UseInterfacePath,
708-
StringRef sdkPath,
709-
llvm::SmallString<256> &OutPath,
710-
StringRef &CacheHash);
711-
std::string getCacheHash(StringRef useInterfacePath, StringRef sdkPath);
743+
InterfaceModuleNameExpander::ResultTy
744+
getCachedOutputPath(StringRef moduleName, StringRef interfacePath,
745+
StringRef sdkPath);
712746
};
713-
714-
class InterfaceModuleNameExpander {
715-
public:
716-
using ArgListTy = std::vector<std::string>;
717-
struct ResultTy {
718-
llvm::SmallString<256> outputPath;
719-
720-
// Hash points to a segment of outputPath.
721-
StringRef hash;
722-
};
723-
724-
private:
725-
const StringRef moduleName;
726-
const StringRef interfacePath;
727-
const StringRef sdkPath;
728-
const CompilerInvocation &CI;
729-
ArgListTy extraArgs;
730-
731-
ResultTy expandedName;
732-
733-
bool expanded = false;
734-
735-
std::string getHash();
736-
737-
public:
738-
InterfaceModuleNameExpander(const StringRef moduleName,
739-
const StringRef interfacePath,
740-
const StringRef sdkPath,
741-
const CompilerInvocation &CI)
742-
: moduleName(moduleName), interfacePath(interfacePath), sdkPath(sdkPath),
743-
CI(CI), extraArgs(CI.getClangImporterOptions()
744-
.getReducedExtraArgsForSwiftModuleDependency()) {}
745-
ResultTy getExpandedName();
746-
void pruneExtraArgs(std::function<void(ArgListTy &)> filter);
747-
};
748-
}
747+
} // namespace swift
749748

750749
#endif

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ class ExplicitModuleDependencyResolver {
180180

181181
pruneUnusedVFSOverlay();
182182

183+
// It is necessary to update the command line to take
184+
// the pruned unused VFS overlay into account before remapping the
185+
// command line.
183186
if (resolvingDepInfo.isSwiftInterfaceModule())
184187
updateSwiftInterfaceCommandLine();
185188

@@ -453,13 +456,14 @@ class ExplicitModuleDependencyResolver {
453456
}
454457

455458
void updateSwiftInterfaceCommandLine() {
456-
// The command line needs upadte once we prune the unused VFS overlays.
459+
// The command line needs update once we prune the unused VFS overlays.
457460
// The update consists of two steps.
458-
// 1. Recompute the output path, which includes the module hash.
461+
// 1. Obtain the output path, which includes the module hash that takes the
462+
// VFS pruning into account.
459463
// 2. Update `-o `'s value on the command line with the new output path.
460464

461465
assert(nameExpander && "Can only update if we hae a nameExpander.");
462-
auto expandedName = nameExpander->getExpandedName();
466+
const auto &expandedName = nameExpander->getExpandedName();
463467

464468
StringRef outputName = expandedName.outputPath.str();
465469

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 79 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,11 +1098,9 @@ class ModuleInterfaceLoaderImpl {
10981098
requiresOSSAModules);
10991099

11001100
// Compute the output path if we're loading or emitting a cached module.
1101-
llvm::SmallString<256> cachedOutputPath;
1102-
StringRef CacheHash;
1103-
astDelegate.computeCachedOutputPath(moduleName, interfacePath,
1104-
ctx.SearchPathOpts.getSDKPath(),
1105-
cachedOutputPath, CacheHash);
1101+
auto expandedName = astDelegate.getCachedOutputPath(
1102+
moduleName, interfacePath, ctx.SearchPathOpts.getSDKPath());
1103+
auto &cachedOutputPath = expandedName.outputPath;
11061104

11071105
// Try to find the right module for this interface, either alongside it,
11081106
// in the cache, or in the prebuilt cache.
@@ -2007,110 +2005,13 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
20072005

20082006
/// Calculate an output filename in \p genericSubInvocation's cache path that
20092007
/// includes a hash of relevant key data.
2010-
StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
2011-
StringRef moduleName,
2012-
StringRef useInterfacePath,
2013-
StringRef sdkPath,
2014-
llvm::SmallString<256> &OutPath,
2015-
StringRef &CacheHash) {
2016-
OutPath = genericSubInvocation.getClangModuleCachePath();
2017-
llvm::sys::path::append(OutPath, moduleName);
2018-
OutPath.append("-");
2019-
auto hashStart = OutPath.size();
2020-
OutPath.append(getCacheHash(useInterfacePath, sdkPath));
2021-
CacheHash = OutPath.str().substr(hashStart);
2022-
OutPath.append(".");
2023-
auto OutExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
2024-
OutPath.append(OutExt);
2025-
return OutPath.str();
2026-
}
2027-
2028-
/// Construct a cache key for the .swiftmodule being generated. There is a
2029-
/// balance to be struck here between things that go in the cache key and
2030-
/// things that go in the "up to date" check of the cache entry. We want to
2031-
/// avoid fighting over a single cache entry too much when (say) running
2032-
/// different compiler versions on the same machine or different inputs
2033-
/// that happen to have the same short module name, so we will disambiguate
2034-
/// those in the key. But we want to invalidate and rebuild a cache entry
2035-
/// -- rather than making a new one and potentially filling up the cache
2036-
/// with dead entries -- when other factors change, such as the contents of
2037-
/// the .swiftinterface input or its dependencies.
2038-
std::string
2039-
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath,
2040-
StringRef sdkPath) {
2041-
// When doing dependency scanning for explicit module, use strict context hash
2042-
// to ensure sound module hash.
2043-
bool useStrictCacheHash =
2044-
genericSubInvocation.getFrontendOptions().RequestedAction ==
2045-
FrontendOptions::ActionType::ScanDependencies;
2046-
2047-
// Include the normalized target triple when not using strict hash.
2048-
// Otherwise, use the full target to ensure soundness of the hash. In
2049-
// practice, .swiftinterface files will be in target-specific subdirectories
2050-
// and would have target-specific pieces #if'd out. However, it doesn't hurt
2051-
// to include it, and it guards against mistakenly reusing cached modules
2052-
// across targets. Note that this normalization explicitly doesn't include the
2053-
// minimum deployment target (e.g. the '12.0' in 'ios12.0').
2054-
auto targetToHash = useStrictCacheHash
2055-
? genericSubInvocation.getLangOptions().Target
2056-
: getTargetSpecificModuleTriple(
2057-
genericSubInvocation.getLangOptions().Target);
2058-
2059-
std::string sdkBuildVersion = getSDKBuildVersion(sdkPath);
2060-
const auto ExtraArgs = genericSubInvocation.getClangImporterOptions()
2061-
.getReducedExtraArgsForSwiftModuleDependency();
2062-
2063-
llvm::hash_code H = hash_combine(
2064-
// Start with the compiler version (which will be either tag names or
2065-
// revs). Explicitly don't pass in the "effective" language version --
2066-
// this would mean modules built in different -swift-version modes would
2067-
// rebuild their dependencies.
2068-
swift::version::getSwiftFullVersion(),
2069-
2070-
// Simplest representation of input "identity" (not content) is just a
2071-
// pathname, and probably all we can get from the VFS in this regard
2072-
// anyways.
2073-
useInterfacePath,
2074-
2075-
// The target triple to hash.
2076-
targetToHash.str(),
2077-
2078-
// The SDK path is going to affect how this module is imported, so
2079-
// include it.
2080-
genericSubInvocation.getSDKPath(),
2081-
2082-
// The SDK build version may identify differences in headers
2083-
// that affects references serialized in the cached file.
2084-
sdkBuildVersion,
2085-
2086-
// Applying the distribution channel of the current compiler enables
2087-
// different compilers to share a module cache location.
2088-
version::getCurrentCompilerChannel(),
2089-
2090-
// Whether or not we're tracking system dependencies affects the
2091-
// invalidation behavior of this cache item.
2092-
genericSubInvocation.getFrontendOptions().shouldTrackSystemDependencies(),
2093-
2094-
// Whether or not caching is enabled affects if the instance is able to
2095-
// correctly load the dependencies.
2096-
genericSubInvocation.getCASOptions().getModuleScanningHashComponents(),
2097-
2098-
// Clang ExtraArgs that affects how clang types are imported into swift
2099-
// module.
2100-
llvm::hash_combine_range(ExtraArgs.begin(), ExtraArgs.end()),
2101-
2102-
/// Application extension.
2103-
unsigned(
2104-
genericSubInvocation.getLangOptions().EnableAppExtensionRestrictions),
2105-
2106-
// Whether or not OSSA modules are enabled.
2107-
//
2108-
// If OSSA modules are enabled, we use a separate namespace of modules to
2109-
// ensure that we compile all swift interface files with the option set.
2110-
unsigned(genericSubInvocation.getSILOptions().EnableOSSAModules)
2111-
);
2112-
2113-
return llvm::toString(llvm::APInt(64, H), 36, /*Signed=*/false);
2008+
InterfaceModuleNameExpander::ResultTy
2009+
InterfaceSubContextDelegateImpl::getCachedOutputPath(StringRef moduleName,
2010+
StringRef interfacePath,
2011+
StringRef sdkPath) {
2012+
InterfaceModuleNameExpander expander(moduleName, interfacePath, sdkPath,
2013+
genericSubInvocation);
2014+
return expander.getExpandedName();
21142015
}
21152016

21162017
std::error_code
@@ -2189,13 +2090,11 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
21892090
}
21902091

21912092
// Calculate output path of the module.
2192-
llvm::SmallString<256> buffer;
2193-
StringRef CacheHash;
2194-
auto hashedOutput = computeCachedOutputPath(moduleName, interfacePath,
2195-
sdkPath, buffer, CacheHash);
2093+
auto expandedName = getCachedOutputPath(moduleName, interfacePath, sdkPath);
2094+
21962095
// If no specific output path is given, use the hashed output path.
21972096
if (outputPath.empty()) {
2198-
outputPath = hashedOutput;
2097+
outputPath = expandedName.outputPath;
21992098
}
22002099

22012100
// Configure the outputs in front-end options. There must be an equal number of
@@ -2249,7 +2148,7 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
22492148
}
22502149

22512150
info.BuildArguments = BuildArgs;
2252-
info.Hash = CacheHash;
2151+
info.Hash = expandedName.hash;
22532152

22542153
// Run the action under the sub compiler instance.
22552154
return action(info);
@@ -2846,26 +2745,45 @@ std::unique_ptr<ExplicitCASModuleLoader> ExplicitCASModuleLoader::create(
28462745

28472746
InterfaceModuleNameExpander::ResultTy
28482747
InterfaceModuleNameExpander::getExpandedName() {
2849-
// Expand the name once, and reuse later.
2850-
if (!expanded) {
2851-
auto &outputPath = expandedName.outputPath;
2748+
if (!expandedName) {
2749+
expandedName = std::make_unique<ResultTy>();
2750+
auto &outputPath = expandedName->outputPath;
28522751
outputPath = CI.getClangModuleCachePath();
28532752
llvm::sys::path::append(outputPath, moduleName);
28542753
outputPath.append("-");
28552754
auto hashStart = outputPath.size();
28562755
outputPath.append(getHash());
2857-
expandedName.hash = outputPath.str().substr(hashStart);
2756+
expandedName->hash = outputPath.str().substr(hashStart);
28582757
outputPath.append(".");
28592758
auto outExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
28602759
outputPath.append(outExt);
2861-
expanded = true;
28622760
}
2863-
return expandedName;
2761+
return *expandedName;
28642762
}
28652763

2764+
/// Construct a key for the .swiftmodule being generated. There is a
2765+
/// balance to be struck here between things that go in the cache key and
2766+
/// things that go in the "up to date" check of the cache entry. We want to
2767+
/// avoid fighting over a single cache entry too much when (say) running
2768+
/// different compiler versions on the same machine or different inputs
2769+
/// that happen to have the same short module name, so we will disambiguate
2770+
/// those in the key. But we want to invalidate and rebuild a cache entry
2771+
/// -- rather than making a new one and potentially filling up the cache
2772+
/// with dead entries -- when other factors change, such as the contents of
2773+
/// the .swiftinterface input or its dependencies.
28662774
std::string InterfaceModuleNameExpander::getHash() {
2775+
// When doing dependency scanning for explicit module, use strict context hash
2776+
// to ensure sound module hash.
28672777
bool useStrictCacheHash = CI.getFrontendOptions().RequestedAction ==
28682778
FrontendOptions::ActionType::ScanDependencies;
2779+
2780+
// Include the normalized target triple when not using strict hash.
2781+
// Otherwise, use the full target to ensure soundness of the hash. In
2782+
// practice, .swiftinterface files will be in target-specific subdirectories
2783+
// and would have target-specific pieces #if'd out. However, it doesn't hurt
2784+
// to include it, and it guards against mistakenly reusing cached modules
2785+
// across targets. Note that this normalization explicitly doesn't include the
2786+
// minimum deployment target (e.g. the '12.0' in 'ios12.0').
28692787
auto targetToHash =
28702788
useStrictCacheHash
28712789
? CI.getLangOptions().Target
@@ -2874,12 +2792,50 @@ std::string InterfaceModuleNameExpander::getHash() {
28742792
std::string sdkBuildVersion = getSDKBuildVersion(sdkPath);
28752793

28762794
llvm::hash_code H = llvm::hash_combine(
2877-
swift::version::getSwiftFullVersion(), interfacePath, targetToHash.str(),
2878-
CI.getSDKPath(), sdkBuildVersion, version::getCurrentCompilerChannel(),
2795+
// Start with the compiler version (which will be either tag names or
2796+
// revs). Explicitly don't pass in the "effective" language version --
2797+
// this would mean modules built in different -swift-version modes would
2798+
// rebuild their dependencies.
2799+
swift::version::getSwiftFullVersion(),
2800+
2801+
// Simplest representation of input "identity" (not content) is just a
2802+
// pathname, and probably all we can get from the VFS in this regard
2803+
// anyways.
2804+
interfacePath,
2805+
2806+
// The target triple to hash.
2807+
targetToHash.str(),
2808+
2809+
// The SDK path is going to affect how this module is imported, so
2810+
// include it.
2811+
CI.getSDKPath(),
2812+
2813+
// The SDK build version may identify differences in headers
2814+
// that affects references serialized in the cached file.
2815+
sdkBuildVersion,
2816+
2817+
// Applying the distribution channel of the current compiler enables
2818+
// different compilers to share a module cache location.
2819+
version::getCurrentCompilerChannel(),
2820+
2821+
// Whether or not we're tracking system dependencies affects the
2822+
// invalidation behavior of this cache item.
28792823
CI.getFrontendOptions().shouldTrackSystemDependencies(),
2824+
2825+
// Whether or not caching is enabled affects if the instance is able to
2826+
// correctly load the dependencies.
28802827
CI.getCASOptions().getModuleScanningHashComponents(),
2828+
2829+
// Take care of any extra arguments that should affect the hash.
28812830
llvm::hash_combine_range(extraArgs.begin(), extraArgs.end()),
2831+
2832+
// Application extension.
28822833
unsigned(CI.getLangOptions().EnableAppExtensionRestrictions),
2834+
2835+
// Whether or not OSSA modules are enabled.
2836+
//
2837+
// If OSSA modules are enabled, we use a separate namespace of modules to
2838+
// ensure that we compile all swift interface files with the option set.
28832839
unsigned(CI.getSILOptions().EnableOSSAModules));
28842840

28852841
return llvm::toString(llvm::APInt(64, H), 36, /*Signed=*/false);

0 commit comments

Comments
 (0)