12
12
13
13
#include " swift/extractor/SwiftExtractor.h"
14
14
#include " swift/extractor/TargetTrapFile.h"
15
- #include " swift/extractor/remapping/SwiftOutputRewrite.h"
16
- #include " swift/extractor/remapping/SwiftOpenInterception.h"
15
+ #include " swift/extractor/remapping/SwiftFileInterception.h"
17
16
#include " swift/extractor/invocation/SwiftDiagnosticsConsumer.h"
18
17
#include " swift/extractor/trap/TrapDomain.h"
19
18
20
19
using namespace std ::string_literals;
21
20
21
+ static void lockOutputSwiftModuleTraps (const codeql::SwiftExtractorConfiguration& config,
22
+ const swift::CompilerInstance& compiler) {
23
+ std::filesystem::path output = compiler.getInvocation ().getOutputFilename ();
24
+ if (output.extension () == " .swiftmodule" ) {
25
+ if (auto target = codeql::createTargetTrapFile (config, output)) {
26
+ *target << " // trap file deliberately empty\n "
27
+ " // this swiftmodule was created during the build, so its entities must have"
28
+ " been extracted directly from source files" ;
29
+ }
30
+ }
31
+ }
32
+
33
+ static void modifyFrontendOptions (swift::FrontendOptions& options) {
34
+ using Action = swift::FrontendOptions::ActionType;
35
+ switch (options.RequestedAction ) {
36
+ case Action::EmitModuleOnly:
37
+ case Action::MergeModules:
38
+ case Action::CompileModuleFromInterface:
39
+ // for module emission actions, we redirect the output to our internal artifact storage
40
+ {
41
+ swift::SupplementaryOutputPaths paths;
42
+ paths.ModuleOutputPath =
43
+ codeql::redirect (options.InputsAndOutputs .getSingleOutputFilename ()).string ();
44
+ options.InputsAndOutputs .setMainAndSupplementaryOutputs (std::vector{paths.ModuleOutputPath },
45
+ std::vector{paths});
46
+ return ;
47
+ }
48
+ case Action::EmitObject:
49
+ // for object emission, we do a type check pass instead, muting output but getting the sema
50
+ // phase to run in order to extract everything
51
+ options.RequestedAction = Action::Typecheck;
52
+ return ;
53
+ case Action::PrintVersion:
54
+ case Action::DumpAST:
55
+ case Action::PrintAST:
56
+ case Action::PrintASTDecl:
57
+ // these actions are nice to have on the extractor for debugging, so we preserve them. Also,
58
+ // version printing is used by CI to match up the correct compiler version
59
+ return ;
60
+ default :
61
+ // otherwise, do nothing (the closest action to doing nothing is printing the version)
62
+ options.RequestedAction = Action::PrintVersion;
63
+ break ;
64
+ }
65
+ }
66
+
22
67
// This is part of the swiftFrontendTool interface, we hook into the
23
68
// compilation pipeline and extract files after the Swift frontend performed
24
69
// semantic analysis
@@ -28,8 +73,13 @@ class Observer : public swift::FrontendObserver {
28
73
codeql::SwiftDiagnosticsConsumer& diagConsumer)
29
74
: config{config}, diagConsumer{diagConsumer} {}
30
75
76
+ void parsedArgs (swift::CompilerInvocation& invocation) override {
77
+ modifyFrontendOptions (invocation.getFrontendOptions ());
78
+ }
79
+
31
80
void configuredCompiler (swift::CompilerInstance& instance) override {
32
81
instance.addDiagnosticConsumer (&diagConsumer);
82
+ lockOutputSwiftModuleTraps (config, instance);
33
83
}
34
84
35
85
void performedSemanticAnalysis (swift::CompilerInstance& compiler) override {
@@ -48,19 +98,6 @@ static std::string getenv_or(const char* envvar, const std::string& def) {
48
98
return def;
49
99
}
50
100
51
- static void lockOutputSwiftModuleTraps (const codeql::SwiftExtractorConfiguration& config,
52
- const codeql::PathRemapping& remapping) {
53
- for (const auto & [oldPath, newPath] : remapping) {
54
- if (oldPath.extension () == " .swiftmodule" ) {
55
- if (auto target = codeql::createTargetTrapFile (config, oldPath)) {
56
- *target << " // trap file deliberately empty\n "
57
- " // this swiftmodule was created during the build, so its entities must have"
58
- " been extracted directly from source files" ;
59
- }
60
- }
61
- }
62
- }
63
-
64
101
static bool checkRunUnderFilter (int argc, char * const * argv) {
65
102
auto runUnderFilter = getenv (" CODEQL_EXTRACTOR_SWIFT_RUN_UNDER_FILTER" );
66
103
if (runUnderFilter == nullptr ) {
@@ -106,7 +143,7 @@ static void checkWhetherToRunUnderTool(int argc, char* const* argv) {
106
143
107
144
// Creates a target file that should store per-invocation info, e.g. compilation args,
108
145
// compilations, diagnostics, etc.
109
- codeql::TargetFile invocationTargetFile (codeql::SwiftExtractorConfiguration& configuration) {
146
+ codeql::TargetFile invocationTargetFile (const codeql::SwiftExtractorConfiguration& configuration) {
110
147
auto timestamp = std::chrono::system_clock::now ().time_since_epoch ().count ();
111
148
auto filename = std::to_string (timestamp) + ' -' + std::to_string (getpid ());
112
149
auto target = std::filesystem::path (" invocations" ) / std::filesystem::path (filename);
@@ -118,6 +155,15 @@ codeql::TargetFile invocationTargetFile(codeql::SwiftExtractorConfiguration& con
118
155
return std::move (maybeFile.value ());
119
156
}
120
157
158
+ codeql::SwiftExtractorConfiguration configure (int argc, char ** argv) {
159
+ codeql::SwiftExtractorConfiguration configuration{};
160
+ configuration.trapDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_TRAP_DIR" , " ." );
161
+ configuration.sourceArchiveDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_SOURCE_ARCHIVE_DIR" , " ." );
162
+ configuration.scratchDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_SCRATCH_DIR" , " ." );
163
+ configuration.frontendOptions .assign (argv + 1 , argv + argc);
164
+ return configuration;
165
+ }
166
+
121
167
int main (int argc, char ** argv) {
122
168
checkWhetherToRunUnderTool (argc, argv);
123
169
@@ -130,36 +176,16 @@ int main(int argc, char** argv) {
130
176
PROGRAM_START (argc, argv);
131
177
INITIALIZE_LLVM ();
132
178
133
- codeql::SwiftExtractorConfiguration configuration{};
134
- configuration.trapDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_TRAP_DIR" , " ." );
135
- configuration.sourceArchiveDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_SOURCE_ARCHIVE_DIR" , " ." );
136
- configuration.scratchDir = getenv_or (" CODEQL_EXTRACTOR_SWIFT_SCRATCH_DIR" , " ." );
137
-
138
- codeql::initRemapping (configuration.getTempArtifactDir ());
139
-
140
- configuration.frontendOptions .reserve (argc - 1 );
141
- for (int i = 1 ; i < argc; i++) {
142
- configuration.frontendOptions .push_back (argv[i]);
143
- }
144
- configuration.patchedFrontendOptions = configuration.frontendOptions ;
145
-
146
- auto remapping = codeql::rewriteOutputsInPlace (configuration.getTempArtifactDir (),
147
- configuration.patchedFrontendOptions );
148
- codeql::ensureDirectoriesForNewPathsExist (remapping);
149
- lockOutputSwiftModuleTraps (configuration, remapping);
179
+ const auto configuration = configure (argc, argv);
150
180
151
- std::vector<const char *> args;
152
- for (auto & arg : configuration.patchedFrontendOptions ) {
153
- args.push_back (arg.c_str ());
154
- }
181
+ auto openInterception = codeql::setupFileInterception (configuration.getTempArtifactDir ());
155
182
156
183
auto invocationTrapFile = invocationTargetFile (configuration);
157
184
codeql::TrapDomain invocationDomain (invocationTrapFile);
158
185
codeql::SwiftDiagnosticsConsumer diagConsumer (invocationDomain);
159
186
Observer observer (configuration, diagConsumer);
160
- int frontend_rc = swift::performFrontend (args, " swift-extractor" , (void *)main, &observer);
161
-
162
- codeql::finalizeRemapping (remapping);
187
+ int frontend_rc = swift::performFrontend (configuration.frontendOptions , " swift-extractor" ,
188
+ (void *)main, &observer);
163
189
164
190
return frontend_rc;
165
191
}
0 commit comments