Skip to content

Commit c7f13f1

Browse files
committed
Swift: collect TRAP files related to an extractor run
In order to do this a mutable `SwiftExtractorState` is introduced.
1 parent c31c515 commit c7f13f1

File tree

6 files changed

+47
-29
lines changed

6 files changed

+47
-29
lines changed

swift/extractor/SwiftExtractor.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
109109
}
110110

111111
static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
112-
const SwiftExtractorConfiguration& config,
112+
SwiftExtractorState& state,
113113
swift::CompilerInstance& compiler,
114114
swift::ModuleDecl& module,
115115
swift::SourceFile* primaryFile = nullptr) {
@@ -118,7 +118,7 @@ static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
118118
// The extractor can be called several times from different processes with
119119
// the same input file(s). Using `TargetFile` the first process will win, and the following
120120
// will just skip the work
121-
auto trap = createTargetTrapDomain(config, filename);
121+
auto trap = createTargetTrapDomain(state, filename);
122122
if (!trap) {
123123
// another process arrived first, nothing to do for us
124124
return {};
@@ -170,8 +170,7 @@ static std::vector<swift::ModuleDecl*> collectLoadedModules(swift::CompilerInsta
170170
return ret;
171171
}
172172

173-
void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
174-
swift::CompilerInstance& compiler) {
173+
void codeql::extractSwiftFiles(SwiftExtractorState& state, swift::CompilerInstance& compiler) {
175174
auto inputFiles = collectInputFilenames(compiler);
176175
std::vector<swift::ModuleDecl*> todo = collectLoadedModules(compiler);
177176
std::unordered_set<swift::ModuleDecl*> seen{todo.begin(), todo.end()};
@@ -190,11 +189,11 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
190189
if (inputFiles.count(sourceFile->getFilename().str()) == 0) {
191190
continue;
192191
}
193-
archiveFile(config, *sourceFile);
194-
encounteredModules = extractDeclarations(config, compiler, *module, sourceFile);
192+
archiveFile(state.configuration, *sourceFile);
193+
encounteredModules = extractDeclarations(state, compiler, *module, sourceFile);
195194
}
196195
if (!isFromSourceFile) {
197-
encounteredModules = extractDeclarations(config, compiler, *module);
196+
encounteredModules = extractDeclarations(state, compiler, *module);
198197
}
199198
for (auto encountered : encounteredModules) {
200199
if (seen.count(encountered) == 0) {

swift/extractor/SwiftExtractor.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
#pragma once
22

3-
#include "swift/extractor/config/SwiftExtractorConfiguration.h"
3+
#include "swift/extractor/config/SwiftExtractorState.h"
44
#include <swift/AST/SourceFile.h>
55
#include <swift/Frontend/Frontend.h>
66
#include <memory>
77

88
namespace codeql {
9-
void extractSwiftFiles(const SwiftExtractorConfiguration& config,
10-
swift::CompilerInstance& compiler);
9+
void extractSwiftFiles(SwiftExtractorState& state, swift::CompilerInstance& compiler);
1110
} // namespace codeql

swift/extractor/TargetTrapDomain.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#include "swift/extractor/TargetTrapDomain.h"
22
#include <iomanip>
33
namespace codeql {
4-
std::optional<TrapDomain> createTargetTrapDomain(const SwiftExtractorConfiguration& configuration,
4+
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
55
const std::filesystem::path& target) {
66
auto trap = target;
77
trap += ".trap";
8-
if (auto ret = TargetFile::create(trap, configuration.trapDir, configuration.getTempTrapDir())) {
8+
state.traps.push_back(trap.relative_path());
9+
if (auto ret = TargetFile::create(trap, state.configuration.trapDir,
10+
state.configuration.getTempTrapDir())) {
911
*ret << "/* extractor-args:\n";
10-
for (const auto& opt : configuration.frontendOptions) {
12+
for (const auto& opt : state.configuration.frontendOptions) {
1113
*ret << " " << std::quoted(opt) << " \\\n";
1214
}
1315
*ret << "\n*/\n";

swift/extractor/TargetTrapDomain.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#pragma once
22

33
#include "swift/extractor/trap/TrapDomain.h"
4-
#include "swift/extractor/config/SwiftExtractorConfiguration.h"
4+
#include "swift/extractor/config/SwiftExtractorState.h"
55

66
namespace codeql {
77

8-
std::optional<TrapDomain> createTargetTrapDomain(const SwiftExtractorConfiguration& configuration,
8+
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
99
const std::filesystem::path& target);
1010

1111
} // namespace codeql
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <filesystem>
5+
6+
#include <swift/AST/Decl.h>
7+
8+
#include "swift/extractor/config/SwiftExtractorConfiguration.h"
9+
10+
namespace codeql {
11+
struct SwiftExtractorState {
12+
const SwiftExtractorConfiguration configuration;
13+
14+
// All the trap files related to this extraction. This may also include trap files generated in a
15+
// previous run but that this run requested as well. Paths are relative to `configuration.trapDir`
16+
std::vector<std::filesystem::path> traps;
17+
};
18+
19+
} // namespace codeql

swift/extractor/main.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
using namespace std::string_literals;
2222

2323
// must be called before processFrontendOptions modifies output paths
24-
static void lockOutputSwiftModuleTraps(const codeql::SwiftExtractorConfiguration& config,
24+
static void lockOutputSwiftModuleTraps(codeql::SwiftExtractorState& state,
2525
const swift::FrontendOptions& options) {
2626
for (const auto& input : options.InputsAndOutputs.getAllInputs()) {
2727
if (const auto& module = input.getPrimarySpecificPaths().SupplementaryOutputs.ModuleOutputPath;
2828
!module.empty()) {
29-
if (auto target = codeql::createTargetTrapDomain(config, codeql::resolvePath(module))) {
29+
if (auto target = codeql::createTargetTrapDomain(state, codeql::resolvePath(module))) {
3030
target->emit("// trap file deliberately empty\n"
3131
"// this swiftmodule was created during the build, so its entities must have"
3232
" been extracted directly from source files");
@@ -65,18 +65,18 @@ static void processFrontendOptions(swift::FrontendOptions& options) {
6565
}
6666
}
6767

68+
codeql::TrapDomain invocationTrapDomain(codeql::SwiftExtractorState& state);
69+
6870
// This is part of the swiftFrontendTool interface, we hook into the
6971
// compilation pipeline and extract files after the Swift frontend performed
7072
// semantic analysis
7173
class Observer : public swift::FrontendObserver {
7274
public:
73-
explicit Observer(const codeql::SwiftExtractorConfiguration& config,
74-
codeql::SwiftDiagnosticsConsumer& diagConsumer)
75-
: config{config}, diagConsumer{diagConsumer} {}
75+
explicit Observer(const codeql::SwiftExtractorConfiguration& config) : state{config} {}
7676

7777
void parsedArgs(swift::CompilerInvocation& invocation) override {
7878
auto& options = invocation.getFrontendOptions();
79-
lockOutputSwiftModuleTraps(config, options);
79+
lockOutputSwiftModuleTraps(state, options);
8080
processFrontendOptions(options);
8181
}
8282

@@ -85,12 +85,13 @@ class Observer : public swift::FrontendObserver {
8585
}
8686

8787
void performedSemanticAnalysis(swift::CompilerInstance& compiler) override {
88-
codeql::extractSwiftFiles(config, compiler);
88+
codeql::extractSwiftFiles(state, compiler);
8989
}
9090

9191
private:
92-
const codeql::SwiftExtractorConfiguration& config;
93-
codeql::SwiftDiagnosticsConsumer& diagConsumer;
92+
codeql::SwiftExtractorState state;
93+
codeql::TrapDomain invocationTrap{invocationTrapDomain(state)};
94+
codeql::SwiftDiagnosticsConsumer diagConsumer{invocationTrap};
9495
};
9596

9697
static std::string getenv_or(const char* envvar, const std::string& def) {
@@ -145,11 +146,11 @@ static void checkWhetherToRunUnderTool(int argc, char* const* argv) {
145146

146147
// Creates a target file that should store per-invocation info, e.g. compilation args,
147148
// compilations, diagnostics, etc.
148-
codeql::TrapDomain invocationTrapDomain(const codeql::SwiftExtractorConfiguration& configuration) {
149+
codeql::TrapDomain invocationTrapDomain(codeql::SwiftExtractorState& state) {
149150
auto timestamp = std::chrono::system_clock::now().time_since_epoch().count();
150151
auto filename = std::to_string(timestamp) + '-' + std::to_string(getpid());
151152
auto target = std::filesystem::path("invocations") / std::filesystem::path(filename);
152-
auto maybeDomain = codeql::createTargetTrapDomain(configuration, target);
153+
auto maybeDomain = codeql::createTargetTrapDomain(state, target);
153154
if (!maybeDomain) {
154155
std::cerr << "Cannot create invocation trap file: " << target << "\n";
155156
abort();
@@ -183,9 +184,7 @@ int main(int argc, char** argv) {
183184

184185
auto openInterception = codeql::setupFileInterception(configuration);
185186

186-
auto invocationDomain = invocationTrapDomain(configuration);
187-
codeql::SwiftDiagnosticsConsumer diagConsumer(invocationDomain);
188-
Observer observer(configuration, diagConsumer);
187+
Observer observer(configuration);
189188
int frontend_rc = swift::performFrontend(configuration.frontendOptions, "swift-extractor",
190189
(void*)main, &observer);
191190

0 commit comments

Comments
 (0)