Skip to content

Commit 70ff401

Browse files
committed
Swift: replace internal swift mangler with our own
Our mangler is split in two version: * `SwiftTrapMangler`, with the same behaviour as the previous `SwiftMangler`, constructing mangled names with trap label references * `SwiftRecursiveMangler` that replaces trap label references with recursive calls to its own `mangle` functions, effectively rolling out the entire chain of references The latter is used to create lazy trap file names. Hashing is used to avoid excessively long filenames.
1 parent ab3b87a commit 70ff401

File tree

7 files changed

+76
-62
lines changed

7 files changed

+76
-62
lines changed

swift/extractor/SwiftExtractor.cpp

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "swift/extractor/infra/file/Path.h"
1515
#include "swift/extractor/infra/SwiftLocationExtractor.h"
1616
#include "swift/extractor/infra/SwiftBodyEmissionStrategy.h"
17-
#include "swift/extractor/mangler/SwiftMangler.h"
1817
#include "swift/logging/SwiftAssert.h"
1918

2019
using namespace codeql;
@@ -49,32 +48,20 @@ static void archiveFile(const SwiftExtractorConfiguration& config, swift::Source
4948
}
5049
}
5150

52-
// TODO: This will be factored out/replaced with a simplified version of custom mangling
53-
static std::string mangledDeclName(const swift::ValueDecl& decl) {
54-
std::string_view moduleName = decl.getModuleContext()->getRealName().str();
55-
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
56-
if (decl.getKind() == swift::DeclKind::Module) {
57-
return std::string{moduleName};
58-
}
59-
swift::Mangle::ASTMangler mangler;
60-
if (decl.getKind() == swift::DeclKind::TypeAlias) {
61-
// In cases like this (when coming from PCM)
62-
// typealias CFXMLTree = CFTree
63-
// typealias CFXMLTreeRef = CFXMLTree
64-
// mangleAnyDecl mangles both CFXMLTree and CFXMLTreeRef into 'So12CFXMLTreeRefa'
65-
// which is not correct and causes inconsistencies. mangleEntity makes these two distinct
66-
// prefix adds a couple of special symbols, we don't necessary need them
67-
return mangler.mangleEntity(&decl);
68-
}
69-
if (decl.getKind() == swift::DeclKind::GenericTypeParam) {
70-
// internal mangling does not distinguish generic type parameters with the same name and
71-
// position of different functions. We prepend the context (that is, the function) to
72-
// circumvent that
73-
auto context = llvm::dyn_cast<swift::ValueDecl>(decl.getDeclContext()->getAsDecl());
74-
assert(context);
75-
return mangledDeclName(*context) + '_' + mangler.mangleAnyDecl(&decl, /* prefix = */ false);
51+
static std::string mangledDeclName(const swift::Decl& decl) {
52+
// SwiftRecursiveMangler mangled name cannot be used directly as it can be too long for file names
53+
// so we build some minimal human readable info for debuggability and append a hash
54+
auto ret = decl.getModuleContext()->getRealName().str().str();
55+
ret += '/';
56+
ret += swift::Decl::getKindName(decl.getKind());
57+
ret += '_';
58+
if (auto valueDecl = llvm::dyn_cast<swift::ValueDecl>(&decl); valueDecl && valueDecl->hasName()) {
59+
ret += valueDecl->getBaseName().userFacingName();
60+
ret += '_';
7661
}
77-
return mangler.mangleAnyDecl(&decl, /* prefix = */ false);
62+
SwiftRecursiveMangler mangler;
63+
ret += mangler.mangleDecl(decl).hash();
64+
return ret;
7865
}
7966

8067
static fs::path getFilename(swift::ModuleDecl& module,
@@ -84,20 +71,7 @@ static fs::path getFilename(swift::ModuleDecl& module,
8471
return resolvePath(primaryFile->getFilename());
8572
}
8673
if (lazyDeclaration) {
87-
// this code will be thrown away in the near future
88-
auto decl = llvm::dyn_cast<swift::ValueDecl>(lazyDeclaration);
89-
CODEQL_ASSERT(decl, "not a ValueDecl");
90-
auto mangled = mangledDeclName(*decl);
91-
// mangled name can be too long to use as a file name, so we can't use it directly
92-
mangled = picosha2::hash256_hex_string(mangled);
93-
std::string ret;
94-
ret += module.getRealName().str();
95-
ret += '_';
96-
ret += decl->getBaseName().userFacingName();
97-
ret += '_';
98-
// half a SHA2 is enough
99-
ret += std::string_view(mangled).substr(0, mangled.size() / 2);
100-
return ret;
74+
return mangledDeclName(*lazyDeclaration);
10175
}
10276
// PCM clang module
10377
if (module.isNonSwiftModule()) {

swift/extractor/infra/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ swift_cc_library(
1111
"//swift/extractor/trap",
1212
"//swift/logging",
1313
"//swift/third_party/swift-llvm-support",
14+
"@picosha2",
1415
],
1516
)

swift/extractor/infra/SwiftMangledName.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
#include "swift/extractor/infra/SwiftMangledName.h"
22
#include "absl/strings/str_cat.h"
33

4+
#include <picosha2.h>
5+
46
namespace codeql {
57

8+
std::string SwiftMangledName::hash() const {
9+
auto ret = picosha2::hash256_hex_string(value);
10+
// half a hash is already enough for disambuiguation
11+
ret.resize(ret.size() / 2);
12+
return ret;
13+
}
14+
615
SwiftMangledName& SwiftMangledName::operator<<(UntypedTrapLabel label) & {
716
absl::StrAppend(&value, "{", label.str(), "}");
817
return *this;

swift/extractor/infra/SwiftMangledName.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class SwiftMangledName {
1616
explicit operator bool() const { return !value.empty(); }
1717

1818
const std::string& str() const { return value; }
19+
operator std::string_view() const { return value; }
20+
21+
std::string hash() const;
1922

2023
// let's avoid copying as long as we don't need it
2124
SwiftMangledName() = default;
@@ -29,7 +32,6 @@ class SwiftMangledName {
2932
(operator<<(std::forward<Args>(args)), ...);
3033
}
3134

32-
// streaming labels or ints into a SwiftMangledName just appends them
3335
SwiftMangledName& operator<<(UntypedTrapLabel label) &;
3436
SwiftMangledName& operator<<(unsigned i) &;
3537

@@ -46,11 +48,6 @@ class SwiftMangledName {
4648
return *this;
4749
}
4850

49-
SwiftMangledName& operator<<(const SwiftMangledName& other) {
50-
value += other.value;
51-
return *this;
52-
}
53-
5451
template <typename T>
5552
SwiftMangledName&& operator<<(T&& arg) && {
5653
return std::move(operator<<(std::forward<T>(arg)));

swift/extractor/mangler/SwiftMangler.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,6 @@ std::string_view getTypeKindStr(const swift::TypeBase* type) {
3838

3939
} // namespace
4040

41-
template <typename E>
42-
UntypedTrapLabel SwiftMangler::fetch(E&& e) {
43-
auto ret = dispatcher.fetchLabel(std::forward<E>(e));
44-
// TODO use a generic logging handle for Swift entities here, once it's available
45-
CODEQL_ASSERT(ret.valid(), "using an undefined label in mangling");
46-
return ret;
47-
}
48-
4941
SwiftMangledName SwiftMangler::initMangled(const swift::TypeBase* type) {
5042
return {getTypeKindStr(type), '_'};
5143
}
@@ -373,3 +365,29 @@ SwiftMangledName SwiftMangler::visitParametrizedProtocolType(
373365
ret << '>';
374366
return ret;
375367
}
368+
369+
namespace {
370+
template <typename E>
371+
UntypedTrapLabel fetchLabel(SwiftDispatcher& dispatcher, const E* e) {
372+
auto ret = dispatcher.fetchLabel(e);
373+
// TODO use a generic logging handle for Swift entities here, once it's available
374+
CODEQL_ASSERT(ret.valid(), "using an undefined label in mangling");
375+
return ret;
376+
}
377+
} // namespace
378+
379+
SwiftMangledName SwiftTrapMangler::fetch(const swift::Decl* decl) {
380+
return {fetchLabel(dispatcher, decl)};
381+
}
382+
383+
SwiftMangledName SwiftTrapMangler::fetch(const swift::TypeBase* type) {
384+
return {fetchLabel(dispatcher, type)};
385+
}
386+
387+
SwiftMangledName SwiftRecursiveMangler::fetch(const swift::Decl* decl) {
388+
return mangleDecl(*decl).hash();
389+
}
390+
391+
SwiftMangledName SwiftRecursiveMangler::fetch(const swift::TypeBase* type) {
392+
return mangleType(*type).hash();
393+
}

swift/extractor/mangler/SwiftMangler.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
3636
using DeclVisitor = swift::DeclVisitor<SwiftMangler, SwiftMangledName>;
3737

3838
public:
39-
explicit SwiftMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
39+
virtual ~SwiftMangler() = default;
4040

4141
static SwiftMangledName mangleModuleName(std::string_view name);
4242

@@ -104,18 +104,33 @@ class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
104104
SwiftMangledName visitParametrizedProtocolType(const swift::ParameterizedProtocolType* type);
105105

106106
private:
107-
template <typename E>
108-
UntypedTrapLabel fetch(E&& e);
107+
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
108+
109+
virtual SwiftMangledName fetch(const swift::Decl* decl) = 0;
110+
virtual SwiftMangledName fetch(const swift::TypeBase* type) = 0;
111+
SwiftMangledName fetch(swift::Type type) { return fetch(type.getPointer()); }
109112

113+
void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
114+
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
110115
static SwiftMangledName initMangled(const swift::TypeBase* type);
111116
SwiftMangledName initMangled(const swift::Decl* decl);
112117
SwiftMangledName visitTypeDiscriminatedValueDecl(const swift::ValueDecl* decl);
118+
};
119+
120+
class SwiftTrapMangler : public SwiftMangler {
121+
public:
122+
explicit SwiftTrapMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
123+
124+
private:
125+
SwiftMangledName fetch(const swift::Decl* decl) override;
126+
SwiftMangledName fetch(const swift::TypeBase* type) override;
113127

114-
swift::Mangle::ASTMangler mangler;
115128
SwiftDispatcher& dispatcher;
116-
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
117-
void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
118-
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
129+
};
130+
131+
class SwiftRecursiveMangler : public SwiftMangler {
132+
SwiftMangledName fetch(const swift::Decl* decl) override;
133+
SwiftMangledName fetch(const swift::TypeBase* type) override;
119134
};
120135

121136
} // namespace codeql

swift/extractor/translators/SwiftVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class SwiftVisitor : private SwiftDispatcher {
5858
StmtTranslator stmtTranslator{*this};
5959
TypeTranslator typeTranslator{*this};
6060
PatternTranslator patternTranslator{*this};
61-
SwiftMangler mangler{*this};
61+
SwiftTrapMangler mangler{*this};
6262
};
6363

6464
} // namespace codeql

0 commit comments

Comments
 (0)