Skip to content

Commit b974d97

Browse files
committed
[Dependency Scanning] Record header dependencies of Binary Swift module dependencies
These are meant to capture paths to the PCH files that a given module was built with.
1 parent 90a1bb8 commit b974d97

File tree

6 files changed

+97
-51
lines changed

6 files changed

+97
-51
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,15 @@ class ModuleDependencyInfoStorageBase {
106106
const ModuleDependencyKind dependencyKind;
107107

108108
ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind,
109-
StringRef moduleCacheKey = "",
110-
bool resolved = false)
109+
StringRef moduleCacheKey = "")
111110
: dependencyKind(dependencyKind), moduleCacheKey(moduleCacheKey.str()),
112-
resolved(resolved) {}
111+
resolved(false) { }
112+
113+
ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind,
114+
const std::vector<std::string> &moduleImports,
115+
StringRef moduleCacheKey = "")
116+
: dependencyKind(dependencyKind), moduleImports(moduleImports),
117+
moduleCacheKey(moduleCacheKey.str()), resolved(false) {}
113118

114119
virtual ModuleDependencyInfoStorageBase *clone() const = 0;
115120

@@ -282,12 +287,15 @@ class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBas
282287
SwiftBinaryModuleDependencyStorage(const std::string &compiledModulePath,
283288
const std::string &moduleDocPath,
284289
const std::string &sourceInfoPath,
290+
const std::vector<std::string> &moduleImports,
291+
const std::vector<std::string> &headerImports,
285292
const bool isFramework,
286293
const std::string &moduleCacheKey)
287294
: ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftBinary,
288-
moduleCacheKey),
295+
moduleImports, moduleCacheKey),
289296
compiledModulePath(compiledModulePath), moduleDocPath(moduleDocPath),
290-
sourceInfoPath(sourceInfoPath), isFramework(isFramework) {}
297+
sourceInfoPath(sourceInfoPath), preCompiledBridgingHeaderPaths(headerImports),
298+
isFramework(isFramework) {}
291299

292300
ModuleDependencyInfoStorageBase *clone() const override {
293301
return new SwiftBinaryModuleDependencyStorage(*this);
@@ -302,6 +310,9 @@ class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBas
302310
/// The path to the .swiftSourceInfo file.
303311
const std::string sourceInfoPath;
304312

313+
/// The paths of all the .pch dependencies of this module.
314+
const std::vector<std::string> preCompiledBridgingHeaderPaths;
315+
305316
/// A flag that indicates this dependency is a framework
306317
const bool isFramework;
307318

@@ -447,15 +458,17 @@ class ModuleDependencyInfo {
447458
}
448459

449460
/// Describe the module dependencies for a serialized or parsed Swift module.
450-
static ModuleDependencyInfo
451-
forSwiftBinaryModule(const std::string &compiledModulePath,
452-
const std::string &moduleDocPath,
453-
const std::string &sourceInfoPath, bool isFramework,
454-
const std::string &moduleCacheKey) {
461+
static ModuleDependencyInfo forSwiftBinaryModule(
462+
const std::string &compiledModulePath,
463+
const std::string &moduleDocPath,
464+
const std::string &sourceInfoPath,
465+
const std::vector<std::string> &moduleImports,
466+
const std::vector<std::string> &headerImports,
467+
bool isFramework, const std::string &moduleCacheKey) {
455468
return ModuleDependencyInfo(
456469
std::make_unique<SwiftBinaryModuleDependencyStorage>(
457-
compiledModulePath, moduleDocPath, sourceInfoPath, isFramework,
458-
moduleCacheKey));
470+
compiledModulePath, moduleDocPath, sourceInfoPath,
471+
moduleImports, headerImports, isFramework, moduleCacheKey));
459472
}
460473

461474
/// Describe the main Swift module.

include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ using SwiftBinaryModuleDetailsLayout =
165165
FileIDField, // compiledModulePath
166166
FileIDField, // moduleDocPath
167167
FileIDField, // moduleSourceInfoPath
168+
ImportArrayIDField, // headerImports
168169
IsFrameworkField, // isFramework
169170
IdentifierIDField // moduleCacheKey
170171
>;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,20 @@ class SerializedModuleLoaderBase : public ModuleLoader {
150150
/// Scan the given serialized module file to determine dependencies.
151151
llvm::ErrorOr<ModuleDependencyInfo> scanModuleFile(Twine modulePath, bool isFramework);
152152

153-
static llvm::ErrorOr<llvm::StringSet<>>
154-
getModuleImportsOfModule(Twine modulePath,
155-
ModuleLoadingBehavior transitiveBehavior,
156-
bool isFramework,
157-
bool isRequiredOSSAModules,
158-
StringRef SDKName,
159-
StringRef packageName,
160-
llvm::vfs::FileSystem *fileSystem,
161-
PathObfuscator &recoverer);
153+
struct BinaryModuleImports {
154+
llvm::StringSet<> moduleImports;
155+
llvm::StringSet<> headerImports;
156+
};
157+
158+
static llvm::ErrorOr<BinaryModuleImports>
159+
getImportsOfModule(Twine modulePath,
160+
ModuleLoadingBehavior transitiveBehavior,
161+
bool isFramework,
162+
bool isRequiredOSSAModules,
163+
StringRef SDKName,
164+
StringRef packageName,
165+
llvm::vfs::FileSystem *fileSystem,
166+
PathObfuscator &recoverer);
162167

163168
/// Load the module file into a buffer and also collect its module name.
164169
static std::unique_ptr<llvm::MemoryBuffer>

lib/DependencyScan/ModuleDependencyCacheSerialization.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
462462
"Unexpected SWIFT_BINARY_MODULE_DETAILS_NODE record");
463463
cache.configureForContextHash(getContextHash());
464464
unsigned compiledModulePathID, moduleDocPathID, moduleSourceInfoPathID,
465-
isFramework, moduleCacheKeyID;
465+
headerImportsArrayID, isFramework, moduleCacheKeyID;
466466
SwiftBinaryModuleDetailsLayout::readRecord(
467467
Scratch, compiledModulePathID, moduleDocPathID,
468-
moduleSourceInfoPathID, isFramework, moduleCacheKeyID);
468+
moduleSourceInfoPathID, headerImportsArrayID, isFramework,
469+
moduleCacheKeyID);
469470

470471
auto compiledModulePath = getIdentifier(compiledModulePathID);
471472
if (!compiledModulePath)
@@ -477,16 +478,18 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
477478
if (!moduleSourceInfoPath)
478479
llvm::report_fatal_error("Bad module source info path");
479480
auto moduleCacheKey = getIdentifier(moduleCacheKeyID);
480-
if (!moduleCacheKeyID)
481+
if (!moduleCacheKey)
481482
llvm::report_fatal_error("Bad moduleCacheKey");
482483

484+
auto headerImports = getStringArray(headerImportsArrayID);
485+
if (!headerImports)
486+
llvm::report_fatal_error("Bad binary direct dependencies: no header imports");
487+
483488
// Form the dependencies storage object
484489
auto moduleDep = ModuleDependencyInfo::forSwiftBinaryModule(
485-
*compiledModulePath, *moduleDocPath, *moduleSourceInfoPath,
486-
isFramework, *moduleCacheKey);
487-
// Add dependencies of this module
488-
for (const auto &moduleName : *currentModuleImports)
489-
moduleDep.addModuleImport(moduleName);
490+
*compiledModulePath, *moduleDocPath, *moduleSourceInfoPath,
491+
*currentModuleImports, *headerImports, isFramework,
492+
*moduleCacheKey);
490493

491494
cache.recordDependency(currentModuleName, std::move(moduleDep),
492495
getContextHash());
@@ -704,6 +707,7 @@ bool swift::dependencies::module_dependency_cache_serialization::
704707
enum ModuleIdentifierArrayKind : uint8_t {
705708
Empty = 0,
706709
DependencyImports,
710+
DependencyHeaders,
707711
QualifiedModuleDependencyIDs,
708712
CompiledModuleCandidates,
709713
BuildCommandLine,
@@ -975,6 +979,7 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(ModuleDependencyID modul
975979
getIdentifier(swiftBinDeps->compiledModulePath),
976980
getIdentifier(swiftBinDeps->moduleDocPath),
977981
getIdentifier(swiftBinDeps->sourceInfoPath),
982+
getArrayID(moduleID, ModuleIdentifierArrayKind::DependencyHeaders),
978983
swiftBinDeps->isFramework,
979984
getIdentifier(swiftBinDeps->moduleCacheKey));
980985

@@ -1152,6 +1157,8 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays(
11521157
addIdentifier(swiftBinDeps->moduleDocPath);
11531158
addIdentifier(swiftBinDeps->sourceInfoPath);
11541159
addIdentifier(swiftBinDeps->moduleCacheKey);
1160+
addStringArray(moduleID, ModuleIdentifierArrayKind::DependencyHeaders,
1161+
swiftBinDeps->preCompiledBridgingHeaderPaths);
11551162
break;
11561163
}
11571164
case swift::ModuleDependencyKind::SwiftPlaceholder: {

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,38 +208,41 @@ ErrorOr<ModuleDependencyInfo> ModuleDependencyScanner::scanInterfaceFile(
208208
});
209209
if (adjacentBinaryModule != compiledCandidates.end()) {
210210
// Required modules.
211-
auto adjacentBinaryModuleRequiredImports = getModuleImportsOfModule(
211+
auto adjacentBinaryModuleRequiredImports = getImportsOfModule(
212212
*adjacentBinaryModule, ModuleLoadingBehavior::Required, isFramework,
213213
isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
214214
Ctx.LangOpts.PackageName, Ctx.SourceMgr.getFileSystem().get(),
215215
Ctx.SearchPathOpts.DeserializedPathRecoverer);
216216
if (!adjacentBinaryModuleRequiredImports)
217217
return adjacentBinaryModuleRequiredImports.getError();
218-
218+
auto adjacentBinaryModuleRequiredModuleImports =
219+
(*adjacentBinaryModuleRequiredImports).moduleImports;
219220
#ifndef NDEBUG
220221
// Verify that the set of required modules read out from the binary
221222
// module is a super-set of module imports identified in the
222223
// textual interface.
223224
for (const auto &requiredImport : Result->getModuleImports()) {
224-
assert(adjacentBinaryModuleRequiredImports->contains(requiredImport) &&
225+
assert(adjacentBinaryModuleRequiredModuleImports.contains(requiredImport) &&
225226
"Expected adjacent binary module's import set to contain all "
226227
"textual interface imports.");
227228
}
228229
#endif
229230

230-
for (const auto &requiredImport : *adjacentBinaryModuleRequiredImports)
231+
for (const auto &requiredImport : adjacentBinaryModuleRequiredModuleImports)
231232
Result->addModuleImport(requiredImport.getKey(),
232233
&alreadyAddedModules);
233234

234235
// Optional modules. Will be looked-up on a best-effort basis
235-
auto adjacentBinaryModuleOptionalImports = getModuleImportsOfModule(
236+
auto adjacentBinaryModuleOptionalImports = getImportsOfModule(
236237
*adjacentBinaryModule, ModuleLoadingBehavior::Optional, isFramework,
237238
isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
238239
Ctx.LangOpts.PackageName, Ctx.SourceMgr.getFileSystem().get(),
239240
Ctx.SearchPathOpts.DeserializedPathRecoverer);
240241
if (!adjacentBinaryModuleOptionalImports)
241242
return adjacentBinaryModuleOptionalImports.getError();
242-
for (const auto &optionalImport : *adjacentBinaryModuleOptionalImports)
243+
auto adjacentBinaryModuleOptionalModuleImports =
244+
(*adjacentBinaryModuleOptionalImports).moduleImports;
245+
for (const auto &optionalImport : adjacentBinaryModuleOptionalModuleImports)
243246
Result->addOptionalModuleImport(optionalImport.getKey(),
244247
&alreadyAddedModules);
245248
}

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,8 @@ std::error_code SerializedModuleLoaderBase::openModuleFile(
392392
return std::error_code();
393393
}
394394

395-
llvm::ErrorOr<llvm::StringSet<>>
396-
SerializedModuleLoaderBase::getModuleImportsOfModule(
395+
llvm::ErrorOr<SerializedModuleLoaderBase::BinaryModuleImports>
396+
SerializedModuleLoaderBase::getImportsOfModule(
397397
Twine modulePath, ModuleLoadingBehavior transitiveBehavior,
398398
bool isFramework, bool isRequiredOSSAModules, StringRef SDKName,
399399
StringRef packageName, llvm::vfs::FileSystem *fileSystem,
@@ -403,16 +403,18 @@ SerializedModuleLoaderBase::getModuleImportsOfModule(
403403
return moduleBuf.getError();
404404

405405
llvm::StringSet<> importedModuleNames;
406+
llvm::StringSet<> importedHeaders;
406407
// Load the module file without validation.
407408
std::shared_ptr<const ModuleFileSharedCore> loadedModuleFile;
408409
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
409410
"", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework,
410411
isRequiredOSSAModules, SDKName, recoverer, loadedModuleFile);
411412

412413
for (const auto &dependency : loadedModuleFile->getDependencies()) {
413-
// FIXME: Record header dependency?
414-
if (dependency.isHeader())
414+
if (dependency.isHeader()) {
415+
importedHeaders.insert(dependency.RawPath);
415416
continue;
417+
}
416418

417419
ModuleLoadingBehavior dependencyTransitiveBehavior =
418420
loadedModuleFile->getTransitiveLoadingBehavior(
@@ -433,17 +435,13 @@ SerializedModuleLoaderBase::getModuleImportsOfModule(
433435
importedModuleNames.insert(moduleName);
434436
}
435437

436-
return importedModuleNames;
438+
return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames, importedHeaders};
437439
}
438440

439441
llvm::ErrorOr<ModuleDependencyInfo>
440442
SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework) {
441443
const std::string moduleDocPath;
442444
const std::string sourceInfoPath;
443-
// Map the set of dependencies over to the "module dependencies".
444-
auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule(
445-
modulePath.str(), moduleDocPath, sourceInfoPath, isFramework,
446-
/*module-cache-key*/ "");
447445
// Some transitive dependencies of binary modules are not required to be
448446
// imported during normal builds.
449447
// TODO: This is worth revisiting for debugger purposes where
@@ -452,18 +450,37 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework) {
452450
// optional.
453451
ModuleLoadingBehavior transitiveLoadingBehavior =
454452
ModuleLoadingBehavior::Required;
455-
auto importedModuleNames = getModuleImportsOfModule(
453+
auto binaryModuleImports = getImportsOfModule(
456454
modulePath, transitiveLoadingBehavior, isFramework,
457455
isRequiredOSSAModules(), Ctx.LangOpts.SDKName, Ctx.LangOpts.PackageName,
458456
Ctx.SourceMgr.getFileSystem().get(),
459457
Ctx.SearchPathOpts.DeserializedPathRecoverer);
460-
if (!importedModuleNames)
461-
return importedModuleNames.getError();
458+
if (!binaryModuleImports)
459+
return binaryModuleImports.getError();
460+
461+
auto importedModuleSet = binaryModuleImports.get().moduleImports;
462+
std::vector<std::string> importedModuleNames;
463+
importedModuleNames.reserve(importedModuleSet.size());
464+
llvm::transform(importedModuleSet.keys(),
465+
std::back_inserter(importedModuleNames),
466+
[](llvm::StringRef N) {
467+
return N.str();
468+
});
469+
470+
auto importedHeaderSet = binaryModuleImports.get().headerImports;
471+
std::vector<std::string> importedHeaders;
472+
importedHeaders.reserve(importedHeaderSet.size());
473+
llvm::transform(importedHeaderSet.keys(),
474+
std::back_inserter(importedHeaders),
475+
[](llvm::StringRef N) {
476+
return N.str();
477+
});
462478

463-
llvm::StringSet<> addedModuleNames;
464-
for (const auto &importedModuleName : *importedModuleNames)
465-
dependencies.addModuleImport(importedModuleName.getKey(),
466-
&addedModuleNames);
479+
// Map the set of dependencies over to the "module dependencies".
480+
auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule(
481+
modulePath.str(), moduleDocPath, sourceInfoPath,
482+
importedModuleNames, importedHeaders, isFramework,
483+
/*module-cache-key*/ "");
467484

468485
return std::move(dependencies);
469486
}

0 commit comments

Comments
 (0)