-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathSwiftMangler.h
146 lines (119 loc) · 7.09 KB
/
SwiftMangler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once
#include <swift/AST/ASTMangler.h>
#include <swift/AST/Types.h>
#include <swift/AST/ASTVisitor.h>
#include <swift/AST/TypeVisitor.h>
#include <variant>
#include "swift/extractor/trap/TrapLabel.h"
#include "swift/extractor/infra/SwiftMangledName.h"
#include <optional>
#include <unordered_map>
namespace codeql {
class SwiftDispatcher;
// This class is tasked with assigning unique names to entities that need it (non-local
// declarations and types), to be used as trap keys.
// This uses the Template Method design pattern (or Non-Virtual Interface). The actual behavior
// when the identity depends on some other entity (like the parent of a declaration, or the
// declaration introducing a user type) depends on a private virtual fetch method. See below for
// the specific implementations.
//
// * all names are prefixed with the name of the entity class (for example `ParamDecl_`)
// * declarations usually use a fetch of their declaration context as first element, followed
// by whatever distinguishes them within that context (the name, or the signature for function)
// * user defined types have a name that is a simple wrapper around a fetch of their declaration
class SwiftMangler : private swift::TypeVisitor<SwiftMangler, SwiftMangledName>,
private swift::DeclVisitor<SwiftMangler, SwiftMangledName> {
using TypeVisitor = swift::TypeVisitor<SwiftMangler, SwiftMangledName>;
using DeclVisitor = swift::DeclVisitor<SwiftMangler, SwiftMangledName>;
public:
virtual ~SwiftMangler() = default;
static SwiftMangledName mangleModuleName(std::string_view name);
SwiftMangledName mangleDecl(const swift::Decl& decl) {
return DeclVisitor::visit(const_cast<swift::Decl*>(&decl));
}
SwiftMangledName mangleType(const swift::TypeBase& type) {
return TypeVisitor::visit(const_cast<swift::TypeBase*>(&type));
}
private:
friend TypeVisitor;
friend DeclVisitor;
// assign no name by default
static SwiftMangledName visitDecl(const swift::Decl* decl) { return {}; }
// current default, falling back to internal mangling
SwiftMangledName visitValueDecl(const swift::ValueDecl* decl, bool force = false);
SwiftMangledName visitModuleDecl(const swift::ModuleDecl* decl);
SwiftMangledName visitExtensionDecl(const swift::ExtensionDecl* decl);
SwiftMangledName visitAbstractFunctionDecl(const swift::AbstractFunctionDecl* decl);
SwiftMangledName visitSubscriptDecl(const swift::SubscriptDecl* decl);
SwiftMangledName visitVarDecl(const swift::VarDecl* decl);
SwiftMangledName visitGenericTypeParamDecl(const swift::GenericTypeParamDecl* decl);
SwiftMangledName visitAssociatedTypeDecl(const swift::AssociatedTypeDecl* decl);
// default fallback for non mangled types. This covers types that should not appear in normal
// successful extractor runs, like ErrorType
SwiftMangledName visitType(const swift::TypeBase* type);
SwiftMangledName visitModuleType(const swift::ModuleType* type);
SwiftMangledName visitTupleType(const swift::TupleType* type);
SwiftMangledName visitBuiltinType(const swift::BuiltinType* type);
SwiftMangledName visitAnyGenericType(const swift::AnyGenericType* type);
// shouldn't be required, but they forgot to link `NominalType` to its direct superclass
// in swift/AST/TypeNodes.def, so we need to chain the call manually
SwiftMangledName visitNominalType(const swift::NominalType* type) {
return visitAnyGenericType(type);
}
SwiftMangledName visitBoundGenericType(const swift::BoundGenericType* type);
SwiftMangledName visitAnyFunctionType(const swift::AnyFunctionType* type);
SwiftMangledName visitGenericFunctionType(const swift::GenericFunctionType* type);
SwiftMangledName visitGenericTypeParamType(const swift::GenericTypeParamType* type);
SwiftMangledName visitAnyMetatypeType(const swift::AnyMetatypeType* type);
SwiftMangledName visitDependentMemberType(const swift::DependentMemberType* type);
SwiftMangledName visitInOutType(const swift::InOutType* type);
SwiftMangledName visitExistentialType(const swift::ExistentialType* type);
SwiftMangledName visitUnarySyntaxSugarType(const swift::UnarySyntaxSugarType* type);
SwiftMangledName visitDictionaryType(const swift::DictionaryType* type);
SwiftMangledName visitTypeAliasType(const swift::TypeAliasType* type);
SwiftMangledName visitArchetypeType(const swift::ArchetypeType* type);
SwiftMangledName visitOpaqueTypeArchetypeType(const swift::OpaqueTypeArchetypeType* type);
SwiftMangledName visitOpenedArchetypeType(const swift::OpenedArchetypeType* type);
SwiftMangledName visitProtocolCompositionType(const swift::ProtocolCompositionType* type);
SwiftMangledName visitParenType(const swift::ParenType* type);
SwiftMangledName visitLValueType(const swift::LValueType* type);
SwiftMangledName visitDynamicSelfType(const swift::DynamicSelfType* type);
SwiftMangledName visitUnboundGenericType(const swift::UnboundGenericType* type);
SwiftMangledName visitReferenceStorageType(const swift::ReferenceStorageType* type);
SwiftMangledName visitParametrizedProtocolType(const swift::ParameterizedProtocolType* type);
SwiftMangledName visitPackArchetypeType(const swift::PackArchetypeType* type);
SwiftMangledName visitPackType(const swift::PackType* type);
SwiftMangledName visitPackElementType(const swift::PackElementType* type);
SwiftMangledName visitPackExpansionType(const swift::PackExpansionType* type);
private:
std::unordered_map<const swift::Decl*, unsigned> preloadedExtensionIndexes;
virtual SwiftMangledName fetch(const swift::Decl* decl) = 0;
virtual SwiftMangledName fetch(const swift::TypeBase* type) = 0;
SwiftMangledName fetch(swift::Type type) { return fetch(type.getPointer()); }
void indexExtensions(llvm::ArrayRef<swift::Decl*> siblings);
unsigned int getExtensionIndex(const swift::ExtensionDecl* decl, const swift::Decl* parent);
static SwiftMangledName initMangled(const swift::TypeBase* type);
SwiftMangledName initMangled(const swift::Decl* decl);
SwiftMangledName visitTypeDiscriminatedValueDecl(const swift::ValueDecl* decl);
};
// This implementation is indented for use in defining trap keys. In this case fetching gives
// a [trap id-ref][1] is used, using the dispatcher to give us a label reference to that entity.
// Because that entity will also generally have a mangled name, it is important that this does not
// lead to any recursive loop (which is checked at runtime within the dispatcher).
//
// [1]: https://github.com/github/codeql-core/blob/main/wiki/extractors/trap.md#ids
class SwiftTrapMangler : public SwiftMangler {
public:
explicit SwiftTrapMangler(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
private:
SwiftMangledName fetch(const swift::Decl* decl) override;
SwiftMangledName fetch(const swift::TypeBase* type) override;
SwiftDispatcher& dispatcher;
};
// In this implementation, fetching gives a hash of the mangled name itself, leading to a direct
// recursion. This is intended for use in trap file names.
class SwiftRecursiveMangler : public SwiftMangler {
SwiftMangledName fetch(const swift::Decl* decl) override;
SwiftMangledName fetch(const swift::TypeBase* type) override;
};
} // namespace codeql