LLVM 20.0.0git
MicrosoftDemangle.h
Go to the documentation of this file.
1//===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
10#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
11
14
15#include <cassert>
16#include <string_view>
17#include <utility>
18
19namespace llvm {
20namespace ms_demangle {
21// This memory allocator is extremely fast, but it doesn't call dtors
22// for allocated objects. That means you can't use STL containers
23// (such as std::vector) with this allocator. But it pays off --
24// the demangler is 3x faster with this allocator compared to one with
25// STL containers.
26constexpr size_t AllocUnit = 4096;
27
29 struct AllocatorNode {
30 uint8_t *Buf = nullptr;
31 size_t Used = 0;
32 size_t Capacity = 0;
33 AllocatorNode *Next = nullptr;
34 };
35
36 void addNode(size_t Capacity) {
37 AllocatorNode *NewHead = new AllocatorNode;
38 NewHead->Buf = new uint8_t[Capacity];
39 NewHead->Next = Head;
40 NewHead->Capacity = Capacity;
41 Head = NewHead;
42 NewHead->Used = 0;
43 }
44
45public:
46 ArenaAllocator() { addNode(AllocUnit); }
47
49 while (Head) {
50 assert(Head->Buf);
51 delete[] Head->Buf;
52 AllocatorNode *Next = Head->Next;
53 delete Head;
54 Head = Next;
55 }
56 }
57
58 // Delete the copy constructor and the copy assignment operator.
59 ArenaAllocator(const ArenaAllocator &) = delete;
61
62 char *allocUnalignedBuffer(size_t Size) {
63 assert(Head && Head->Buf);
64
65 uint8_t *P = Head->Buf + Head->Used;
66
67 Head->Used += Size;
68 if (Head->Used <= Head->Capacity)
69 return reinterpret_cast<char *>(P);
70
71 addNode(std::max(AllocUnit, Size));
72 Head->Used = Size;
73 return reinterpret_cast<char *>(Head->Buf);
74 }
75
76 template <typename T, typename... Args> T *allocArray(size_t Count) {
77 size_t Size = Count * sizeof(T);
78 assert(Head && Head->Buf);
79
80 size_t P = (size_t)Head->Buf + Head->Used;
81 uintptr_t AlignedP =
82 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
83 uint8_t *PP = (uint8_t *)AlignedP;
84 size_t Adjustment = AlignedP - P;
85
86 Head->Used += Size + Adjustment;
87 if (Head->Used <= Head->Capacity)
88 return new (PP) T[Count]();
89
90 addNode(std::max(AllocUnit, Size));
91 Head->Used = Size;
92 return new (Head->Buf) T[Count]();
93 }
94
95 template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
96 constexpr size_t Size = sizeof(T);
97 assert(Head && Head->Buf);
98
99 size_t P = (size_t)Head->Buf + Head->Used;
100 uintptr_t AlignedP =
101 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
102 uint8_t *PP = (uint8_t *)AlignedP;
103 size_t Adjustment = AlignedP - P;
104
105 Head->Used += Size + Adjustment;
106 if (Head->Used <= Head->Capacity)
107 return new (PP) T(std::forward<Args>(ConstructorArgs)...);
108
109 static_assert(Size < AllocUnit);
110 addNode(AllocUnit);
111 Head->Used = Size;
112 return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
113 }
114
115private:
116 AllocatorNode *Head = nullptr;
117};
118
120 static constexpr size_t Max = 10;
121
124
125 // The first 10 BackReferences in a mangled name can be back-referenced by
126 // special name @[0-9]. This is a storage for the first 10 BackReferences.
128 size_t NamesCount = 0;
129};
130
132
134 NBB_None = 0, // don't save any names as backrefs.
135 NBB_Template = 1 << 0, // save template instanations.
136 NBB_Simple = 1 << 1, // save simple names.
137};
138
140
141// Demangler class takes the main role in demangling symbols.
142// It has a set of functions to parse mangled symbols into Type instances.
143// It also has a set of functions to convert Type instances to strings.
145 friend std::optional<size_t>
146 llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName);
147
148public:
149 Demangler() = default;
150 virtual ~Demangler() = default;
151
152 // You are supposed to call parse() first and then check if error is true. If
153 // it is false, call output() to write the formatted name to the given stream.
154 SymbolNode *parse(std::string_view &MangledName);
155
156 TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
157
158 // True if an error occurred.
159 bool Error = false;
160
161 void dumpBackReferences();
162
163private:
164 SymbolNode *demangleEncodedSymbol(std::string_view &MangledName,
166 SymbolNode *demangleDeclarator(std::string_view &MangledName);
167 SymbolNode *demangleMD5Name(std::string_view &MangledName);
168 SymbolNode *demangleTypeinfoName(std::string_view &MangledName);
169
170 VariableSymbolNode *demangleVariableEncoding(std::string_view &MangledName,
171 StorageClass SC);
172 FunctionSymbolNode *demangleFunctionEncoding(std::string_view &MangledName);
173
174 Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName);
175
176 // Parser functions. This is a recursive-descent parser.
177 TypeNode *demangleType(std::string_view &MangledName,
179 PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName);
180 CustomTypeNode *demangleCustomType(std::string_view &MangledName);
181 TagTypeNode *demangleClassType(std::string_view &MangledName);
182 PointerTypeNode *demanglePointerType(std::string_view &MangledName);
183 PointerTypeNode *demangleMemberPointerType(std::string_view &MangledName);
184 FunctionSignatureNode *demangleFunctionType(std::string_view &MangledName,
185 bool HasThisQuals);
186
187 ArrayTypeNode *demangleArrayType(std::string_view &MangledName);
188
189 NodeArrayNode *demangleFunctionParameterList(std::string_view &MangledName,
190 bool &IsVariadic);
191 NodeArrayNode *demangleTemplateParameterList(std::string_view &MangledName);
192
193 std::pair<uint64_t, bool> demangleNumber(std::string_view &MangledName);
194 uint64_t demangleUnsigned(std::string_view &MangledName);
195 int64_t demangleSigned(std::string_view &MangledName);
196
197 void memorizeString(std::string_view s);
198 void memorizeIdentifier(IdentifierNode *Identifier);
199
200 /// Allocate a copy of \p Borrowed into memory that we own.
201 std::string_view copyString(std::string_view Borrowed);
202
204 demangleFullyQualifiedTypeName(std::string_view &MangledName);
206 demangleFullyQualifiedSymbolName(std::string_view &MangledName);
207
208 IdentifierNode *demangleUnqualifiedTypeName(std::string_view &MangledName,
209 bool Memorize);
210 IdentifierNode *demangleUnqualifiedSymbolName(std::string_view &MangledName,
212
213 QualifiedNameNode *demangleNameScopeChain(std::string_view &MangledName,
214 IdentifierNode *UnqualifiedName);
215 IdentifierNode *demangleNameScopePiece(std::string_view &MangledName);
216
217 NamedIdentifierNode *demangleBackRefName(std::string_view &MangledName);
219 demangleTemplateInstantiationName(std::string_view &MangledName,
222 translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
223 IdentifierNode *demangleFunctionIdentifierCode(std::string_view &MangledName);
225 demangleFunctionIdentifierCode(std::string_view &MangledName,
228 demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor);
230 demangleConversionOperatorIdentifier(std::string_view &MangledName);
232 demangleLiteralOperatorIdentifier(std::string_view &MangledName);
233
234 SymbolNode *demangleSpecialIntrinsic(std::string_view &MangledName);
236 demangleSpecialTableSymbolNode(std::string_view &MangledName,
239 demangleLocalStaticGuard(std::string_view &MangledName, bool IsThread);
240 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
241 std::string_view &MangledName,
242 std::string_view VariableName);
244 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
245 std::string_view &MangledName);
246 FunctionSymbolNode *demangleInitFiniStub(std::string_view &MangledName,
247 bool IsDestructor);
248
249 NamedIdentifierNode *demangleSimpleName(std::string_view &MangledName,
250 bool Memorize);
252 demangleAnonymousNamespaceName(std::string_view &MangledName);
254 demangleLocallyScopedNamePiece(std::string_view &MangledName);
256 demangleStringLiteral(std::string_view &MangledName);
257 FunctionSymbolNode *demangleVcallThunkNode(std::string_view &MangledName);
258
259 std::string_view demangleSimpleString(std::string_view &MangledName,
260 bool Memorize);
261
262 FuncClass demangleFunctionClass(std::string_view &MangledName);
263 CallingConv demangleCallingConvention(std::string_view &MangledName);
264 StorageClass demangleVariableStorageClass(std::string_view &MangledName);
265 bool demangleThrowSpecification(std::string_view &MangledName);
266 wchar_t demangleWcharLiteral(std::string_view &MangledName);
267 uint8_t demangleCharLiteral(std::string_view &MangledName);
268
269 std::pair<Qualifiers, bool> demangleQualifiers(std::string_view &MangledName);
270
271 // Memory allocator.
272 ArenaAllocator Arena;
273
274 // A single type uses one global back-ref table for all function params.
275 // This means back-refs can even go "into" other types. Examples:
276 //
277 // // Second int* is a back-ref to first.
278 // void foo(int *, int*);
279 //
280 // // Second int* is not a back-ref to first (first is not a function param).
281 // int* foo(int*);
282 //
283 // // Second int* is a back-ref to first (ALL function types share the same
284 // // back-ref map.
285 // using F = void(*)(int*);
286 // F G(int *);
287 BackrefContext Backrefs;
288};
289
290} // namespace ms_demangle
291} // namespace llvm
292
293#endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
uint64_t Size
#define T
#define P(N)
#define CH(x, y, z)
Definition: SHA256.cpp:34
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
T * alloc(Args &&... ConstructorArgs)
char * allocUnalignedBuffer(size_t Size)
ArenaAllocator & operator=(const ArenaAllocator &)=delete
ArenaAllocator(const ArenaAllocator &)=delete
TagTypeNode * parseTagUniqueName(std::string_view &MangledName)
virtual ~Demangler()=default
constexpr size_t AllocUnit
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::optional< size_t > getArm64ECInsertionPointInMangledName(std::string_view MangledName)
NamedIdentifierNode * Names[Max]
Definition: regcomp.c:192