Skip to content

Commit ddef87f

Browse files
authored
Merge pull request github#10956 from github/redsun82/swift-linkage-awareness
Swift: disambuigate entities using linkage awareness on modules
2 parents 176b2ca + 4880ab4 commit ddef87f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+680
-114
lines changed

swift/extractor/SwiftExtractor.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
#include <swift/AST/SourceFile.h>
99
#include <swift/AST/Builtins.h>
1010

11-
#include "swift/extractor/trap/TrapDomain.h"
1211
#include "swift/extractor/translators/SwiftVisitor.h"
13-
#include "swift/extractor/TargetTrapFile.h"
12+
#include "swift/extractor/infra/TargetDomains.h"
1413
#include "swift/extractor/SwiftBuiltinSymbols.h"
1514
#include "swift/extractor/infra/file/Path.h"
1615

@@ -109,21 +108,24 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
109108
}
110109

111110
static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
112-
const SwiftExtractorConfiguration& config,
111+
SwiftExtractorState& state,
113112
swift::CompilerInstance& compiler,
114113
swift::ModuleDecl& module,
115114
swift::SourceFile* primaryFile = nullptr) {
116115
auto filename = getFilename(module, primaryFile);
116+
if (primaryFile) {
117+
state.sourceFiles.push_back(filename);
118+
}
117119

118120
// The extractor can be called several times from different processes with
119121
// the same input file(s). Using `TargetFile` the first process will win, and the following
120122
// will just skip the work
121-
auto trapTarget = createTargetTrapFile(config, filename);
122-
if (!trapTarget) {
123+
const auto trapType = primaryFile ? TrapType::source : TrapType::module;
124+
auto trap = createTargetTrapDomain(state, filename, trapType);
125+
if (!trap) {
123126
// another process arrived first, nothing to do for us
124127
return {};
125128
}
126-
TrapDomain trap{*trapTarget};
127129

128130
std::vector<swift::Token> comments;
129131
if (primaryFile && primaryFile->getBufferID().hasValue()) {
@@ -137,7 +139,7 @@ static std::unordered_set<swift::ModuleDecl*> extractDeclarations(
137139
}
138140
}
139141

140-
SwiftVisitor visitor(compiler.getSourceMgr(), trap, module, primaryFile);
142+
SwiftVisitor visitor(compiler.getSourceMgr(), *trap, module, primaryFile);
141143
auto topLevelDecls = getTopLevelDecls(module, primaryFile);
142144
for (auto decl : topLevelDecls) {
143145
visitor.extract(decl);
@@ -171,11 +173,10 @@ static std::vector<swift::ModuleDecl*> collectLoadedModules(swift::CompilerInsta
171173
return ret;
172174
}
173175

174-
void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
175-
swift::CompilerInstance& compiler) {
176+
void codeql::extractSwiftFiles(SwiftExtractorState& state, swift::CompilerInstance& compiler) {
176177
auto inputFiles = collectInputFilenames(compiler);
177178
std::vector<swift::ModuleDecl*> todo = collectLoadedModules(compiler);
178-
std::unordered_set<swift::ModuleDecl*> seen{todo.begin(), todo.end()};
179+
state.encounteredModules.insert(todo.begin(), todo.end());
179180

180181
while (!todo.empty()) {
181182
auto module = todo.back();
@@ -191,16 +192,16 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
191192
if (inputFiles.count(sourceFile->getFilename().str()) == 0) {
192193
continue;
193194
}
194-
archiveFile(config, *sourceFile);
195-
encounteredModules = extractDeclarations(config, compiler, *module, sourceFile);
195+
archiveFile(state.configuration, *sourceFile);
196+
encounteredModules = extractDeclarations(state, compiler, *module, sourceFile);
196197
}
197198
if (!isFromSourceFile) {
198-
encounteredModules = extractDeclarations(config, compiler, *module);
199+
encounteredModules = extractDeclarations(state, compiler, *module);
199200
}
200201
for (auto encountered : encounteredModules) {
201-
if (seen.count(encountered) == 0) {
202+
if (state.encounteredModules.count(encountered) == 0) {
202203
todo.push_back(encountered);
203-
seen.insert(encountered);
204+
state.encounteredModules.insert(encountered);
204205
}
205206
}
206207
}

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/TargetTrapFile.cpp

Lines changed: 0 additions & 18 deletions
This file was deleted.

swift/extractor/TargetTrapFile.h

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <unordered_set>
5+
#include <filesystem>
6+
7+
#include <swift/AST/Decl.h>
8+
9+
#include "swift/extractor/config/SwiftExtractorConfiguration.h"
10+
11+
namespace codeql {
12+
struct SwiftExtractorState {
13+
const SwiftExtractorConfiguration configuration;
14+
15+
// All the trap files related to this extraction. This may also include trap files generated in a
16+
// previous run but that this run requested as well. Paths are relative to `configuration.trapDir`
17+
std::vector<std::filesystem::path> traps;
18+
19+
// All modules encountered during this extractor run, which therefore are dependencies of the
20+
// outcomes of this run
21+
std::unordered_set<const swift::ModuleDecl*> encounteredModules;
22+
23+
std::vector<std::filesystem::path> sourceFiles;
24+
25+
// The path for the modules outputted by the underlying frontend run, ignoring path redirection
26+
std::vector<std::filesystem::path> originalOutputModules;
27+
};
28+
29+
} // namespace codeql

swift/extractor/infra/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ swift_cc_library(
66
hdrs = glob(["*.h"]),
77
visibility = ["//swift:__subpackages__"],
88
deps = [
9+
"//swift/extractor/config",
910
"//swift/extractor/infra/file",
1011
"//swift/extractor/trap",
1112
"//swift/third_party/swift-llvm-support",
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "swift/extractor/infra/TargetDomains.h"
2+
#include <iomanip>
3+
4+
namespace codeql {
5+
6+
static const char* typeToStr(TrapType type) {
7+
switch (type) {
8+
case TrapType::source:
9+
return "sources";
10+
case TrapType::module:
11+
return "modules";
12+
case TrapType::invocation:
13+
return "invocations";
14+
case TrapType::linkage:
15+
return "linkage";
16+
default:
17+
return "";
18+
}
19+
}
20+
21+
static std::filesystem::path getRelativeTrapPath(const std::filesystem::path& target,
22+
TrapType type,
23+
const char* extension = ".trap") {
24+
auto trap = typeToStr(type) / target.relative_path();
25+
trap += extension;
26+
return trap;
27+
}
28+
29+
std::filesystem::path getTrapPath(const SwiftExtractorState& state,
30+
const std::filesystem::path& target,
31+
TrapType type) {
32+
return state.configuration.trapDir / getRelativeTrapPath(target, type);
33+
}
34+
35+
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
36+
const std::filesystem::path& target,
37+
TrapType type) {
38+
if (target.empty()) {
39+
return std::nullopt;
40+
}
41+
auto trap = getRelativeTrapPath(target, type);
42+
auto ret =
43+
TargetFile::create(trap, state.configuration.trapDir, state.configuration.getTempTrapDir());
44+
state.traps.push_back(std::move(trap));
45+
if (ret) {
46+
*ret << "/* extractor-args:\n";
47+
for (const auto& opt : state.configuration.frontendOptions) {
48+
*ret << " " << std::quoted(opt) << " \\\n";
49+
}
50+
*ret << "\n*/\n";
51+
return TrapDomain{*std::move(ret)};
52+
}
53+
return std::nullopt;
54+
}
55+
56+
namespace {
57+
template <typename Domain>
58+
std::optional<Domain> createTarget(const SwiftExtractorState& state,
59+
const std::filesystem::path& target,
60+
const char* extension) {
61+
if (target.empty()) {
62+
return std::nullopt;
63+
}
64+
auto file = getRelativeTrapPath(target, TrapType::linkage, extension);
65+
auto ret =
66+
TargetFile::create(file, state.configuration.trapDir, state.configuration.getTempTrapDir());
67+
if (ret) {
68+
return Domain{*std::move(ret)};
69+
}
70+
return std::nullopt;
71+
}
72+
73+
} // namespace
74+
75+
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
76+
const std::filesystem::path& target) {
77+
return createTarget<LinkDomain>(state, target, ".link");
78+
}
79+
80+
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
81+
const std::filesystem::path& target) {
82+
return createTarget<ObjectDomain>(state, target, ".odep");
83+
}
84+
85+
} // namespace codeql

swift/extractor/infra/TargetDomains.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include "swift/extractor/trap/TrapDomain.h"
4+
#include "swift/extractor/trap/LinkDomain.h"
5+
#include "swift/extractor/trap/ObjectDomain.h"
6+
#include "swift/extractor/config/SwiftExtractorState.h"
7+
8+
namespace codeql {
9+
10+
enum class TrapType {
11+
source,
12+
module,
13+
invocation,
14+
linkage,
15+
};
16+
17+
std::filesystem::path getTrapPath(const SwiftExtractorState& state,
18+
const std::filesystem::path& target,
19+
TrapType type);
20+
21+
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
22+
const std::filesystem::path& target,
23+
TrapType type);
24+
25+
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
26+
const std::filesystem::path& target);
27+
28+
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
29+
const std::filesystem::path& target);
30+
31+
} // namespace codeql

swift/extractor/infra/file/Path.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ std::filesystem::path resolvePath(const std::filesystem::path& path) {
2121
std::filesystem::path ret = {};
2222
static const auto canonicalize = shouldCanonicalize();
2323
if (canonicalize) {
24-
ret = std::filesystem::canonical(path, ec);
24+
ret = std::filesystem::weakly_canonical(path, ec);
2525
} else {
2626
ret = std::filesystem::absolute(path, ec);
2727
}

swift/extractor/invocation/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ swift_cc_library(
66
hdrs = glob(["*.h"]),
77
visibility = ["//swift:__subpackages__"],
88
deps = [
9+
"//swift/extractor/config",
910
"//swift/extractor/infra",
11+
"//swift/extractor/remapping",
1012
],
1113
)

0 commit comments

Comments
 (0)