llvm.org GIT mirror llvm / c35d5db
[MS Demangler] Expose the Demangler AST publicly. LLDB would like to use this in order to build a clang AST from a mangled name. This is NFC otherwise. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@345837 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 10 months ago
5 changed file(s) with 888 addition(s) and 853 deletion(s). Raw diff Collapse all Expand all
0 //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is dual licensed under the MIT and the University of Illinois Open
5 // Source Licenses. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
10 #define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
11
12 #include "llvm/Demangle/Compiler.h"
13 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
14 #include "llvm/Demangle/StringView.h"
15 #include "llvm/Demangle/Utility.h"
16
17 #include
18
19 namespace llvm {
20 namespace 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.
26 constexpr size_t AllocUnit = 4096;
27
28 class ArenaAllocator {
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
45 public:
46 ArenaAllocator() { addNode(AllocUnit); }
47
48 ~ArenaAllocator() {
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 char *allocUnalignedBuffer(size_t Length) {
59 uint8_t *Buf = Head->Buf + Head->Used;
60
61 Head->Used += Length;
62 if (Head->Used > Head->Capacity) {
63 // It's possible we need a buffer which is larger than our default unit
64 // size, so we need to be careful to add a node with capacity that is at
65 // least as large as what we need.
66 addNode(std::max(AllocUnit, Length));
67 Head->Used = Length;
68 Buf = Head->Buf;
69 }
70
71 return reinterpret_cast(Buf);
72 }
73
74 template T *allocArray(size_t Count) {
75
76 size_t Size = Count * sizeof(T);
77 assert(Head && Head->Buf);
78
79 size_t P = (size_t)Head->Buf + Head->Used;
80 uintptr_t AlignedP =
81 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
82 uint8_t *PP = (uint8_t *)AlignedP;
83 size_t Adjustment = AlignedP - P;
84
85 Head->Used += Size + Adjustment;
86 if (Head->Used < Head->Capacity)
87 return new (PP) T[Count]();
88
89 addNode(AllocUnit);
90 Head->Used = Size;
91 return new (Head->Buf) T[Count]();
92 }
93
94 template T *alloc(Args &&... ConstructorArgs) {
95
96 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(ConstructorArgs)...);
108
109 addNode(AllocUnit);
110 Head->Used = Size;
111 return new (Head->Buf) T(std::forward(ConstructorArgs)...);
112 }
113
114 private:
115 AllocatorNode *Head = nullptr;
116 };
117
118 struct BackrefContext {
119 static constexpr size_t Max = 10;
120
121 TypeNode *FunctionParams[Max];
122 size_t FunctionParamCount = 0;
123
124 // The first 10 BackReferences in a mangled name can be back-referenced by
125 // special name @[0-9]. This is a storage for the first 10 BackReferences.
126 NamedIdentifierNode *Names[Max];
127 size_t NamesCount = 0;
128 };
129
130 enum class QualifierMangleMode { Drop, Mangle, Result };
131
132 enum NameBackrefBehavior : uint8_t {
133 NBB_None = 0, // don't save any names as backrefs.
134 NBB_Template = 1 << 0, // save template instanations.
135 NBB_Simple = 1 << 1, // save simple names.
136 };
137
138 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
139
140 // Demangler class takes the main role in demangling symbols.
141 // It has a set of functions to parse mangled symbols into Type instances.
142 // It also has a set of functions to convert Type instances to strings.
143 class Demangler {
144 public:
145 Demangler() = default;
146 virtual ~Demangler() = default;
147
148 // You are supposed to call parse() first and then check if error is true. If
149 // it is false, call output() to write the formatted name to the given stream.
150 SymbolNode *parse(StringView &MangledName);
151
152 TagTypeNode *parseTagUniqueName(StringView &MangledName);
153
154 // True if an error occurred.
155 bool Error = false;
156
157 void dumpBackReferences();
158
159 private:
160 SymbolNode *demangleEncodedSymbol(StringView &MangledName,
161 QualifiedNameNode *QN);
162
163 VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
164 StorageClass SC);
165 FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
166
167 Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
168
169 // Parser functions. This is a recursive-descent parser.
170 TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
171 PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
172 CustomTypeNode *demangleCustomType(StringView &MangledName);
173 TagTypeNode *demangleClassType(StringView &MangledName);
174 PointerTypeNode *demanglePointerType(StringView &MangledName);
175 PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
176 FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
177 bool HasThisQuals);
178
179 ArrayTypeNode *demangleArrayType(StringView &MangledName);
180
181 NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
182 NodeArrayNode *demangleFunctionParameterList(StringView &MangledName);
183
184 std::pair demangleNumber(StringView &MangledName);
185 uint64_t demangleUnsigned(StringView &MangledName);
186 int64_t demangleSigned(StringView &MangledName);
187
188 void memorizeString(StringView s);
189 void memorizeIdentifier(IdentifierNode *Identifier);
190
191 /// Allocate a copy of \p Borrowed into memory that we own.
192 StringView copyString(StringView Borrowed);
193
194 QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
195 QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
196
197 IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
198 bool Memorize);
199 IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
200 NameBackrefBehavior NBB);
201
202 QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
203 IdentifierNode *UnqualifiedName);
204 IdentifierNode *demangleNameScopePiece(StringView &MangledName);
205
206 NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
207 IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
208 NameBackrefBehavior NBB);
209 IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
210 IdentifierNode *
211 demangleFunctionIdentifierCode(StringView &MangledName,
212 FunctionIdentifierCodeGroup Group);
213 StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
214 bool IsDestructor);
215 ConversionOperatorIdentifierNode *
216 demangleConversionOperatorIdentifier(StringView &MangledName);
217 LiteralOperatorIdentifierNode *
218 demangleLiteralOperatorIdentifier(StringView &MangledName);
219
220 SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
221 SpecialTableSymbolNode *
222 demangleSpecialTableSymbolNode(StringView &MangledName,
223 SpecialIntrinsicKind SIK);
224 LocalStaticGuardVariableNode *
225 demangleLocalStaticGuard(StringView &MangledName);
226 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
227 StringView &MangledName,
228 StringView VariableName);
229 VariableSymbolNode *
230 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
231 StringView &MangledName);
232 FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
233 bool IsDestructor);
234
235 NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
236 bool Memorize);
237 NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
238 NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
239 EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
240 FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
241
242 StringView demangleSimpleString(StringView &MangledName, bool Memorize);
243
244 FuncClass demangleFunctionClass(StringView &MangledName);
245 CallingConv demangleCallingConvention(StringView &MangledName);
246 StorageClass demangleVariableStorageClass(StringView &MangledName);
247 void demangleThrowSpecification(StringView &MangledName);
248 wchar_t demangleWcharLiteral(StringView &MangledName);
249 uint8_t demangleCharLiteral(StringView &MangledName);
250
251 std::pair demangleQualifiers(StringView &MangledName);
252
253 // Memory allocator.
254 ArenaAllocator Arena;
255
256 // A single type uses one global back-ref table for all function params.
257 // This means back-refs can even go "into" other types. Examples:
258 //
259 // // Second int* is a back-ref to first.
260 // void foo(int *, int*);
261 //
262 // // Second int* is not a back-ref to first (first is not a function param).
263 // int* foo(int*);
264 //
265 // // Second int* is a back-ref to first (ALL function types share the same
266 // // back-ref map.
267 // using F = void(*)(int*);
268 // F G(int *);
269 BackrefContext Backrefs;
270 };
271
272 } // namespace ms_demangle
273 } // namespace llvm
274
275 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
0 #ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
1 #define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
2
3 #include "llvm/Demangle/Compiler.h"
4 #include "llvm/Demangle/StringView.h"
5 #include
6
7 class OutputStream;
8
9 namespace llvm {
10 namespace ms_demangle {
11
12 // Storage classes
13 enum Qualifiers : uint8_t {
14 Q_None = 0,
15 Q_Const = 1 << 0,
16 Q_Volatile = 1 << 1,
17 Q_Far = 1 << 2,
18 Q_Huge = 1 << 3,
19 Q_Unaligned = 1 << 4,
20 Q_Restrict = 1 << 5,
21 Q_Pointer64 = 1 << 6
22 };
23
24 enum class StorageClass : uint8_t {
25 None,
26 PrivateStatic,
27 ProtectedStatic,
28 PublicStatic,
29 Global,
30 FunctionLocalStatic,
31 };
32
33 enum class PointerAffinity { None, Pointer, Reference, RValueReference };
34 enum class FunctionRefQualifier { None, Reference, RValueReference };
35
36 // Calling conventions
37 enum class CallingConv : uint8_t {
38 None,
39 Cdecl,
40 Pascal,
41 Thiscall,
42 Stdcall,
43 Fastcall,
44 Clrcall,
45 Eabi,
46 Vectorcall,
47 Regcall,
48 };
49
50 enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
51
52 enum OutputFlags {
53 OF_Default = 0,
54 OF_NoCallingConvention = 1,
55 };
56
57 // Types
58 enum class PrimitiveKind {
59 Void,
60 Bool,
61 Char,
62 Schar,
63 Uchar,
64 Char16,
65 Char32,
66 Short,
67 Ushort,
68 Int,
69 Uint,
70 Long,
71 Ulong,
72 Int64,
73 Uint64,
74 Wchar,
75 Float,
76 Double,
77 Ldouble,
78 Nullptr,
79 };
80
81 enum class CharKind {
82 Char,
83 Char16,
84 Char32,
85 Wchar,
86 };
87
88 enum class IntrinsicFunctionKind : uint8_t {
89 None,
90 New, // ?2 # operator new
91 Delete, // ?3 # operator delete
92 Assign, // ?4 # operator=
93 RightShift, // ?5 # operator>>
94 LeftShift, // ?6 # operator<<
95 LogicalNot, // ?7 # operator!
96 Equals, // ?8 # operator==
97 NotEquals, // ?9 # operator!=
98 ArraySubscript, // ?A # operator[]
99 Pointer, // ?C # operator->
100 Dereference, // ?D # operator*
101 Increment, // ?E # operator++
102 Decrement, // ?F # operator--
103 Minus, // ?G # operator-
104 Plus, // ?H # operator+
105 BitwiseAnd, // ?I # operator&
106 MemberPointer, // ?J # operator->*
107 Divide, // ?K # operator/
108 Modulus, // ?L # operator%
109 LessThan, // ?M operator<
110 LessThanEqual, // ?N operator<=
111 GreaterThan, // ?O operator>
112 GreaterThanEqual, // ?P operator>=
113 Comma, // ?Q operator,
114 Parens, // ?R operator()
115 BitwiseNot, // ?S operator~
116 BitwiseXor, // ?T operator^
117 BitwiseOr, // ?U operator|
118 LogicalAnd, // ?V operator&&
119 LogicalOr, // ?W operator||
120 TimesEqual, // ?X operator*=
121 PlusEqual, // ?Y operator+=
122 MinusEqual, // ?Z operator-=
123 DivEqual, // ?_0 operator/=
124 ModEqual, // ?_1 operator%=
125 RshEqual, // ?_2 operator>>=
126 LshEqual, // ?_3 operator<<=
127 BitwiseAndEqual, // ?_4 operator&=
128 BitwiseOrEqual, // ?_5 operator|=
129 BitwiseXorEqual, // ?_6 operator^=
130 VbaseDtor, // ?_D # vbase destructor
131 VecDelDtor, // ?_E # vector deleting destructor
132 DefaultCtorClosure, // ?_F # default constructor closure
133 ScalarDelDtor, // ?_G # scalar deleting destructor
134 VecCtorIter, // ?_H # vector constructor iterator
135 VecDtorIter, // ?_I # vector destructor iterator
136 VecVbaseCtorIter, // ?_J # vector vbase constructor iterator
137 VdispMap, // ?_K # virtual displacement map
138 EHVecCtorIter, // ?_L # eh vector constructor iterator
139 EHVecDtorIter, // ?_M # eh vector destructor iterator
140 EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
141 CopyCtorClosure, // ?_O # copy constructor closure
142 LocalVftableCtorClosure, // ?_T # local vftable constructor closure
143 ArrayNew, // ?_U operator new[]
144 ArrayDelete, // ?_V operator delete[]
145 ManVectorCtorIter, // ?__A managed vector ctor iterator
146 ManVectorDtorIter, // ?__B managed vector dtor iterator
147 EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator
148 EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator
149 VectorCopyCtorIter, // ?__G vector copy constructor iterator
150 VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator
151 ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor
152 CoAwait, // ?__L co_await
153 Spaceship, // operator<=>
154 MaxIntrinsic
155 };
156
157 enum class SpecialIntrinsicKind {
158 None,
159 Vftable,
160 Vbtable,
161 Typeof,
162 VcallThunk,
163 LocalStaticGuard,
164 StringLiteralSymbol,
165 UdtReturning,
166 Unknown,
167 DynamicInitializer,
168 DynamicAtexitDestructor,
169 RttiTypeDescriptor,
170 RttiBaseClassDescriptor,
171 RttiBaseClassArray,
172 RttiClassHierarchyDescriptor,
173 RttiCompleteObjLocator,
174 LocalVftable,
175 LocalStaticThreadGuard,
176 };
177
178 // Function classes
179 enum FuncClass : uint16_t {
180 FC_None = 0,
181 FC_Public = 1 << 0,
182 FC_Protected = 1 << 1,
183 FC_Private = 1 << 2,
184 FC_Global = 1 << 3,
185 FC_Static = 1 << 4,
186 FC_Virtual = 1 << 5,
187 FC_Far = 1 << 6,
188 FC_ExternC = 1 << 7,
189 FC_NoParameterList = 1 << 8,
190 FC_VirtualThisAdjust = 1 << 9,
191 FC_VirtualThisAdjustEx = 1 << 10,
192 FC_StaticThisAdjust = 1 << 11,
193 };
194
195 enum class TagKind { Class, Struct, Union, Enum };
196
197 enum class NodeKind {
198 Unknown,
199 Md5Symbol,
200 PrimitiveType,
201 FunctionSignature,
202 Identifier,
203 NamedIdentifier,
204 VcallThunkIdentifier,
205 LocalStaticGuardIdentifier,
206 IntrinsicFunctionIdentifier,
207 ConversionOperatorIdentifier,
208 DynamicStructorIdentifier,
209 StructorIdentifier,
210 LiteralOperatorIdentifier,
211 ThunkSignature,
212 PointerType,
213 TagType,
214 ArrayType,
215 Custom,
216 IntrinsicType,
217 NodeArray,
218 QualifiedName,
219 TemplateParameterReference,
220 EncodedStringLiteral,
221 IntegerLiteral,
222 RttiBaseClassDescriptor,
223 LocalStaticGuardVariable,
224 FunctionSymbol,
225 VariableSymbol,
226 SpecialTableSymbol
227 };
228
229 struct Node {
230 explicit Node(NodeKind K) : Kind(K) {}
231 virtual ~Node() = default;
232
233 NodeKind kind() const { return Kind; }
234
235 virtual void output(OutputStream &OS, OutputFlags Flags) const = 0;
236
237 private:
238 NodeKind Kind;
239 };
240
241 struct TypeNode;
242 struct PrimitiveTypeNode;
243 struct FunctionSignatureNode;
244 struct IdentifierNode;
245 struct NamedIdentifierNode;
246 struct VcallThunkIdentifierNode;
247 struct IntrinsicFunctionIdentifierNode;
248 struct LiteralOperatorIdentifierNode;
249 struct ConversionOperatorIdentifierNode;
250 struct StructorIdentifierNode;
251 struct ThunkSignatureNode;
252 struct PointerTypeNode;
253 struct ArrayTypeNode;
254 struct CustomNode;
255 struct TagTypeNode;
256 struct IntrinsicTypeNode;
257 struct NodeArrayNode;
258 struct QualifiedNameNode;
259 struct TemplateParameterReferenceNode;
260 struct EncodedStringLiteralNode;
261 struct IntegerLiteralNode;
262 struct RttiBaseClassDescriptorNode;
263 struct LocalStaticGuardVariableNode;
264 struct SymbolNode;
265 struct FunctionSymbolNode;
266 struct VariableSymbolNode;
267 struct SpecialTableSymbolNode;
268
269 struct TypeNode : public Node {
270 explicit TypeNode(NodeKind K) : Node(K) {}
271
272 virtual void outputPre(OutputStream &OS, OutputFlags Flags) const = 0;
273 virtual void outputPost(OutputStream &OS, OutputFlags Flags) const = 0;
274
275 void output(OutputStream &OS, OutputFlags Flags) const override {
276 outputPre(OS, Flags);
277 outputPost(OS, Flags);
278 }
279
280 void outputQuals(bool SpaceBefore, bool SpaceAfter) const;
281
282 Qualifiers Quals = Q_None;
283 };
284
285 struct PrimitiveTypeNode : public TypeNode {
286 explicit PrimitiveTypeNode(PrimitiveKind K)
287 : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {}
288
289 void outputPre(OutputStream &OS, OutputFlags Flags) const;
290 void outputPost(OutputStream &OS, OutputFlags Flags) const {}
291
292 PrimitiveKind PrimKind;
293 };
294
295 struct FunctionSignatureNode : public TypeNode {
296 explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
297 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
298
299 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
300 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
301
302 // Valid if this FunctionTypeNode is the Pointee of a PointerType or
303 // MemberPointerType.
304 PointerAffinity Affinity = PointerAffinity::None;
305
306 // The function's calling convention.
307 CallingConv CallConvention = CallingConv::None;
308
309 // Function flags (gloabl, public, etc)
310 FuncClass FunctionClass = FC_Global;
311
312 FunctionRefQualifier RefQualifier = FunctionRefQualifier::None;
313
314 // The return type of the function.
315 TypeNode *ReturnType = nullptr;
316
317 // True if this is a C-style ... varargs function.
318 bool IsVariadic = false;
319
320 // Function parameters
321 NodeArrayNode *Params = nullptr;
322 };
323
324 struct IdentifierNode : public Node {
325 explicit IdentifierNode(NodeKind K) : Node(K) {}
326
327 NodeArrayNode *TemplateParams = nullptr;
328
329 protected:
330 void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const;
331 };
332
333 struct VcallThunkIdentifierNode : public IdentifierNode {
334 VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {}
335
336 void output(OutputStream &OS, OutputFlags Flags) const override;
337
338 uint64_t OffsetInVTable = 0;
339 };
340
341 struct DynamicStructorIdentifierNode : public IdentifierNode {
342 DynamicStructorIdentifierNode()
343 : IdentifierNode(NodeKind::DynamicStructorIdentifier) {}
344
345 void output(OutputStream &OS, OutputFlags Flags) const override;
346
347 VariableSymbolNode *Variable = nullptr;
348 QualifiedNameNode *Name = nullptr;
349 bool IsDestructor = false;
350 };
351
352 struct NamedIdentifierNode : public IdentifierNode {
353 NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {}
354
355 void output(OutputStream &OS, OutputFlags Flags) const override;
356
357 StringView Name;
358 };
359
360 struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
361 explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator)
362 : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier),
363 Operator(Operator) {}
364
365 void output(OutputStream &OS, OutputFlags Flags) const override;
366
367 IntrinsicFunctionKind Operator;
368 };
369
370 struct LiteralOperatorIdentifierNode : public IdentifierNode {
371 LiteralOperatorIdentifierNode()
372 : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {}
373
374 void output(OutputStream &OS, OutputFlags Flags) const override;
375
376 StringView Name;
377 };
378
379 struct LocalStaticGuardIdentifierNode : public IdentifierNode {
380 LocalStaticGuardIdentifierNode()
381 : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {}
382
383 void output(OutputStream &OS, OutputFlags Flags) const override;
384
385 uint32_t ScopeIndex = 0;
386 };
387
388 struct ConversionOperatorIdentifierNode : public IdentifierNode {
389 ConversionOperatorIdentifierNode()
390 : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {}
391
392 void output(OutputStream &OS, OutputFlags Flags) const override;
393
394 // The type that this operator converts too.
395 TypeNode *TargetType = nullptr;
396 };
397
398 struct StructorIdentifierNode : public IdentifierNode {
399 StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {}
400 explicit StructorIdentifierNode(bool IsDestructor)
401 : IdentifierNode(NodeKind::StructorIdentifier),
402 IsDestructor(IsDestructor) {}
403
404 void output(OutputStream &OS, OutputFlags Flags) const override;
405
406 // The name of the class that this is a structor of.
407 IdentifierNode *Class = nullptr;
408 bool IsDestructor = false;
409 };
410
411 struct ThunkSignatureNode : public FunctionSignatureNode {
412 ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {}
413
414 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
415 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
416
417 struct ThisAdjustor {
418 uint32_t StaticOffset = 0;
419 int32_t VBPtrOffset = 0;
420 int32_t VBOffsetOffset = 0;
421 int32_t VtordispOffset = 0;
422 };
423
424 ThisAdjustor ThisAdjust;
425 };
426
427 struct PointerTypeNode : public TypeNode {
428 PointerTypeNode() : TypeNode(NodeKind::PointerType) {}
429 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
430 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
431
432 // Is this a pointer, reference, or rvalue-reference?
433 PointerAffinity Affinity = PointerAffinity::None;
434
435 // If this is a member pointer, this is the class that the member is in.
436 QualifiedNameNode *ClassParent = nullptr;
437
438 // Represents a type X in "a pointer to X", "a reference to X", or
439 // "rvalue-reference to X"
440 TypeNode *Pointee = nullptr;
441 };
442
443 struct TagTypeNode : public TypeNode {
444 explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {}
445
446 void outputPre(OutputStream &OS, OutputFlags Flags) const;
447 void outputPost(OutputStream &OS, OutputFlags Flags) const;
448
449 QualifiedNameNode *QualifiedName = nullptr;
450 TagKind Tag;
451 };
452
453 struct ArrayTypeNode : public TypeNode {
454 ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {}
455
456 void outputPre(OutputStream &OS, OutputFlags Flags) const;
457 void outputPost(OutputStream &OS, OutputFlags Flags) const;
458
459 void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const;
460 void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const;
461
462 // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]`
463 NodeArrayNode *Dimensions = nullptr;
464
465 // The type of array element.
466 TypeNode *ElementType = nullptr;
467 };
468
469 struct IntrinsicNode : public TypeNode {
470 IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
471 void output(OutputStream &OS, OutputFlags Flags) const override {}
472 };
473
474 struct CustomTypeNode : public TypeNode {
475 CustomTypeNode() : TypeNode(NodeKind::Custom) {}
476
477 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
478 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
479
480 IdentifierNode *Identifier;
481 };
482
483 struct NodeArrayNode : public Node {
484 NodeArrayNode() : Node(NodeKind::NodeArray) {}
485
486 void output(OutputStream &OS, OutputFlags Flags) const override;
487
488 void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const;
489
490 Node **Nodes = 0;
491 size_t Count = 0;
492 };
493
494 struct QualifiedNameNode : public Node {
495 QualifiedNameNode() : Node(NodeKind::QualifiedName) {}
496
497 void output(OutputStream &OS, OutputFlags Flags) const override;
498
499 NodeArrayNode *Components = nullptr;
500
501 IdentifierNode *getUnqualifiedIdentifier() {
502 Node *LastComponent = Components->Nodes[Components->Count - 1];
503 return static_cast(LastComponent);
504 }
505 };
506
507 struct TemplateParameterReferenceNode : public Node {
508 TemplateParameterReferenceNode()
509 : Node(NodeKind::TemplateParameterReference) {}
510
511 void output(OutputStream &OS, OutputFlags Flags) const override;
512
513 SymbolNode *Symbol = nullptr;
514
515 int ThunkOffsetCount = 0;
516 std::array ThunkOffsets;
517 PointerAffinity Affinity = PointerAffinity::None;
518 bool IsMemberPointer = false;
519 };
520
521 struct IntegerLiteralNode : public Node {
522 IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) {}
523 IntegerLiteralNode(uint64_t Value, bool IsNegative)
524 : Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {}
525
526 void output(OutputStream &OS, OutputFlags Flags) const override;
527
528 uint64_t Value = 0;
529 bool IsNegative = false;
530 };
531
532 struct RttiBaseClassDescriptorNode : public IdentifierNode {
533 RttiBaseClassDescriptorNode()
534 : IdentifierNode(NodeKind::RttiBaseClassDescriptor) {}
535
536 void output(OutputStream &OS, OutputFlags Flags) const override;
537
538 uint32_t NVOffset = 0;
539 int32_t VBPtrOffset = 0;
540 uint32_t VBTableOffset = 0;
541 uint32_t Flags = 0;
542 };
543
544 struct SymbolNode : public Node {
545 explicit SymbolNode(NodeKind K) : Node(K) {}
546 void output(OutputStream &OS, OutputFlags Flags) const override;
547 QualifiedNameNode *Name = nullptr;
548 };
549
550 struct SpecialTableSymbolNode : public SymbolNode {
551 explicit SpecialTableSymbolNode()
552 : SymbolNode(NodeKind::SpecialTableSymbol) {}
553
554 void output(OutputStream &OS, OutputFlags Flags) const override;
555 QualifiedNameNode *TargetName = nullptr;
556 Qualifiers Quals;
557 };
558
559 struct LocalStaticGuardVariableNode : public SymbolNode {
560 LocalStaticGuardVariableNode()
561 : SymbolNode(NodeKind::LocalStaticGuardVariable) {}
562
563 void output(OutputStream &OS, OutputFlags Flags) const override;
564
565 bool IsVisible = false;
566 };
567
568 struct EncodedStringLiteralNode : public SymbolNode {
569 EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {}
570
571 void output(OutputStream &OS, OutputFlags Flags) const override;
572
573 StringView DecodedString;
574 bool IsTruncated = false;
575 CharKind Char = CharKind::Char;
576 };
577
578 struct VariableSymbolNode : public SymbolNode {
579 VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {}
580
581 void output(OutputStream &OS, OutputFlags Flags) const override;
582
583 StorageClass SC = StorageClass::None;
584 TypeNode *Type = nullptr;
585 };
586
587 struct FunctionSymbolNode : public SymbolNode {
588 FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
589
590 void output(OutputStream &OS, OutputFlags Flags) const override;
591
592 FunctionSignatureNode *Signature = nullptr;
593 };
594
595 } // namespace ms_demangle
596 } // namespace llvm
597
598 #endif
1313 //
1414 //===----------------------------------------------------------------------===//
1515
16 #include "MicrosoftDemangleNodes.h"
16 #include "llvm/Demangle/MicrosoftDemangle.h"
1717 #include "llvm/Demangle/Demangle.h"
18 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
1819
1920 #include "llvm/Demangle/Compiler.h"
2021 #include "llvm/Demangle/StringView.h"
3233 return !S.empty() && std::isdigit(S.front());
3334 }
3435
35 enum class QualifierMangleMode { Drop, Mangle, Result };
3636
3737 struct NodeList {
3838 Node *N = nullptr;
3939 NodeList *Next = nullptr;
40 };
41
42 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
43
44 enum NameBackrefBehavior : uint8_t {
45 NBB_None = 0, // don't save any names as backrefs.
46 NBB_Template = 1 << 0, // save template instanations.
47 NBB_Simple = 1 << 1, // save simple names.
4840 };
4941
5042 static bool isMemberPointer(StringView MangledName) {
244236 }
245237 return std::make_pair(Q_None, PointerAffinity::Pointer);
246238 }
247
248 namespace {
249
250 struct BackrefContext {
251 static constexpr size_t Max = 10;
252
253 TypeNode *FunctionParams[Max];
254 size_t FunctionParamCount = 0;
255
256 // The first 10 BackReferences in a mangled name can be back-referenced by
257 // special name @[0-9]. This is a storage for the first 10 BackReferences.
258 NamedIdentifierNode *Names[Max];
259 size_t NamesCount = 0;
260 };
261
262 // Demangler class takes the main role in demangling symbols.
263 // It has a set of functions to parse mangled symbols into Type instances.
264 // It also has a set of functions to cnovert Type instances to strings.
265 class Demangler {
266 public:
267 Demangler() = default;
268 virtual ~Demangler() = default;
269
270 // You are supposed to call parse() first and then check if error is true. If
271 // it is false, call output() to write the formatted name to the given stream.
272 SymbolNode *parse(StringView &MangledName);
273
274 // True if an error occurred.
275 bool Error = false;
276
277 void dumpBackReferences();
278
279 private:
280 SymbolNode *demangleEncodedSymbol(StringView &MangledName,
281 QualifiedNameNode *QN);
282
283 VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
284 StorageClass SC);
285 FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
286
287 Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
288
289 // Parser functions. This is a recursive-descent parser.
290 TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
291 PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
292 CustomTypeNode *demangleCustomType(StringView &MangledName);
293 TagTypeNode *demangleClassType(StringView &MangledName);
294 PointerTypeNode *demanglePointerType(StringView &MangledName);
295 PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
296 FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
297 bool HasThisQuals);
298
299 ArrayTypeNode *demangleArrayType(StringView &MangledName);
300
301 NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
302 NodeArrayNode *demangleFunctionParameterList(StringView &MangledName);
303
304 std::pair demangleNumber(StringView &MangledName);
305 uint64_t demangleUnsigned(StringView &MangledName);
306 int64_t demangleSigned(StringView &MangledName);
307
308 void memorizeString(StringView s);
309 void memorizeIdentifier(IdentifierNode *Identifier);
310
311 /// Allocate a copy of \p Borrowed into memory that we own.
312 StringView copyString(StringView Borrowed);
313
314 QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
315 QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
316
317 IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
318 bool Memorize);
319 IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
320 NameBackrefBehavior NBB);
321
322 QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
323 IdentifierNode *UnqualifiedName);
324 IdentifierNode *demangleNameScopePiece(StringView &MangledName);
325
326 NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
327 IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
328 NameBackrefBehavior NBB);
329 IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
330 IdentifierNode *
331 demangleFunctionIdentifierCode(StringView &MangledName,
332 FunctionIdentifierCodeGroup Group);
333 StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
334 bool IsDestructor);
335 ConversionOperatorIdentifierNode *
336 demangleConversionOperatorIdentifier(StringView &MangledName);
337 LiteralOperatorIdentifierNode *
338 demangleLiteralOperatorIdentifier(StringView &MangledName);
339
340 SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
341 SpecialTableSymbolNode *
342 demangleSpecialTableSymbolNode(StringView &MangledName,
343 SpecialIntrinsicKind SIK);
344 LocalStaticGuardVariableNode *
345 demangleLocalStaticGuard(StringView &MangledName);
346 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
347 StringView &MangledName,
348 StringView VariableName);
349 VariableSymbolNode *
350 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
351 StringView &MangledName);
352 FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
353 bool IsDestructor);
354
355 NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
356 bool Memorize);
357 NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
358 NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
359 EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
360 FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
361
362 StringView demangleSimpleString(StringView &MangledName, bool Memorize);
363
364 FuncClass demangleFunctionClass(StringView &MangledName);
365 CallingConv demangleCallingConvention(StringView &MangledName);
366 StorageClass demangleVariableStorageClass(StringView &MangledName);
367 void demangleThrowSpecification(StringView &MangledName);
368 wchar_t demangleWcharLiteral(StringView &MangledName);
369 uint8_t demangleCharLiteral(StringView &MangledName);
370
371 std::pair demangleQualifiers(StringView &MangledName);
372
373 // Memory allocator.
374 ArenaAllocator Arena;
375
376 // A single type uses one global back-ref table for all function params.
377 // This means back-refs can even go "into" other types. Examples:
378 //
379 // // Second int* is a back-ref to first.
380 // void foo(int *, int*);
381 //
382 // // Second int* is not a back-ref to first (first is not a function param).
383 // int* foo(int*);
384 //
385 // // Second int* is a back-ref to first (ALL function types share the same
386 // // back-ref map.
387 // using F = void(*)(int*);
388 // F G(int *);
389 BackrefContext Backrefs;
390 };
391 } // namespace
392239
393240 StringView Demangler::copyString(StringView Borrowed) {
394241 char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1);
885732 return Symbol;
886733 }
887734
735 TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
736 if (!MangledName.consumeFront(".?A"))
737 return nullptr;
738 MangledName.consumeFront(".?A");
739 if (MangledName.empty())
740 return nullptr;
741
742 return demangleClassType(MangledName);
743 }
744
888745 // ::=
889746 // ::= 0 # private static member
890747 // ::= 1 # protected static member
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "MicrosoftDemangleNodes.h"
13 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
1414 #include "llvm/Demangle/Compiler.h"
1515 #include "llvm/Demangle/Utility.h"
1616 #include
+0
-697
lib/Demangle/MicrosoftDemangleNodes.h less more
None #ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
1 #define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
2
3 #include "llvm/Demangle/Compiler.h"
4 #include "llvm/Demangle/StringView.h"
5 #include
6
7 class OutputStream;
8
9 namespace llvm {
10 namespace ms_demangle {
11
12 // This memory allocator is extremely fast, but it doesn't call dtors
13 // for allocated objects. That means you can't use STL containers
14 // (such as std::vector) with this allocator. But it pays off --
15 // the demangler is 3x faster with this allocator compared to one with
16 // STL containers.
17 constexpr size_t AllocUnit = 4096;
18
19 class ArenaAllocator {
20 struct AllocatorNode {
21 uint8_t *Buf = nullptr;
22 size_t Used = 0;
23 size_t Capacity = 0;
24 AllocatorNode *Next = nullptr;
25 };
26
27 void addNode(size_t Capacity) {
28 AllocatorNode *NewHead = new AllocatorNode;
29 NewHead->Buf = new uint8_t[Capacity];
30 NewHead->Next = Head;
31 NewHead->Capacity = Capacity;
32 Head = NewHead;
33 NewHead->Used = 0;
34 }
35
36 public:
37 ArenaAllocator() { addNode(AllocUnit); }
38
39 ~ArenaAllocator() {
40 while (Head) {
41 assert(Head->Buf);
42 delete[] Head->Buf;
43 AllocatorNode *Next = Head->Next;
44 delete Head;
45 Head = Next;
46 }
47 }
48
49 char *allocUnalignedBuffer(size_t Length) {
50 uint8_t *Buf = Head->Buf + Head->Used;
51
52 Head->Used += Length;
53 if (Head->Used > Head->Capacity) {
54 // It's possible we need a buffer which is larger than our default unit
55 // size, so we need to be careful to add a node with capacity that is at
56 // least as large as what we need.
57 addNode(std::max(AllocUnit, Length));
58 Head->Used = Length;
59 Buf = Head->Buf;
60 }
61
62 return reinterpret_cast(Buf);
63 }
64
65 template
66 T *allocArray(size_t Count) {
67
68 size_t Size = Count * sizeof(T);
69 assert(Head && Head->Buf);
70
71 size_t P = (size_t)Head->Buf + Head->Used;
72 uintptr_t AlignedP =
73 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
74 uint8_t *PP = (uint8_t *)AlignedP;
75 size_t Adjustment = AlignedP - P;
76
77 Head->Used += Size + Adjustment;
78 if (Head->Used < Head->Capacity)
79 return new (PP) T[Count]();
80
81 addNode(AllocUnit);
82 Head->Used = Size;
83 return new (Head->Buf) T[Count]();
84 }
85
86 template T *alloc(Args &&... ConstructorArgs) {
87
88 size_t Size = sizeof(T);
89 assert(Head && Head->Buf);
90
91 size_t P = (size_t)Head->Buf + Head->Used;
92 uintptr_t AlignedP =
93 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
94 uint8_t *PP = (uint8_t *)AlignedP;
95 size_t Adjustment = AlignedP - P;
96
97 Head->Used += Size + Adjustment;
98 if (Head->Used < Head->Capacity)
99 return new (PP) T(std::forward(ConstructorArgs)...);
100
101 addNode(AllocUnit);
102 Head->Used = Size;
103 return new (Head->Buf) T(std::forward(ConstructorArgs)...);
104 }
105
106 private:
107 AllocatorNode *Head = nullptr;
108 };
109
110 // Storage classes
111 enum Qualifiers : uint8_t {
112 Q_None = 0,
113 Q_Const = 1 << 0,
114 Q_Volatile = 1 << 1,
115 Q_Far = 1 << 2,
116 Q_Huge = 1 << 3,
117 Q_Unaligned = 1 << 4,
118 Q_Restrict = 1 << 5,
119 Q_Pointer64 = 1 << 6
120 };
121
122 enum class StorageClass : uint8_t {
123 None,
124 PrivateStatic,
125 ProtectedStatic,
126 PublicStatic,
127 Global,
128 FunctionLocalStatic,
129 };
130
131 enum class PointerAffinity { None, Pointer, Reference, RValueReference };
132 enum class FunctionRefQualifier { None, Reference, RValueReference };
133
134 // Calling conventions
135 enum class CallingConv : uint8_t {
136 None,
137 Cdecl,
138 Pascal,
139 Thiscall,
140 Stdcall,
141 Fastcall,
142 Clrcall,
143 Eabi,
144 Vectorcall,
145 Regcall,
146 };
147
148 enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
149
150 enum OutputFlags {
151 OF_Default = 0,
152 OF_NoCallingConvention = 1,
153 };
154
155 // Types
156 enum class PrimitiveKind {
157 Void,
158 Bool,
159 Char,
160 Schar,
161 Uchar,
162 Char16,
163 Char32,
164 Short,
165 Ushort,
166 Int,
167 Uint,
168 Long,
169 Ulong,
170 Int64,
171 Uint64,
172 Wchar,
173 Float,
174 Double,
175 Ldouble,
176 Nullptr,
177 };
178
179 enum class CharKind {
180 Char,
181 Char16,
182 Char32,
183 Wchar,
184 };
185
186 enum class IntrinsicFunctionKind : uint8_t {
187 None,
188 New, // ?2 # operator new
189 Delete, // ?3 # operator delete
190 Assign, // ?4 # operator=
191 RightShift, // ?5 # operator>>
192 LeftShift, // ?6 # operator<<
193 LogicalNot, // ?7 # operator!
194 Equals, // ?8 # operator==
195 NotEquals, // ?9 # operator!=
196 ArraySubscript, // ?A # operator[]
197 Pointer, // ?C # operator->
198 Dereference, // ?D # operator*
199 Increment, // ?E # operator++
200 Decrement, // ?F # operator--
201 Minus, // ?G # operator-
202 Plus, // ?H # operator+
203 BitwiseAnd, // ?I # operator&
204 MemberPointer, // ?J # operator->*
205 Divide, // ?K # operator/
206 Modulus, // ?L # operator%
207 LessThan, // ?M operator<
208 LessThanEqual, // ?N operator<=
209 GreaterThan, // ?O operator>
210 GreaterThanEqual, // ?P operator>=
211 Comma, // ?Q operator,
212 Parens, // ?R operator()
213 BitwiseNot, // ?S operator~
214 BitwiseXor, // ?T operator^
215 BitwiseOr, // ?U operator|
216 LogicalAnd, // ?V operator&&
217 LogicalOr, // ?W operator||
218 TimesEqual, // ?X operator*=
219 PlusEqual, // ?Y operator+=
220 MinusEqual, // ?Z operator-=
221 DivEqual, // ?_0 operator/=
222 ModEqual, // ?_1 operator%=
223 RshEqual, // ?_2 operator>>=
224 LshEqual, // ?_3 operator<<=
225 BitwiseAndEqual, // ?_4 operator&=
226 BitwiseOrEqual, // ?_5 operator|=
227 BitwiseXorEqual, // ?_6 operator^=
228 VbaseDtor, // ?_D # vbase destructor
229 VecDelDtor, // ?_E # vector deleting destructor
230 DefaultCtorClosure, // ?_F # default constructor closure
231 ScalarDelDtor, // ?_G # scalar deleting destructor
232 VecCtorIter, // ?_H # vector constructor iterator
233 VecDtorIter, // ?_I # vector destructor iterator
234 VecVbaseCtorIter, // ?_J # vector vbase constructor iterator
235 VdispMap, // ?_K # virtual displacement map
236 EHVecCtorIter, // ?_L # eh vector constructor iterator
237 EHVecDtorIter, // ?_M # eh vector destructor iterator
238 EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
239 CopyCtorClosure, // ?_O # copy constructor closure
240 LocalVftableCtorClosure, // ?_T # local vftable constructor closure
241 ArrayNew, // ?_U operator new[]
242 ArrayDelete, // ?_V operator delete[]
243 ManVectorCtorIter, // ?__A managed vector ctor iterator
244 ManVectorDtorIter, // ?__B managed vector dtor iterator
245 EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator
246 EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator
247 VectorCopyCtorIter, // ?__G vector copy constructor iterator
248 VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator
249 ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor
250 CoAwait, // ?__L co_await
251 Spaceship, // operator<=>
252 MaxIntrinsic
253 };
254
255 enum class SpecialIntrinsicKind {
256 None,
257 Vftable,
258 Vbtable,
259 Typeof,
260 VcallThunk,
261 LocalStaticGuard,
262 StringLiteralSymbol,
263 UdtReturning,
264 Unknown,
265 DynamicInitializer,
266 DynamicAtexitDestructor,
267 RttiTypeDescriptor,
268 RttiBaseClassDescriptor,
269 RttiBaseClassArray,
270 RttiClassHierarchyDescriptor,
271 RttiCompleteObjLocator,
272 LocalVftable,
273 LocalStaticThreadGuard,
274 };
275
276 // Function classes
277 enum FuncClass : uint16_t {
278 FC_None = 0,
279 FC_Public = 1 << 0,
280 FC_Protected = 1 << 1,
281 FC_Private = 1 << 2,
282 FC_Global = 1 << 3,
283 FC_Static = 1 << 4,
284 FC_Virtual = 1 << 5,
285 FC_Far = 1 << 6,
286 FC_ExternC = 1 << 7,
287 FC_NoParameterList = 1 << 8,
288 FC_VirtualThisAdjust = 1 << 9,
289 FC_VirtualThisAdjustEx = 1 << 10,
290 FC_StaticThisAdjust = 1 << 11,
291 };
292
293 enum class TagKind { Class, Struct, Union, Enum };
294
295 enum class NodeKind {
296 Unknown,
297 Md5Symbol,
298 PrimitiveType,
299 FunctionSignature,
300 Identifier,
301 NamedIdentifier,
302 VcallThunkIdentifier,
303 LocalStaticGuardIdentifier,
304 IntrinsicFunctionIdentifier,
305 ConversionOperatorIdentifier,
306 DynamicStructorIdentifier,
307 StructorIdentifier,
308 LiteralOperatorIdentifier,
309 ThunkSignature,
310 PointerType,
311 TagType,
312 ArrayType,
313 Custom,
314 IntrinsicType,
315 NodeArray,
316 QualifiedName,
317 TemplateParameterReference,
318 EncodedStringLiteral,
319 IntegerLiteral,
320 RttiBaseClassDescriptor,
321 LocalStaticGuardVariable,
322 FunctionSymbol,
323 VariableSymbol,
324 SpecialTableSymbol
325 };
326
327 struct Node {
328 explicit Node(NodeKind K) : Kind(K) {}
329 virtual ~Node() = default;
330
331 NodeKind kind() const { return Kind; }
332
333 virtual void output(OutputStream &OS, OutputFlags Flags) const = 0;
334
335 private:
336 NodeKind Kind;
337 };
338
339 struct TypeNode;
340 struct PrimitiveTypeNode;
341 struct FunctionSignatureNode;
342 struct IdentifierNode;
343 struct NamedIdentifierNode;
344 struct VcallThunkIdentifierNode;
345 struct IntrinsicFunctionIdentifierNode;
346 struct LiteralOperatorIdentifierNode;
347 struct ConversionOperatorIdentifierNode;
348 struct StructorIdentifierNode;
349 struct ThunkSignatureNode;
350 struct PointerTypeNode;
351 struct ArrayTypeNode;
352 struct CustomNode;
353 struct TagTypeNode;
354 struct IntrinsicTypeNode;
355 struct NodeArrayNode;
356 struct QualifiedNameNode;
357 struct TemplateParameterReferenceNode;
358 struct EncodedStringLiteralNode;
359 struct IntegerLiteralNode;
360 struct RttiBaseClassDescriptorNode;
361 struct LocalStaticGuardVariableNode;
362 struct SymbolNode;
363 struct FunctionSymbolNode;
364 struct VariableSymbolNode;
365 struct SpecialTableSymbolNode;
366
367 struct TypeNode : public Node {
368 explicit TypeNode(NodeKind K) : Node(K) {}
369
370 virtual void outputPre(OutputStream &OS, OutputFlags Flags) const = 0;
371 virtual void outputPost(OutputStream &OS, OutputFlags Flags) const = 0;
372
373 void output(OutputStream &OS, OutputFlags Flags) const override {
374 outputPre(OS, Flags);
375 outputPost(OS, Flags);
376 }
377
378 void outputQuals(bool SpaceBefore, bool SpaceAfter) const;
379
380 Qualifiers Quals = Q_None;
381 };
382
383 struct PrimitiveTypeNode : public TypeNode {
384 explicit PrimitiveTypeNode(PrimitiveKind K)
385 : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {}
386
387 void outputPre(OutputStream &OS, OutputFlags Flags) const;
388 void outputPost(OutputStream &OS, OutputFlags Flags) const {}
389
390 PrimitiveKind PrimKind;
391 };
392
393 struct FunctionSignatureNode : public TypeNode {
394 explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
395 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
396
397 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
398 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
399
400 // Valid if this FunctionTypeNode is the Pointee of a PointerType or
401 // MemberPointerType.
402 PointerAffinity Affinity = PointerAffinity::None;
403
404 // The function's calling convention.
405 CallingConv CallConvention = CallingConv::None;
406
407 // Function flags (gloabl, public, etc)
408 FuncClass FunctionClass = FC_Global;
409
410 FunctionRefQualifier RefQualifier = FunctionRefQualifier::None;
411
412 // The return type of the function.
413 TypeNode *ReturnType = nullptr;
414
415 // True if this is a C-style ... varargs function.
416 bool IsVariadic = false;
417
418 // Function parameters
419 NodeArrayNode *Params = nullptr;
420 };
421
422 struct IdentifierNode : public Node {
423 explicit IdentifierNode(NodeKind K) : Node(K) {}
424
425 NodeArrayNode *TemplateParams = nullptr;
426
427 protected:
428 void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const;
429 };
430
431 struct VcallThunkIdentifierNode : public IdentifierNode {
432 VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {}
433
434 void output(OutputStream &OS, OutputFlags Flags) const override;
435
436 uint64_t OffsetInVTable = 0;
437 };
438
439 struct DynamicStructorIdentifierNode : public IdentifierNode {
440 DynamicStructorIdentifierNode()
441 : IdentifierNode(NodeKind::DynamicStructorIdentifier) {}
442
443 void output(OutputStream &OS, OutputFlags Flags) const override;
444
445 VariableSymbolNode *Variable = nullptr;
446 QualifiedNameNode *Name = nullptr;
447 bool IsDestructor = false;
448 };
449
450 struct NamedIdentifierNode : public IdentifierNode {
451 NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {}
452
453 void output(OutputStream &OS, OutputFlags Flags) const override;
454
455 StringView Name;
456 };
457
458 struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
459 explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator)
460 : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier),
461 Operator(Operator) {}
462
463 void output(OutputStream &OS, OutputFlags Flags) const override;
464
465 IntrinsicFunctionKind Operator;
466 };
467
468 struct LiteralOperatorIdentifierNode : public IdentifierNode {
469 LiteralOperatorIdentifierNode()
470 : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {}
471
472 void output(OutputStream &OS, OutputFlags Flags) const override;
473
474 StringView Name;
475 };
476
477 struct LocalStaticGuardIdentifierNode : public IdentifierNode {
478 LocalStaticGuardIdentifierNode()
479 : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {}
480
481 void output(OutputStream &OS, OutputFlags Flags) const override;
482
483 uint32_t ScopeIndex = 0;
484 };
485
486 struct ConversionOperatorIdentifierNode : public IdentifierNode {
487 ConversionOperatorIdentifierNode()
488 : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {}
489
490 void output(OutputStream &OS, OutputFlags Flags) const override;
491
492 // The type that this operator converts too.
493 TypeNode *TargetType = nullptr;
494 };
495
496 struct StructorIdentifierNode : public IdentifierNode {
497 StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {}
498 explicit StructorIdentifierNode(bool IsDestructor)
499 : IdentifierNode(NodeKind::StructorIdentifier),
500 IsDestructor(IsDestructor) {}
501
502 void output(OutputStream &OS, OutputFlags Flags) const override;
503
504 // The name of the class that this is a structor of.
505 IdentifierNode *Class = nullptr;
506 bool IsDestructor = false;
507 };
508
509 struct ThunkSignatureNode : public FunctionSignatureNode {
510 ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {}
511
512 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
513 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
514
515 struct ThisAdjustor {
516 uint32_t StaticOffset = 0;
517 int32_t VBPtrOffset = 0;
518 int32_t VBOffsetOffset = 0;
519 int32_t VtordispOffset = 0;
520 };
521
522 ThisAdjustor ThisAdjust;
523 };
524
525 struct PointerTypeNode : public TypeNode {
526 PointerTypeNode() : TypeNode(NodeKind::PointerType) {}
527 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
528 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
529
530 // Is this a pointer, reference, or rvalue-reference?
531 PointerAffinity Affinity = PointerAffinity::None;
532
533 // If this is a member pointer, this is the class that the member is in.
534 QualifiedNameNode *ClassParent = nullptr;
535
536 // Represents a type X in "a pointer to X", "a reference to X", or
537 // "rvalue-reference to X"
538 TypeNode *Pointee = nullptr;
539 };
540
541 struct TagTypeNode : public TypeNode {
542 explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {}
543
544 void outputPre(OutputStream &OS, OutputFlags Flags) const;
545 void outputPost(OutputStream &OS, OutputFlags Flags) const;
546
547 QualifiedNameNode *QualifiedName = nullptr;
548 TagKind Tag;
549 };
550
551 struct ArrayTypeNode : public TypeNode {
552 ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {}
553
554 void outputPre(OutputStream &OS, OutputFlags Flags) const;
555 void outputPost(OutputStream &OS, OutputFlags Flags) const;
556
557 void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const;
558 void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const;
559
560 // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]`
561 NodeArrayNode *Dimensions = nullptr;
562
563 // The type of array element.
564 TypeNode *ElementType = nullptr;
565 };
566
567 struct IntrinsicNode : public TypeNode {
568 IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
569 void output(OutputStream &OS, OutputFlags Flags) const override {}
570 };
571
572 struct CustomTypeNode : public TypeNode {
573 CustomTypeNode() : TypeNode(NodeKind::Custom) {}
574
575 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
576 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
577
578 IdentifierNode *Identifier;
579 };
580
581 struct NodeArrayNode : public Node {
582 NodeArrayNode() : Node(NodeKind::NodeArray) {}
583
584 void output(OutputStream &OS, OutputFlags Flags) const override;
585
586 void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const;
587
588 Node **Nodes = 0;
589 size_t Count = 0;
590 };
591
592 struct QualifiedNameNode : public Node {
593 QualifiedNameNode() : Node(NodeKind::QualifiedName) {}
594
595 void output(OutputStream &OS, OutputFlags Flags) const override;
596
597 NodeArrayNode *Components = nullptr;
598
599 IdentifierNode *getUnqualifiedIdentifier() {
600 Node *LastComponent = Components->Nodes[Components->Count - 1];
601 return static_cast(LastComponent);
602 }
603 };
604
605 struct TemplateParameterReferenceNode : public Node {
606 TemplateParameterReferenceNode()
607 : Node(NodeKind::TemplateParameterReference) {}
608
609 void output(OutputStream &OS, OutputFlags Flags) const override;
610
611 SymbolNode *Symbol = nullptr;
612
613 int ThunkOffsetCount = 0;
614 std::array ThunkOffsets;
615 PointerAffinity Affinity = PointerAffinity::None;
616 bool IsMemberPointer = false;
617 };
618
619 struct IntegerLiteralNode : public Node {
620 IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) {}
621 IntegerLiteralNode(uint64_t Value, bool IsNegative)
622 : Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {}
623
624 void output(OutputStream &OS, OutputFlags Flags) const override;
625
626 uint64_t Value = 0;
627 bool IsNegative = false;
628 };
629
630 struct RttiBaseClassDescriptorNode : public IdentifierNode {
631 RttiBaseClassDescriptorNode()
632 : IdentifierNode(NodeKind::RttiBaseClassDescriptor) {}
633
634 void output(OutputStream &OS, OutputFlags Flags) const override;
635
636 uint32_t NVOffset = 0;
637 int32_t VBPtrOffset = 0;
638 uint32_t VBTableOffset = 0;
639 uint32_t Flags = 0;
640 };
641
642 struct SymbolNode : public Node {
643 explicit SymbolNode(NodeKind K) : Node(K) {}
644 void output(OutputStream &OS, OutputFlags Flags) const override;
645 QualifiedNameNode *Name = nullptr;
646 };
647
648 struct SpecialTableSymbolNode : public SymbolNode {
649 explicit SpecialTableSymbolNode()
650 : SymbolNode(NodeKind::SpecialTableSymbol) {}
651
652 void output(OutputStream &OS, OutputFlags Flags) const override;
653 QualifiedNameNode *TargetName = nullptr;
654 Qualifiers Quals;
655 };
656
657 struct LocalStaticGuardVariableNode : public SymbolNode {
658 LocalStaticGuardVariableNode()
659 : SymbolNode(NodeKind::LocalStaticGuardVariable) {}
660
661 void output(OutputStream &OS, OutputFlags Flags) const override;
662
663 bool IsVisible = false;
664 };
665
666 struct EncodedStringLiteralNode : public SymbolNode {
667 EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {}
668
669 void output(OutputStream &OS, OutputFlags Flags) const override;
670
671 StringView DecodedString;
672 bool IsTruncated = false;
673 CharKind Char = CharKind::Char;
674 };
675
676 struct VariableSymbolNode : public SymbolNode {
677 VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {}
678
679 void output(OutputStream &OS, OutputFlags Flags) const override;
680
681 StorageClass SC = StorageClass::None;
682 TypeNode *Type = nullptr;
683 };
684
685 struct FunctionSymbolNode : public SymbolNode {
686 FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
687
688 void output(OutputStream &OS, OutputFlags Flags) const override;
689
690 FunctionSignatureNode *Signature = nullptr;
691 };
692
693 } // namespace ms_demangle
694 } // namespace llvm
695
696 #endif