LLVM: lib/ProfileData/ItaniumManglingCanonicalizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
15
16using namespace llvm;
17using llvm::itanium_demangle::ForwardTemplateReference;
18using llvm::itanium_demangle::Node;
19using llvm::itanium_demangle::NodeKind;
20
21namespace {
22struct FoldingSetNodeIDBuilder {
23 llvm::FoldingSetNodeID &ID;
24 void operator()(const Node *P) { ID.AddPointer(P); }
25 void operator()(std::string_view Str) {
26 if (Str.empty())
27 ID.AddString({});
28 else
29 ID.AddString(llvm::StringRef(&*Str.begin(), Str.size()));
30 }
31 template
32 std::enable_if_t<std::is_integral_v || std::is_enum_v> operator()(T V) {
33 ID.AddInteger((unsigned long long)V);
34 }
35 void operator()(itanium_demangle::NodeArray A) {
36 ID.AddInteger(A.size());
38 (*this)(N);
39 }
40};
41
42template<typename ...T>
44 FoldingSetNodeIDBuilder Builder = {ID};
45 Builder(K);
46 int VisitInOrder[] = {
47 (Builder(V), 0) ...,
48 0
49 };
50 (void)VisitInOrder;
51}
52
53
54template struct ProfileSpecificNode {
55 FoldingSetNodeID &ID;
56 template<typename ...T> void operator()(T ...V) {
57 profileCtor(ID, NodeKind::Kind, V...);
58 }
59};
60
61struct ProfileNode {
62 FoldingSetNodeID &ID;
63 template void operator()(const NodeT *N) {
64 N->match(ProfileSpecificNode{ID});
65 }
66};
67
69 llvm_unreachable("should never canonicalize a ForwardTemplateReference");
70}
71
72void profileNode(llvm::FoldingSetNodeID &ID, const Node *N) {
74}
75
76class FoldingNodeAllocator {
78 public:
79
80 itanium_demangle::Node *getNode() {
81 return reinterpret_cast<itanium_demangle::Node *>(this + 1);
82 }
83 void Profile(llvm::FoldingSetNodeID &ID) { profileNode(ID, getNode()); }
84 };
85
87 llvm::FoldingSet Nodes;
88
89public:
90 void reset() {}
91
92 template <typename T, typename... Args>
93 std::pair<Node *, bool> getOrCreateNode(bool CreateNewNodes, Args &&... As) {
94
95
96
97 if (std::is_same<T, ForwardTemplateReference>::value) {
98
99
100 return {new (RawAlloc.Allocate(sizeof(T), alignof(T)))
101 T(std::forward(As)...),
102 true};
103 }
104
105 llvm::FoldingSetNodeID ID;
106 profileCtor(ID, NodeKind::Kind, As...);
107
108 void *InsertPos;
110 return {static_cast<T*>(Existing->getNode()), false};
111
112 if (!CreateNewNodes)
113 return {nullptr, true};
114
115 static_assert(alignof(T) <= alignof(NodeHeader),
116 "underaligned node header for specific node kind");
117 void *Storage =
118 RawAlloc.Allocate(sizeof(NodeHeader) + sizeof(T), alignof(NodeHeader));
119 NodeHeader *New = new (Storage) NodeHeader;
120 T *Result = new (New->getNode()) T(std::forward(As)...);
122 return {Result, true};
123 }
124
125 template<typename T, typename... Args>
126 Node *makeNode(Args &&...As) {
127 return getOrCreateNode(true, std::forward(As)...).first;
128 }
129
130 void *allocateNodeArray(size_t sz) {
131 return RawAlloc.Allocate(sizeof(Node *) * sz, alignof(Node *));
132 }
133};
134
135class CanonicalizerAllocator : public FoldingNodeAllocator {
136 Node *MostRecentlyCreated = nullptr;
137 Node *TrackedNode = nullptr;
138 bool TrackedNodeIsUsed = false;
139 bool CreateNewNodes = true;
140 llvm::SmallDenseMap<Node*, Node*, 32> Remappings;
141
142 template<typename T, typename ...Args> Node *makeNodeSimple(Args &&...As) {
143 std::pair<Node *, bool> Result =
144 getOrCreateNode(CreateNewNodes, std::forward(As)...);
146
147 MostRecentlyCreated = Result.first;
148 } else if (Result.first) {
149
153 "should never need multiple remap steps");
154 }
155 if (Result.first == TrackedNode)
156 TrackedNodeIsUsed = true;
157 }
159 }
160
161
162 template struct MakeNodeImpl {
163 CanonicalizerAllocator &Self;
164 template<typename ...Args> Node *make(Args &&...As) {
165 return Self.makeNodeSimple<T>(std::forward(As)...);
166 }
167 };
168
169public:
170 template<typename T, typename ...Args> Node *makeNode(Args &&...As) {
171 return MakeNodeImpl{*this}.make(std::forward(As)...);
172 }
173
174 void reset() { MostRecentlyCreated = nullptr; }
175
176 void setCreateNewNodes(bool CNN) { CreateNewNodes = CNN; }
177
178 void addRemapping(Node *A, Node *B) {
179
180
181 Remappings.insert(std::make_pair(A, B));
182 }
183
184 bool isMostRecentlyCreated(Node *N) const { return MostRecentlyCreated == N; }
185
186 void trackUsesOf(Node *N) {
187 TrackedNode = N;
188 TrackedNodeIsUsed = false;
189 }
190 bool trackedNodeIsUsed() const { return TrackedNodeIsUsed; }
191};
192
193
194
195using CanonicalizingDemangler =
196 itanium_demangle::ManglingParser;
197}
198
200 CanonicalizingDemangler Demangler = {nullptr, nullptr};
201};
202
205
209 auto &Alloc = P->Demangler.ASTAllocator;
210 Alloc.setCreateNewNodes(true);
211
212 auto Parse = [&](StringRef Str) {
213 P->Demangler.reset(Str.begin(), Str.end());
215 switch (Kind) {
216
217
219
220
221
222 if (Str.size() == 2 && P->Demangler.consumeIf("St"))
223 N = P->Demangler.make<itanium_demangle::NameType>("std");
224
225
226
227
228 else if (Str.starts_with("S"))
229
230 N = P->Demangler.parseType();
231 else
232 N = P->Demangler.parseName();
233 break;
234
235
237 N = P->Demangler.parseType();
238 break;
239
240
242 N = P->Demangler.parseEncoding();
243 break;
244 }
245
246
247 if (P->Demangler.numLeft() != 0)
248 N = nullptr;
249
250
251
252 return std::make_pair(N, Alloc.isMostRecentlyCreated(N));
253 };
254
255 Node *FirstNode, *SecondNode;
256 bool FirstIsNew, SecondIsNew;
257
258 std::tie(FirstNode, FirstIsNew) = Parse(First);
259 if (!FirstNode)
261
262 Alloc.trackUsesOf(FirstNode);
263 std::tie(SecondNode, SecondIsNew) = Parse(Second);
264 if (!SecondNode)
266
267
268 if (FirstNode == SecondNode)
270
271 if (FirstIsNew && .trackedNodeIsUsed())
272 Alloc.addRemapping(FirstNode, SecondNode);
273 else if (SecondIsNew)
274 Alloc.addRemapping(SecondNode, FirstNode);
275 else
277
279}
280
283 bool CreateNewNodes) {
284 Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes);
285 Demangler.reset(Mangling.begin(), Mangling.end());
286
287
288
289
290
294 N = Demangler.parse();
295 else
296 N = Demangler.make<itanium_demangle::NameType>(
297 std::string_view(Mangling.data(), Mangling.size()));
299}
300
305
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
static ItaniumManglingCanonicalizer::Key parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, bool CreateNewNodes)
Definition ItaniumManglingCanonicalizer.cpp:282
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
@ Encoding
The mangling fragment is an .
@ Name
The mangling fragment is a (or a predefined ).
@ Type
The mangling fragment is a .
LLVM_ABI Key lookup(StringRef Mangling)
Find a canonical key for the specified mangling, if one has already been formed.
Definition ItaniumManglingCanonicalizer.cpp:307
LLVM_ABI Key canonicalize(StringRef Mangling)
Form a canonical key for the specified mangling.
Definition ItaniumManglingCanonicalizer.cpp:302
LLVM_ABI ItaniumManglingCanonicalizer()
Definition ItaniumManglingCanonicalizer.cpp:203
@ InvalidFirstMangling
The first equivalent mangling is invalid.
@ InvalidSecondMangling
The second equivalent mangling is invalid.
@ ManglingAlreadyUsed
Both the equivalent manglings have already been used as components of some other mangling we've looke...
LLVM_ABI EquivalenceError addEquivalence(FragmentKind Kind, StringRef First, StringRef Second)
Add an equivalence between First and Second.
Definition ItaniumManglingCanonicalizer.cpp:207
LLVM_ABI ~ItaniumManglingCanonicalizer()
Definition ItaniumManglingCanonicalizer.cpp:204
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FoldingSetBase::Node FoldingSetNode
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
A forward-reference to a template argument that was not known at the point where the template paramet...
CanonicalizingDemangler Demangler
Definition ItaniumManglingCanonicalizer.cpp:200