Skip to content

Commit 13f2cf9

Browse files
authored
Merge pull request #9922 from github/redsun82/swift-precompiled-modules-are-not-extracted
Swift: extract precompiled swiftmodule files
2 parents 593ce01 + daf1fa3 commit 13f2cf9

File tree

10 files changed

+83
-42
lines changed

10 files changed

+83
-42
lines changed

swift/extractor/BUILD.bazel

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ load("//swift:rules.bzl", "swift_cc_binary")
22

33
swift_cc_binary(
44
name = "extractor",
5-
srcs = [
6-
"SwiftOutputRewrite.cpp",
7-
"SwiftOutputRewrite.h",
8-
"SwiftExtractor.cpp",
9-
"SwiftExtractor.h",
10-
"SwiftExtractorConfiguration.h",
11-
"main.cpp",
12-
],
5+
srcs = glob([
6+
"*.h",
7+
"*.cpp",
8+
]),
139
visibility = ["//swift:__pkg__"],
1410
deps = [
1511
"//swift/extractor/infra",

swift/extractor/SwiftExtractor.cpp

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "swift/extractor/trap/generated/TrapClasses.h"
1515
#include "swift/extractor/trap/TrapDomain.h"
1616
#include "swift/extractor/visitors/SwiftVisitor.h"
17-
#include "swift/extractor/infra/TargetFile.h"
17+
#include "swift/extractor/TargetTrapFile.h"
1818

1919
using namespace codeql;
2020
using namespace std::string_literals;
@@ -56,8 +56,10 @@ static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* pri
5656
}
5757
// PCM clang module
5858
if (module.isNonSwiftModule()) {
59-
// Several modules with different name might come from .pcm (clang module) files
59+
// Several modules with different names might come from .pcm (clang module) files
6060
// In this case we want to differentiate them
61+
// Moreover, pcm files may come from caches located in different directories, but are
62+
// unambiguously identified by the base file name, so we can discard the absolute directory
6163
std::string filename = "/pcms/"s + llvm::sys::path::filename(module.getModuleFilename()).str();
6264
filename += "-";
6365
filename += module.getName().str();
@@ -78,20 +80,6 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
7880
return ret;
7981
}
8082

81-
static void dumpArgs(TargetFile& out, const SwiftExtractorConfiguration& config) {
82-
out << "/* extractor-args:\n";
83-
for (const auto& opt : config.frontendOptions) {
84-
out << " " << std::quoted(opt) << " \\\n";
85-
}
86-
out << "\n*/\n";
87-
88-
out << "/* swift-frontend-args:\n";
89-
for (const auto& opt : config.patchedFrontendOptions) {
90-
out << " " << std::quoted(opt) << " \\\n";
91-
}
92-
out << "\n*/\n";
93-
}
94-
9583
static void extractDeclarations(const SwiftExtractorConfiguration& config,
9684
swift::CompilerInstance& compiler,
9785
swift::ModuleDecl& module,
@@ -101,12 +89,11 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
10189
// The extractor can be called several times from different processes with
10290
// the same input file(s). Using `TargetFile` the first process will win, and the following
10391
// will just skip the work
104-
auto trapTarget = TargetFile::create(filename + ".trap", config.trapDir, config.getTempTrapDir());
92+
auto trapTarget = createTargetTrapFile(config, filename);
10593
if (!trapTarget) {
10694
// another process arrived first, nothing to do for us
10795
return;
10896
}
109-
dumpArgs(*trapTarget, config);
11097
TrapDomain trap{*trapTarget};
11198

11299
// TODO: remove this and recreate it with IPA when we have that
@@ -171,21 +158,21 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
171158
auto modules = collectModules(compiler);
172159

173160
for (auto& module : modules) {
174-
// We only extract system and builtin modules here as the other "user" modules can be built
175-
// during the build process and then re-used at a later stage. In this case, we extract the
176-
// user code twice: once during the module build in a form of a source file, and then as
177-
// a pre-built module during building of the dependent source files.
178-
if (module->isSystemModule() || module->isBuiltinModule()) {
179-
extractDeclarations(config, compiler, *module);
180-
} else {
181-
for (auto file : module->getFiles()) {
182-
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
183-
if (!sourceFile || inputFiles.count(sourceFile->getFilename().str()) == 0) {
184-
continue;
185-
}
186-
archiveFile(config, *sourceFile);
187-
extractDeclarations(config, compiler, *module, sourceFile);
161+
bool isFromSourceFile = false;
162+
for (auto file : module->getFiles()) {
163+
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
164+
if (!sourceFile) {
165+
continue;
166+
}
167+
isFromSourceFile = true;
168+
if (inputFiles.count(sourceFile->getFilename().str()) == 0) {
169+
continue;
188170
}
171+
archiveFile(config, *sourceFile);
172+
extractDeclarations(config, compiler, *module, sourceFile);
173+
}
174+
if (!isFromSourceFile) {
175+
extractDeclarations(config, compiler, *module);
189176
}
190177
}
191178
}

swift/extractor/SwiftExtractorConfiguration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <string>
44
#include <vector>
55

6+
#include "swift/extractor/infra/TargetFile.h"
7+
68
namespace codeql {
79
struct SwiftExtractorConfiguration {
810
// The location for storing TRAP files to be imported by CodeQL engine.
@@ -33,4 +35,5 @@ struct SwiftExtractorConfiguration {
3335
// overall extraction process.
3436
std::string getTempArtifactDir() const { return scratchDir + "/swift-extraction-artifacts"; }
3537
};
38+
3639
} // namespace codeql

swift/extractor/SwiftOutputRewrite.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "SwiftOutputRewrite.h"
22
#include "swift/extractor/SwiftExtractorConfiguration.h"
3+
#include "swift/extractor/TargetTrapFile.h"
34

45
#include <llvm/ADT/SmallString.h>
56
#include <llvm/Support/FileSystem.h>
@@ -163,7 +164,7 @@ static std::vector<std::string> computeModuleAliases(llvm::StringRef modulePath,
163164
namespace codeql {
164165

165166
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
166-
SwiftExtractorConfiguration& config,
167+
const SwiftExtractorConfiguration& config,
167168
std::vector<std::string>& CLIArgs) {
168169
std::unordered_map<std::string, std::string> remapping;
169170

@@ -324,4 +325,17 @@ std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& conf
324325
return overlays;
325326
}
326327

328+
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
329+
const std::unordered_map<std::string, std::string>& remapping) {
330+
for (const auto& [oldPath, newPath] : remapping) {
331+
if (llvm::StringRef(oldPath).endswith(".swiftmodule")) {
332+
if (auto target = createTargetTrapFile(config, oldPath)) {
333+
*target << "// trap file deliberately empty\n"
334+
"// this swiftmodule was created during the build, so its entities must have"
335+
" been extracted directly from source files";
336+
}
337+
}
338+
}
339+
}
340+
327341
} // namespace codeql

swift/extractor/SwiftOutputRewrite.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct SwiftExtractorConfiguration;
1313
// artifacts produced by the actual Swift compiler.
1414
// Returns the map containing remapping oldpath -> newPath.
1515
std::unordered_map<std::string, std::string> rewriteOutputsInPlace(
16-
SwiftExtractorConfiguration& config,
16+
const SwiftExtractorConfiguration& config,
1717
std::vector<std::string>& CLIArgs);
1818

1919
// Create directories for all the redirected new paths as the Swift compiler expects them to exist.
@@ -29,4 +29,7 @@ void storeRemappingForVFS(const SwiftExtractorConfiguration& config,
2929
// This is separate from storeRemappingForVFS as we also collect files produced by other processes.
3030
std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& config);
3131

32+
// Creates empty trap files for output swiftmodule files
33+
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
34+
const std::unordered_map<std::string, std::string>& remapping);
3235
} // namespace codeql

swift/extractor/TargetTrapFile.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "swift/extractor/TargetTrapFile.h"
2+
#include <iomanip>
3+
namespace codeql {
4+
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
5+
std::string_view target) {
6+
std::string trap{target};
7+
trap += ".trap";
8+
auto ret = TargetFile::create(trap, configuration.trapDir, configuration.getTempTrapDir());
9+
if (ret) {
10+
*ret << "/* extractor-args:\n";
11+
for (const auto& opt : configuration.frontendOptions) {
12+
*ret << " " << std::quoted(opt) << " \\\n";
13+
}
14+
*ret << "\n*/\n"
15+
"/* swift-frontend-args:\n";
16+
for (const auto& opt : configuration.patchedFrontendOptions) {
17+
*ret << " " << std::quoted(opt) << " \\\n";
18+
}
19+
*ret << "\n*/\n";
20+
}
21+
return ret;
22+
}
23+
} // namespace codeql

swift/extractor/TargetTrapFile.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include "swift/extractor/infra/TargetFile.h"
4+
#include "swift/extractor/SwiftExtractorConfiguration.h"
5+
6+
namespace codeql {
7+
8+
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
9+
std::string_view target);
10+
11+
} // namespace codeql

swift/extractor/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ int main(int argc, char** argv) {
6868
codeql::rewriteOutputsInPlace(configuration, configuration.patchedFrontendOptions);
6969
codeql::ensureDirectoriesForNewPathsExist(remapping);
7070
codeql::storeRemappingForVFS(configuration, remapping);
71+
codeql::lockOutputSwiftModuleTraps(configuration, remapping);
7172

7273
std::vector<const char*> args;
7374
for (auto& arg : configuration.patchedFrontendOptions) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
| file://:0:0:0:0 | A |
22
| file://:0:0:0:0 | B |
3+
| file://:0:0:0:0 | PackageDescription |
34
| file://:0:0:0:0 | main |
45
| file://:0:0:0:0 | partial_modules |

swift/integration-tests/runner.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ def main(opts):
6262
]
6363
if opts.check_databases:
6464
cmd.append("--check-databases")
65+
else:
66+
cmd.append("--no-check-databases")
6567
if opts.learn:
6668
cmd.append("--learn")
6769
cmd.extend(str(t.parent) for t in succesful_db_creation)

0 commit comments

Comments
 (0)