Skip to content

Commit 23fcb49

Browse files
authored
Merge pull request #37585 from artemcm/SerializeModuleDepCache
[Dependency Scanning] Add a binary serialization format for the Inter-Module Dependencies Cache
2 parents 1a0801a + 14229f1 commit 23fcb49

18 files changed

+1264
-16
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@ class ModuleDependencies {
275275

276276
/// Describe the module dependencies for a Swift module that can be
277277
/// built from a Swift interface file (\c .swiftinterface).
278-
static ModuleDependencies forSwiftInterface(
279-
const std::string &swiftInterfaceFile,
278+
static ModuleDependencies forSwiftTextualModule(
279+
const Optional<std::string> &swiftInterfaceFile,
280280
ArrayRef<std::string> compiledCandidates,
281281
ArrayRef<StringRef> buildCommands,
282282
ArrayRef<StringRef> extraPCMArgs,
@@ -386,6 +386,9 @@ class ModuleDependencies {
386386
/// Add a bridging header to a Swift module's dependencies.
387387
void addBridgingHeader(StringRef bridgingHeader);
388388

389+
/// Add source files
390+
void addSourceFile(StringRef sourceFile);
391+
389392
/// Add source files that the bridging header depends on.
390393
void addBridgingSourceFile(StringRef bridgingSourceFile);
391394

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
//=== SerializedModuleDependencyCacheFormat.h - serialized format -*- C++-*-=//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_DEPENDENCY_SERIALIZEDCACHEFORMAT_H
14+
#define SWIFT_DEPENDENCY_SERIALIZEDCACHEFORMAT_H
15+
16+
#include "llvm/Bitcode/BitcodeConvenience.h"
17+
#include "llvm/Bitstream/BitCodes.h"
18+
19+
namespace llvm {
20+
class MemoryBuffer;
21+
}
22+
23+
namespace swift {
24+
25+
class DiagnosticEngine;
26+
class ModuleDependenciesCache;
27+
28+
namespace dependencies {
29+
namespace module_dependency_cache_serialization {
30+
31+
using llvm::BCArray;
32+
using llvm::BCBlob;
33+
using llvm::BCFixed;
34+
using llvm::BCRecordLayout;
35+
using llvm::BCVBR;
36+
37+
/// Every .moddepcache file begins with these 4 bytes, for easy identification.
38+
const unsigned char MODULE_DEPENDENCY_CACHE_FORMAT_SIGNATURE[] = {'I', 'M', 'D',
39+
'C'};
40+
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR = 1;
41+
/// Increment this on every change.
42+
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 0;
43+
44+
/// Various identifiers in this format will rely on having their strings mapped
45+
/// using this ID.
46+
using IdentifierIDField = BCVBR<13>;
47+
using FileIDField = IdentifierIDField;
48+
using ModuleIDField = IdentifierIDField;
49+
using CompilerFlagField = IdentifierIDField;
50+
using ContextHashField = IdentifierIDField;
51+
52+
/// A bit that indicates whether or not a module is a framework
53+
using IsFrameworkField = BCFixed<1>;
54+
55+
/// Arrays of various identifiers, distinguised for readability
56+
using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>;
57+
58+
/// Identifiers used to refer to the above arrays
59+
using FileIDArrayIDField = IdentifierIDField;
60+
using DependencyIDArrayIDField = IdentifierIDField;
61+
using FlagIDArrayIDField = IdentifierIDField;
62+
63+
/// The ID of the top-level block containing the dependency graph
64+
const unsigned GRAPH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID;
65+
66+
/// The .moddepcache file format consists of a METADATA record, followed by
67+
/// zero or more IDENTIFIER records that contain various strings seen in the graph
68+
/// (e.g. file names or compiler flags), followed by zero or more IDENTIFIER_ARRAY records
69+
/// which are arrays of identifiers seen in the graph (e.g. list of source files or list of compile flags),
70+
/// followed by zero or more MODULE_NODE, *_DETAILS_NODE pairs of records.
71+
namespace graph_block {
72+
enum {
73+
METADATA = 1,
74+
MODULE_NODE,
75+
SWIFT_TEXTUAL_MODULE_DETAILS_NODE,
76+
SWIFT_PLACEHOLDER_MODULE_DETAILS_NODE,
77+
SWIFT_BINARY_MODULE_DETAILS_NODE,
78+
CLANG_MODULE_DETAILS_NODE,
79+
IDENTIFIER_NODE,
80+
IDENTIFIER_ARRAY_NODE
81+
};
82+
83+
// Always the first record in the file.
84+
using MetadataLayout = BCRecordLayout<
85+
METADATA, // ID
86+
BCFixed<16>, // Inter-Module Dependency graph format major version
87+
BCFixed<16>, // Inter-Module Dependency graph format minor version
88+
BCBlob // Compiler version string
89+
>;
90+
91+
// After the metadata record, we have zero or more identifier records,
92+
// for each unique string that is referenced in the graph.
93+
//
94+
// Identifiers are referenced by their sequence number, starting from 1.
95+
// The identifier value 0 is special; it always represents the empty string.
96+
// There is no IDENTIFIER_NODE serialized that corresponds to it, instead
97+
// the first IDENTIFIER_NODE always has a sequence number of 1.
98+
using IdentifierNodeLayout = BCRecordLayout<IDENTIFIER_NODE, BCBlob>;
99+
100+
// After the identifier records we have zero or more identifier array records.
101+
//
102+
// These arrays are also referenced by their sequence number,
103+
// starting from 1, similar to identifiers above. Value 0 indicates an
104+
// empty array. This record is used because individiual array fields must
105+
// appear as the last field of whatever record they belong to, and several of
106+
// the below record layouts contain multiple arrays.
107+
using IdentifierArrayLayout =
108+
BCRecordLayout<IDENTIFIER_ARRAY_NODE, IdentifierIDArryField>;
109+
110+
// After the array records, we have a sequence of Module info
111+
// records, each of which is followed by one of:
112+
// - SwiftTextualModuleDetails
113+
// - SwiftBinaryModuleDetails
114+
// - SwiftPlaceholderModuleDetails
115+
// - ClangModuleDetails
116+
using ModuleInfoLayout =
117+
BCRecordLayout<MODULE_NODE, // ID
118+
IdentifierIDField, // module name
119+
DependencyIDArrayIDField // directDependencies
120+
>;
121+
122+
using SwiftTextualModuleDetailsLayout =
123+
BCRecordLayout<SWIFT_TEXTUAL_MODULE_DETAILS_NODE, // ID
124+
FileIDField, // swiftInterfaceFile
125+
FileIDArrayIDField, // compiledModuleCandidates
126+
FlagIDArrayIDField, // buildCommandLine
127+
FlagIDArrayIDField, // extraPCMArgs
128+
ContextHashField, // contextHash
129+
IsFrameworkField, // isFramework
130+
FileIDField, // bridgingHeaderFile
131+
FileIDArrayIDField, // sourceFiles
132+
FileIDArrayIDField, // bridgingSourceFiles
133+
IdentifierIDField // bridgingModuleDependencies
134+
>;
135+
136+
using SwiftBinaryModuleDetailsLayout =
137+
BCRecordLayout<SWIFT_BINARY_MODULE_DETAILS_NODE, // ID
138+
FileIDField, // compiledModulePath
139+
FileIDField, // moduleDocPath
140+
FileIDField, // moduleSourceInfoPath
141+
IsFrameworkField // isFramework
142+
>;
143+
144+
using SwiftPlaceholderModuleDetailsLayout =
145+
BCRecordLayout<SWIFT_PLACEHOLDER_MODULE_DETAILS_NODE, // ID
146+
FileIDField, // compiledModulePath
147+
FileIDField, // moduleDocPath
148+
FileIDField // moduleSourceInfoPath
149+
>;
150+
151+
using ClangModuleDetailsLayout =
152+
BCRecordLayout<CLANG_MODULE_DETAILS_NODE, // ID
153+
FileIDField, // moduleMapPath
154+
ContextHashField, // contextHash
155+
FlagIDArrayIDField, // commandLine
156+
FileIDArrayIDField // fileDependencies
157+
>;
158+
} // namespace graph_block
159+
160+
/// Tries to read the dependency graph from the given buffer.
161+
/// Returns \c true if there was an error.
162+
bool readInterModuleDependenciesCache(llvm::MemoryBuffer &buffer,
163+
ModuleDependenciesCache &cache);
164+
165+
/// Tries to read the dependency graph from the given path name.
166+
/// Returns true if there was an error.
167+
bool readInterModuleDependenciesCache(llvm::StringRef path,
168+
ModuleDependenciesCache &cache);
169+
170+
/// Tries to write the dependency graph to the given path name.
171+
/// Returns true if there was an error.
172+
bool writeInterModuleDependenciesCache(DiagnosticEngine &diags,
173+
llvm::StringRef path,
174+
const ModuleDependenciesCache &cache);
175+
176+
/// Tries to write out the given dependency cache with the given
177+
/// bitstream writer.
178+
void writeInterModuleDependenciesCache(llvm::BitstreamWriter &Out,
179+
const ModuleDependenciesCache &cache);
180+
181+
} // end namespace module_dependency_cache_serialization
182+
} // end namespace dependencies
183+
} // end namespace swift
184+
185+
#endif

include/swift/Frontend/FrontendOptions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,19 @@ class FrontendOptions {
304304
/// of the main Swift module's source files.
305305
bool ImportPrescan = false;
306306

307+
/// After performing a dependency scanning action, serialize the scanner's internal state.
308+
bool SerializeDependencyScannerCache = false;
309+
310+
/// Load and re-use a prior serialized dependency scanner cache.
311+
bool ReuseDependencyScannerCache = false;
312+
313+
/// The path at which to either serialize or deserialize the dependency scanner cache.
314+
std::string SerializedDependencyScannerCachePath;
315+
316+
/// After performing a dependency scanning action, serialize and deserialize the
317+
/// dependency cache before producing the result.
318+
bool TestDependencyScannerCacheSerialization = false;
319+
307320
/// When performing an incremental build, ensure that cross-module incremental
308321
/// build metadata is available in any swift modules emitted by this frontend
309322
/// job.

include/swift/Option/FrontendOptions.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ def batch_scan_input_file
185185
def import_prescan : Flag<["-"], "import-prescan">,
186186
HelpText<"When performing a dependency scan, only dentify all imports of the main Swift module sources">;
187187

188+
def serialize_dependency_scan_cache : Flag<["-"], "serialize-dependency-scan-cache">,
189+
HelpText<"After performing a dependency scan, serialize the scanner's internal state.">;
190+
191+
def reuse_dependency_scan_cache : Flag<["-"], "load-dependency-scan-cache">,
192+
HelpText<"After performing a dependency scan, serialize the scanner's internal state.">;
193+
194+
def dependency_scan_cache_path : Separate<["-"], "dependency-scan-cache-path">,
195+
HelpText<"The path to output the dependency scanner's internal state.">;
196+
188197
def enable_copy_propagation : Flag<["-"], "enable-copy-propagation">,
189198
HelpText<"Run SIL copy propagation to shorten object lifetime.">;
190199
def disable_copy_propagation : Flag<["-"], "disable-copy-propagation">,
@@ -289,6 +298,9 @@ def debug_crash_immediately : Flag<["-"], "debug-crash-immediately">,
289298
def debug_crash_after_parse : Flag<["-"], "debug-crash-after-parse">,
290299
DebugCrashOpt, HelpText<"Force a crash after parsing">;
291300

301+
def debug_test_dependency_scan_cache_serialization: Flag<["-"], "test-dependency-scan-cache-serialization">,
302+
HelpText<"After performing a dependency scan, serialize and then deserialize the scanner's internal state.">;
303+
292304
def debugger_support : Flag<["-"], "debugger-support">,
293305
HelpText<"Process swift code as if running in the debugger">;
294306

lib/AST/ModuleDependencies.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ void ModuleDependencies::addBridgingSourceFile(StringRef bridgingSourceFile) {
118118
swiftStorage->bridgingSourceFiles.push_back(bridgingSourceFile.str());
119119
}
120120

121+
void ModuleDependencies::addSourceFile(StringRef sourceFile) {
122+
auto swiftStorage = cast<SwiftTextualModuleDependenciesStorage>(storage.get());
123+
swiftStorage->sourceFiles.push_back(sourceFile.str());
124+
}
125+
121126
/// Add (Clang) module on which the bridging header depends.
122127
void ModuleDependencies::addBridgingModuleDependency(
123128
StringRef module, llvm::StringSet<> &alreadyAddedModules) {

lib/DependencyScan/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
add_swift_host_library(swiftDependencyScan STATIC
44
DependencyScanningTool.cpp
5+
ModuleDependencyCacheSerialization.cpp
56
ScanDependencies.cpp
67
StringUtils.cpp)
78

0 commit comments

Comments
 (0)