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