1//===- MicrosoftDemangleNodes.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// This file defines the AST nodes used in the MSVC demangler.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
14#define LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
15
16#include <array>
17#include <cstdint>
18#include <string>
19#include <string_view>
20
21namespace llvm {
22namespace itanium_demangle {
23class OutputBuffer;
24}
25}
26
27using llvm::itanium_demangle::OutputBuffer;
28
29namespace llvm {
30namespace ms_demangle {
31
32// Storage classes
33enum Qualifiers : uint8_t {
34 Q_None = 0,
35 Q_Const = 1 << 0,
36 Q_Volatile = 1 << 1,
37 Q_Far = 1 << 2,
38 Q_Huge = 1 << 3,
39 Q_Unaligned = 1 << 4,
40 Q_Restrict = 1 << 5,
41 Q_Pointer64 = 1 << 6
42};
43
44enum class StorageClass : uint8_t {
45 None,
46 PrivateStatic,
47 ProtectedStatic,
48 PublicStatic,
49 Global,
50 FunctionLocalStatic,
51};
52
53enum class PointerAffinity { None, Pointer, Reference, RValueReference };
54enum class FunctionRefQualifier { None, Reference, RValueReference };
55
56// Calling conventions
57enum class CallingConv : uint8_t {
58 None,
59 Cdecl,
60 Pascal,
61 Thiscall,
62 Stdcall,
63 Fastcall,
64 Clrcall,
65 Eabi,
66 Vectorcall,
67 Regcall,
68 Swift, // Clang-only
69 SwiftAsync, // Clang-only
70};
71
72enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
73
74enum OutputFlags {
75 OF_Default = 0,
76 OF_NoCallingConvention = 1,
77 OF_NoTagSpecifier = 2,
78 OF_NoAccessSpecifier = 4,
79 OF_NoMemberType = 8,
80 OF_NoReturnType = 16,
81 OF_NoVariableType = 32,
82};
83
84// Types
85enum class PrimitiveKind {
86 Void,
87 Bool,
88 Char,
89 Schar,
90 Uchar,
91 Char8,
92 Char16,
93 Char32,
94 Short,
95 Ushort,
96 Int,
97 Uint,
98 Long,
99 Ulong,
100 Int64,
101 Uint64,
102 Wchar,
103 Float,
104 Double,
105 Ldouble,
106 Nullptr,
107};
108
109enum class CharKind {
110 Char,
111 Char16,
112 Char32,
113 Wchar,
114};
115
116enum class IntrinsicFunctionKind : uint8_t {
117 None,
118 New, // ?2 # operator new
119 Delete, // ?3 # operator delete
120 Assign, // ?4 # operator=
121 RightShift, // ?5 # operator>>
122 LeftShift, // ?6 # operator<<
123 LogicalNot, // ?7 # operator!
124 Equals, // ?8 # operator==
125 NotEquals, // ?9 # operator!=
126 ArraySubscript, // ?A # operator[]
127 Pointer, // ?C # operator->
128 Dereference, // ?D # operator*
129 Increment, // ?E # operator++
130 Decrement, // ?F # operator--
131 Minus, // ?G # operator-
132 Plus, // ?H # operator+
133 BitwiseAnd, // ?I # operator&
134 MemberPointer, // ?J # operator->*
135 Divide, // ?K # operator/
136 Modulus, // ?L # operator%
137 LessThan, // ?M operator<
138 LessThanEqual, // ?N operator<=
139 GreaterThan, // ?O operator>
140 GreaterThanEqual, // ?P operator>=
141 Comma, // ?Q operator,
142 Parens, // ?R operator()
143 BitwiseNot, // ?S operator~
144 BitwiseXor, // ?T operator^
145 BitwiseOr, // ?U operator|
146 LogicalAnd, // ?V operator&&
147 LogicalOr, // ?W operator||
148 TimesEqual, // ?X operator*=
149 PlusEqual, // ?Y operator+=
150 MinusEqual, // ?Z operator-=
151 DivEqual, // ?_0 operator/=
152 ModEqual, // ?_1 operator%=
153 RshEqual, // ?_2 operator>>=
154 LshEqual, // ?_3 operator<<=
155 BitwiseAndEqual, // ?_4 operator&=
156 BitwiseOrEqual, // ?_5 operator|=
157 BitwiseXorEqual, // ?_6 operator^=
158 VbaseDtor, // ?_D # vbase destructor
159 VecDelDtor, // ?_E # vector deleting destructor
160 DefaultCtorClosure, // ?_F # default constructor closure
161 ScalarDelDtor, // ?_G # scalar deleting destructor
162 VecCtorIter, // ?_H # vector constructor iterator
163 VecDtorIter, // ?_I # vector destructor iterator
164 VecVbaseCtorIter, // ?_J # vector vbase constructor iterator
165 VdispMap, // ?_K # virtual displacement map
166 EHVecCtorIter, // ?_L # eh vector constructor iterator
167 EHVecDtorIter, // ?_M # eh vector destructor iterator
168 EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
169 CopyCtorClosure, // ?_O # copy constructor closure
170 LocalVftableCtorClosure, // ?_T # local vftable constructor closure
171 ArrayNew, // ?_U operator new[]
172 ArrayDelete, // ?_V operator delete[]
173 ManVectorCtorIter, // ?__A managed vector ctor iterator
174 ManVectorDtorIter, // ?__B managed vector dtor iterator
175 EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator
176 EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator
177 VectorCopyCtorIter, // ?__G vector copy constructor iterator
178 VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator
179 ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor
180 CoAwait, // ?__L operator co_await
181 Spaceship, // ?__M operator<=>
182 MaxIntrinsic
183};
184
185enum class SpecialIntrinsicKind {
186 None,
187 Vftable,
188 Vbtable,
189 Typeof,
190 VcallThunk,
191 LocalStaticGuard,
192 StringLiteralSymbol,
193 UdtReturning,
194 Unknown,
195 DynamicInitializer,
196 DynamicAtexitDestructor,
197 RttiTypeDescriptor,
198 RttiBaseClassDescriptor,
199 RttiBaseClassArray,
200 RttiClassHierarchyDescriptor,
201 RttiCompleteObjLocator,
202 LocalVftable,
203 LocalStaticThreadGuard,
204};
205
206// Function classes
207enum FuncClass : uint16_t {
208 FC_None = 0,
209 FC_Public = 1 << 0,
210 FC_Protected = 1 << 1,
211 FC_Private = 1 << 2,
212 FC_Global = 1 << 3,
213 FC_Static = 1 << 4,
214 FC_Virtual = 1 << 5,
215 FC_Far = 1 << 6,
216 FC_ExternC = 1 << 7,
217 FC_NoParameterList = 1 << 8,
218 FC_VirtualThisAdjust = 1 << 9,
219 FC_VirtualThisAdjustEx = 1 << 10,
220 FC_StaticThisAdjust = 1 << 11,
221};
222
223enum class TagKind { Class, Struct, Union, Enum };
224
225enum class NodeKind {
226 Unknown,
227 Md5Symbol,
228 PrimitiveType,
229 FunctionSignature,
230 Identifier,
231 NamedIdentifier,
232 VcallThunkIdentifier,
233 LocalStaticGuardIdentifier,
234 IntrinsicFunctionIdentifier,
235 ConversionOperatorIdentifier,
236 DynamicStructorIdentifier,
237 StructorIdentifier,
238 LiteralOperatorIdentifier,
239 ThunkSignature,
240 PointerType,
241 TagType,
242 ArrayType,
243 Custom,
244 IntrinsicType,
245 NodeArray,
246 QualifiedName,
247 TemplateParameterReference,
248 EncodedStringLiteral,
249 IntegerLiteral,
250 RttiBaseClassDescriptor,
251 LocalStaticGuardVariable,
252 FunctionSymbol,
253 VariableSymbol,
254 SpecialTableSymbol
255};
256
257struct Node {
258 explicit Node(NodeKind K) : Kind(K) {}
259 virtual ~Node() = default;
260
261 NodeKind kind() const { return Kind; }
262
263 virtual void output(OutputBuffer &OB, OutputFlags Flags) const = 0;
264
265 std::string toString(OutputFlags Flags = OF_Default) const;
266
267private:
268 NodeKind Kind;
269};
270
271struct TypeNode;
272struct PrimitiveTypeNode;
273struct FunctionSignatureNode;
274struct IdentifierNode;
275struct NamedIdentifierNode;
276struct VcallThunkIdentifierNode;
277struct IntrinsicFunctionIdentifierNode;
278struct LiteralOperatorIdentifierNode;
279struct ConversionOperatorIdentifierNode;
280struct StructorIdentifierNode;
281struct ThunkSignatureNode;
282struct PointerTypeNode;
283struct ArrayTypeNode;
284struct TagTypeNode;
285struct NodeArrayNode;
286struct QualifiedNameNode;
287struct TemplateParameterReferenceNode;
288struct EncodedStringLiteralNode;
289struct IntegerLiteralNode;
290struct RttiBaseClassDescriptorNode;
291struct LocalStaticGuardVariableNode;
292struct SymbolNode;
293struct FunctionSymbolNode;
294struct VariableSymbolNode;
295struct SpecialTableSymbolNode;
296
297struct TypeNode : public Node {
298 explicit TypeNode(NodeKind K) : Node(K) {}
299
300 virtual void outputPre(OutputBuffer &OB, OutputFlags Flags) const = 0;
301 virtual void outputPost(OutputBuffer &OB, OutputFlags Flags) const = 0;
302
303 void output(OutputBuffer &OB, OutputFlags Flags) const override {
304 outputPre(OB, Flags);
305 outputPost(OB, Flags);
306 }
307
308 Qualifiers Quals = Q_None;
309};
310
311struct PrimitiveTypeNode : public TypeNode {
312 explicit PrimitiveTypeNode(PrimitiveKind K)
313 : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {}
314
315 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
316 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override {}
317
318 PrimitiveKind PrimKind;
319};
320
321struct FunctionSignatureNode : public TypeNode {
322 explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
323 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
324
325 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
326 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
327
328 // Valid if this FunctionTypeNode is the Pointee of a PointerType or
329 // MemberPointerType.
330 PointerAffinity Affinity = PointerAffinity::None;
331
332 // The function's calling convention.
333 CallingConv CallConvention = CallingConv::None;
334
335 // Function flags (gloabl, public, etc)
336 FuncClass FunctionClass = FC_Global;
337
338 FunctionRefQualifier RefQualifier = FunctionRefQualifier::None;
339
340 // The return type of the function.
341 TypeNode *ReturnType = nullptr;
342
343 // True if this is a C-style ... varargs function.
344 bool IsVariadic = false;
345
346 // Function parameters
347 NodeArrayNode *Params = nullptr;
348
349 // True if the function type is noexcept.
350 bool IsNoexcept = false;
351};
352
353struct IdentifierNode : public Node {
354 explicit IdentifierNode(NodeKind K) : Node(K) {}
355
356 NodeArrayNode *TemplateParams = nullptr;
357
358protected:
359 void outputTemplateParameters(OutputBuffer &OB, OutputFlags Flags) const;
360};
361
362struct VcallThunkIdentifierNode : public IdentifierNode {
363 VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {}
364
365 void output(OutputBuffer &OB, OutputFlags Flags) const override;
366
367 uint64_t OffsetInVTable = 0;
368};
369
370struct DynamicStructorIdentifierNode : public IdentifierNode {
371 DynamicStructorIdentifierNode()
372 : IdentifierNode(NodeKind::DynamicStructorIdentifier) {}
373
374 void output(OutputBuffer &OB, OutputFlags Flags) const override;
375
376 VariableSymbolNode *Variable = nullptr;
377 QualifiedNameNode *Name = nullptr;
378 bool IsDestructor = false;
379};
380
381struct NamedIdentifierNode : public IdentifierNode {
382 NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {}
383
384 void output(OutputBuffer &OB, OutputFlags Flags) const override;
385
386 std::string_view Name;
387};
388
389struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
390 explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator)
391 : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier),
392 Operator(Operator) {}
393
394 void output(OutputBuffer &OB, OutputFlags Flags) const override;
395
396 IntrinsicFunctionKind Operator;
397};
398
399struct LiteralOperatorIdentifierNode : public IdentifierNode {
400 LiteralOperatorIdentifierNode()
401 : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {}
402
403 void output(OutputBuffer &OB, OutputFlags Flags) const override;
404
405 std::string_view Name;
406};
407
408struct LocalStaticGuardIdentifierNode : public IdentifierNode {
409 LocalStaticGuardIdentifierNode()
410 : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {}
411
412 void output(OutputBuffer &OB, OutputFlags Flags) const override;
413
414 bool IsThread = false;
415 uint32_t ScopeIndex = 0;
416};
417
418struct ConversionOperatorIdentifierNode : public IdentifierNode {
419 ConversionOperatorIdentifierNode()
420 : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {}
421
422 void output(OutputBuffer &OB, OutputFlags Flags) const override;
423
424 // The type that this operator converts too.
425 TypeNode *TargetType = nullptr;
426};
427
428struct StructorIdentifierNode : public IdentifierNode {
429 StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {}
430 explicit StructorIdentifierNode(bool IsDestructor)
431 : IdentifierNode(NodeKind::StructorIdentifier),
432 IsDestructor(IsDestructor) {}
433
434 void output(OutputBuffer &OB, OutputFlags Flags) const override;
435
436 // The name of the class that this is a structor of.
437 IdentifierNode *Class = nullptr;
438 bool IsDestructor = false;
439};
440
441struct ThunkSignatureNode : public FunctionSignatureNode {
442 ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {}
443
444 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
445 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
446
447 struct ThisAdjustor {
448 uint32_t StaticOffset = 0;
449 int32_t VBPtrOffset = 0;
450 int32_t VBOffsetOffset = 0;
451 int32_t VtordispOffset = 0;
452 };
453
454 ThisAdjustor ThisAdjust;
455};
456
457struct PointerTypeNode : public TypeNode {
458 PointerTypeNode() : TypeNode(NodeKind::PointerType) {}
459 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
460 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
461
462 // Is this a pointer, reference, or rvalue-reference?
463 PointerAffinity Affinity = PointerAffinity::None;
464
465 // If this is a member pointer, this is the class that the member is in.
466 QualifiedNameNode *ClassParent = nullptr;
467
468 // Represents a type X in "a pointer to X", "a reference to X", or
469 // "rvalue-reference to X"
470 TypeNode *Pointee = nullptr;
471};
472
473struct TagTypeNode : public TypeNode {
474 explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {}
475
476 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
477 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
478
479 QualifiedNameNode *QualifiedName = nullptr;
480 TagKind Tag;
481};
482
483struct ArrayTypeNode : public TypeNode {
484 ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {}
485
486 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
487 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
488
489 void outputDimensionsImpl(OutputBuffer &OB, OutputFlags Flags) const;
490 void outputOneDimension(OutputBuffer &OB, OutputFlags Flags, Node *N) const;
491
492 // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]`
493 NodeArrayNode *Dimensions = nullptr;
494
495 // The type of array element.
496 TypeNode *ElementType = nullptr;
497};
498
499struct IntrinsicNode : public TypeNode {
500 IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
501 void output(OutputBuffer &OB, OutputFlags Flags) const override {}
502};
503
504struct CustomTypeNode : public TypeNode {
505 CustomTypeNode() : TypeNode(NodeKind::Custom) {}
506
507 void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
508 void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
509
510 IdentifierNode *Identifier = nullptr;
511};
512
513struct NodeArrayNode : public Node {
514 NodeArrayNode() : Node(NodeKind::NodeArray) {}
515
516 void output(OutputBuffer &OB, OutputFlags Flags) const override;
517
518 void output(OutputBuffer &OB, OutputFlags Flags,
519 std::string_view Separator) const;
520
521 Node **Nodes = nullptr;
522 size_t Count = 0;
523};
524
525struct QualifiedNameNode : public Node {
526 QualifiedNameNode() : Node(NodeKind::QualifiedName) {}
527
528 void output(OutputBuffer &OB, OutputFlags Flags) const override;
529
530 NodeArrayNode *Components = nullptr;
531
532 IdentifierNode *getUnqualifiedIdentifier() {
533 Node *LastComponent = Components->Nodes[Components->Count - 1];
534 return static_cast<IdentifierNode *>(LastComponent);
535 }
536};
537
538struct TemplateParameterReferenceNode : public Node {
539 TemplateParameterReferenceNode()
540 : Node(NodeKind::TemplateParameterReference) {}
541
542 void output(OutputBuffer &OB, OutputFlags Flags) const override;
543
544 SymbolNode *Symbol = nullptr;
545
546 int ThunkOffsetCount = 0;
547 std::array<int64_t, 3> ThunkOffsets;
548 PointerAffinity Affinity = PointerAffinity::None;
549 bool IsMemberPointer = false;
550};
551
552struct IntegerLiteralNode : public Node {
553 IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) {}
554 IntegerLiteralNode(uint64_t Value, bool IsNegative)
555 : Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {}
556
557 void output(OutputBuffer &OB, OutputFlags Flags) const override;
558
559 uint64_t Value = 0;
560 bool IsNegative = false;
561};
562
563struct RttiBaseClassDescriptorNode : public IdentifierNode {
564 RttiBaseClassDescriptorNode()
565 : IdentifierNode(NodeKind::RttiBaseClassDescriptor) {}
566
567 void output(OutputBuffer &OB, OutputFlags Flags) const override;
568
569 uint32_t NVOffset = 0;
570 int32_t VBPtrOffset = 0;
571 uint32_t VBTableOffset = 0;
572 uint32_t Flags = 0;
573};
574
575struct SymbolNode : public Node {
576 explicit SymbolNode(NodeKind K) : Node(K) {}
577 void output(OutputBuffer &OB, OutputFlags Flags) const override;
578 QualifiedNameNode *Name = nullptr;
579};
580
581struct SpecialTableSymbolNode : public SymbolNode {
582 explicit SpecialTableSymbolNode()
583 : SymbolNode(NodeKind::SpecialTableSymbol) {}
584
585 void output(OutputBuffer &OB, OutputFlags Flags) const override;
586 QualifiedNameNode *TargetName = nullptr;
587 Qualifiers Quals = Qualifiers::Q_None;
588};
589
590struct LocalStaticGuardVariableNode : public SymbolNode {
591 LocalStaticGuardVariableNode()
592 : SymbolNode(NodeKind::LocalStaticGuardVariable) {}
593
594 void output(OutputBuffer &OB, OutputFlags Flags) const override;
595
596 bool IsVisible = false;
597};
598
599struct EncodedStringLiteralNode : public SymbolNode {
600 EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {}
601
602 void output(OutputBuffer &OB, OutputFlags Flags) const override;
603
604 std::string_view DecodedString;
605 bool IsTruncated = false;
606 CharKind Char = CharKind::Char;
607};
608
609struct VariableSymbolNode : public SymbolNode {
610 VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {}
611
612 void output(OutputBuffer &OB, OutputFlags Flags) const override;
613
614 StorageClass SC = StorageClass::None;
615 TypeNode *Type = nullptr;
616};
617
618struct FunctionSymbolNode : public SymbolNode {
619 FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
620
621 void output(OutputBuffer &OB, OutputFlags Flags) const override;
622
623 FunctionSignatureNode *Signature = nullptr;
624};
625
626} // namespace ms_demangle
627} // namespace llvm
628
629#endif
630

source code of llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h