1 #ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
2 #define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H
4 #include "llvm/Demangle/Compiler.h"
5 #include "llvm/Demangle/StringView.h"
11 namespace ms_demangle
{
13 // This memory allocator is extremely fast, but it doesn't call dtors
14 // for allocated objects. That means you can't use STL containers
15 // (such as std::vector) with this allocator. But it pays off --
16 // the demangler is 3x faster with this allocator compared to one with
18 constexpr size_t AllocUnit
= 4096;
20 class ArenaAllocator
{
21 struct AllocatorNode
{
22 uint8_t *Buf
= nullptr;
25 AllocatorNode
*Next
= nullptr;
28 void addNode(size_t Capacity
) {
29 AllocatorNode
*NewHead
= new AllocatorNode
;
30 NewHead
->Buf
= new uint8_t[Capacity
];
32 NewHead
->Capacity
= Capacity
;
38 ArenaAllocator() { addNode(AllocUnit
); }
44 AllocatorNode
*Next
= Head
->Next
;
50 char *allocUnalignedBuffer(size_t Length
) {
51 uint8_t *Buf
= Head
->Buf
+ Head
->Used
;
54 if (Head
->Used
> Head
->Capacity
) {
55 // It's possible we need a buffer which is larger than our default unit
56 // size, so we need to be careful to add a node with capacity that is at
57 // least as large as what we need.
58 addNode(std::max(AllocUnit
, Length
));
63 return reinterpret_cast<char *>(Buf
);
66 template <typename T
, typename
... Args
>
67 T
*allocArray(size_t Count
) {
69 size_t Size
= Count
* sizeof(T
);
70 assert(Head
&& Head
->Buf
);
72 size_t P
= (size_t)Head
->Buf
+ Head
->Used
;
74 (((size_t)P
+ alignof(T
) - 1) & ~(size_t)(alignof(T
) - 1));
75 uint8_t *PP
= (uint8_t *)AlignedP
;
76 size_t Adjustment
= AlignedP
- P
;
78 Head
->Used
+= Size
+ Adjustment
;
79 if (Head
->Used
< Head
->Capacity
)
80 return new (PP
) T
[Count
]();
84 return new (Head
->Buf
) T
[Count
]();
87 template <typename T
, typename
... Args
> T
*alloc(Args
&&... ConstructorArgs
) {
89 size_t Size
= sizeof(T
);
90 assert(Head
&& Head
->Buf
);
92 size_t P
= (size_t)Head
->Buf
+ Head
->Used
;
94 (((size_t)P
+ alignof(T
) - 1) & ~(size_t)(alignof(T
) - 1));
95 uint8_t *PP
= (uint8_t *)AlignedP
;
96 size_t Adjustment
= AlignedP
- P
;
98 Head
->Used
+= Size
+ Adjustment
;
99 if (Head
->Used
< Head
->Capacity
)
100 return new (PP
) T(std::forward
<Args
>(ConstructorArgs
)...);
104 return new (Head
->Buf
) T(std::forward
<Args
>(ConstructorArgs
)...);
108 AllocatorNode
*Head
= nullptr;
112 enum Qualifiers
: uint8_t {
118 Q_Unaligned
= 1 << 4,
123 enum class StorageClass
: uint8_t {
132 enum class PointerAffinity
{ None
, Pointer
, Reference
, RValueReference
};
133 enum class FunctionRefQualifier
{ None
, Reference
, RValueReference
};
135 // Calling conventions
136 enum class CallingConv
: uint8_t {
149 enum class ReferenceKind
: uint8_t { None
, LValueRef
, RValueRef
};
153 OF_NoCallingConvention
= 1,
157 enum class PrimitiveKind
{
180 enum class CharKind
{
187 enum class IntrinsicFunctionKind
: uint8_t {
189 New
, // ?2 # operator new
190 Delete
, // ?3 # operator delete
191 Assign
, // ?4 # operator=
192 RightShift
, // ?5 # operator>>
193 LeftShift
, // ?6 # operator<<
194 LogicalNot
, // ?7 # operator!
195 Equals
, // ?8 # operator==
196 NotEquals
, // ?9 # operator!=
197 ArraySubscript
, // ?A # operator[]
198 Pointer
, // ?C # operator->
199 Dereference
, // ?D # operator*
200 Increment
, // ?E # operator++
201 Decrement
, // ?F # operator--
202 Minus
, // ?G # operator-
203 Plus
, // ?H # operator+
204 BitwiseAnd
, // ?I # operator&
205 MemberPointer
, // ?J # operator->*
206 Divide
, // ?K # operator/
207 Modulus
, // ?L # operator%
208 LessThan
, // ?M operator<
209 LessThanEqual
, // ?N operator<=
210 GreaterThan
, // ?O operator>
211 GreaterThanEqual
, // ?P operator>=
212 Comma
, // ?Q operator,
213 Parens
, // ?R operator()
214 BitwiseNot
, // ?S operator~
215 BitwiseXor
, // ?T operator^
216 BitwiseOr
, // ?U operator|
217 LogicalAnd
, // ?V operator&&
218 LogicalOr
, // ?W operator||
219 TimesEqual
, // ?X operator*=
220 PlusEqual
, // ?Y operator+=
221 MinusEqual
, // ?Z operator-=
222 DivEqual
, // ?_0 operator/=
223 ModEqual
, // ?_1 operator%=
224 RshEqual
, // ?_2 operator>>=
225 LshEqual
, // ?_3 operator<<=
226 BitwiseAndEqual
, // ?_4 operator&=
227 BitwiseOrEqual
, // ?_5 operator|=
228 BitwiseXorEqual
, // ?_6 operator^=
229 VbaseDtor
, // ?_D # vbase destructor
230 VecDelDtor
, // ?_E # vector deleting destructor
231 DefaultCtorClosure
, // ?_F # default constructor closure
232 ScalarDelDtor
, // ?_G # scalar deleting destructor
233 VecCtorIter
, // ?_H # vector constructor iterator
234 VecDtorIter
, // ?_I # vector destructor iterator
235 VecVbaseCtorIter
, // ?_J # vector vbase constructor iterator
236 VdispMap
, // ?_K # virtual displacement map
237 EHVecCtorIter
, // ?_L # eh vector constructor iterator
238 EHVecDtorIter
, // ?_M # eh vector destructor iterator
239 EHVecVbaseCtorIter
, // ?_N # eh vector vbase constructor iterator
240 CopyCtorClosure
, // ?_O # copy constructor closure
241 LocalVftableCtorClosure
, // ?_T # local vftable constructor closure
242 ArrayNew
, // ?_U operator new[]
243 ArrayDelete
, // ?_V operator delete[]
244 ManVectorCtorIter
, // ?__A managed vector ctor iterator
245 ManVectorDtorIter
, // ?__B managed vector dtor iterator
246 EHVectorCopyCtorIter
, // ?__C EH vector copy ctor iterator
247 EHVectorVbaseCopyCtorIter
, // ?__D EH vector vbase copy ctor iterator
248 VectorCopyCtorIter
, // ?__G vector copy constructor iterator
249 VectorVbaseCopyCtorIter
, // ?__H vector vbase copy constructor iterator
250 ManVectorVbaseCopyCtorIter
, // ?__I managed vector vbase copy constructor
251 CoAwait
, // ?__L co_await
252 Spaceship
, // operator<=>
256 enum class SpecialIntrinsicKind
{
267 DynamicAtexitDestructor
,
269 RttiBaseClassDescriptor
,
271 RttiClassHierarchyDescriptor
,
272 RttiCompleteObjLocator
,
274 LocalStaticThreadGuard
,
278 enum FuncClass
: uint16_t {
281 FC_Protected
= 1 << 1,
288 FC_NoParameterList
= 1 << 8,
289 FC_VirtualThisAdjust
= 1 << 9,
290 FC_VirtualThisAdjustEx
= 1 << 10,
291 FC_StaticThisAdjust
= 1 << 11,
294 enum class TagKind
{ Class
, Struct
, Union
, Enum
};
296 enum class NodeKind
{
303 VcallThunkIdentifier
,
304 LocalStaticGuardIdentifier
,
305 IntrinsicFunctionIdentifier
,
306 ConversionOperatorIdentifier
,
307 DynamicStructorIdentifier
,
309 LiteralOperatorIdentifier
,
318 TemplateParameterReference
,
319 EncodedStringLiteral
,
321 RttiBaseClassDescriptor
,
322 LocalStaticGuardVariable
,
329 explicit Node(NodeKind K
) : Kind(K
) {}
330 virtual ~Node() = default;
332 NodeKind
kind() const { return Kind
; }
334 virtual void output(OutputStream
&OS
, OutputFlags Flags
) const = 0;
341 struct PrimitiveTypeNode
;
342 struct FunctionSignatureNode
;
343 struct IdentifierNode
;
344 struct NamedIdentifierNode
;
345 struct VcallThunkIdentifierNode
;
346 struct IntrinsicFunctionIdentifierNode
;
347 struct LiteralOperatorIdentifierNode
;
348 struct ConversionOperatorIdentifierNode
;
349 struct StructorIdentifierNode
;
350 struct ThunkSignatureNode
;
351 struct PointerTypeNode
;
352 struct ArrayTypeNode
;
355 struct IntrinsicTypeNode
;
356 struct NodeArrayNode
;
357 struct QualifiedNameNode
;
358 struct TemplateParameterReferenceNode
;
359 struct EncodedStringLiteralNode
;
360 struct IntegerLiteralNode
;
361 struct RttiBaseClassDescriptorNode
;
362 struct LocalStaticGuardVariableNode
;
364 struct FunctionSymbolNode
;
365 struct VariableSymbolNode
;
366 struct SpecialTableSymbolNode
;
368 struct TypeNode
: public Node
{
369 explicit TypeNode(NodeKind K
) : Node(K
) {}
371 virtual void outputPre(OutputStream
&OS
, OutputFlags Flags
) const = 0;
372 virtual void outputPost(OutputStream
&OS
, OutputFlags Flags
) const = 0;
374 void output(OutputStream
&OS
, OutputFlags Flags
) const override
{
375 outputPre(OS
, Flags
);
376 outputPost(OS
, Flags
);
379 void outputQuals(bool SpaceBefore
, bool SpaceAfter
) const;
381 Qualifiers Quals
= Q_None
;
384 struct PrimitiveTypeNode
: public TypeNode
{
385 explicit PrimitiveTypeNode(PrimitiveKind K
)
386 : TypeNode(NodeKind::PrimitiveType
), PrimKind(K
) {}
388 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const;
389 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const {}
391 PrimitiveKind PrimKind
;
394 struct FunctionSignatureNode
: public TypeNode
{
395 explicit FunctionSignatureNode(NodeKind K
) : TypeNode(K
) {}
396 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature
) {}
398 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const override
;
399 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const override
;
401 // Valid if this FunctionTypeNode is the Pointee of a PointerType or
402 // MemberPointerType.
403 PointerAffinity Affinity
= PointerAffinity::None
;
405 // The function's calling convention.
406 CallingConv CallConvention
= CallingConv::None
;
408 // Function flags (gloabl, public, etc)
409 FuncClass FunctionClass
= FC_Global
;
411 FunctionRefQualifier RefQualifier
= FunctionRefQualifier::None
;
413 // The return type of the function.
414 TypeNode
*ReturnType
= nullptr;
416 // True if this is a C-style ... varargs function.
417 bool IsVariadic
= false;
419 // Function parameters
420 NodeArrayNode
*Params
= nullptr;
423 struct IdentifierNode
: public Node
{
424 explicit IdentifierNode(NodeKind K
) : Node(K
) {}
426 NodeArrayNode
*TemplateParams
= nullptr;
429 void outputTemplateParameters(OutputStream
&OS
, OutputFlags Flags
) const;
432 struct VcallThunkIdentifierNode
: public IdentifierNode
{
433 VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier
) {}
435 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
437 uint64_t OffsetInVTable
= 0;
440 struct DynamicStructorIdentifierNode
: public IdentifierNode
{
441 DynamicStructorIdentifierNode()
442 : IdentifierNode(NodeKind::DynamicStructorIdentifier
) {}
444 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
446 VariableSymbolNode
*Variable
= nullptr;
447 QualifiedNameNode
*Name
= nullptr;
448 bool IsDestructor
= false;
451 struct NamedIdentifierNode
: public IdentifierNode
{
452 NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier
) {}
454 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
459 struct IntrinsicFunctionIdentifierNode
: public IdentifierNode
{
460 explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator
)
461 : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier
),
462 Operator(Operator
) {}
464 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
466 IntrinsicFunctionKind Operator
;
469 struct LiteralOperatorIdentifierNode
: public IdentifierNode
{
470 LiteralOperatorIdentifierNode()
471 : IdentifierNode(NodeKind::LiteralOperatorIdentifier
) {}
473 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
478 struct LocalStaticGuardIdentifierNode
: public IdentifierNode
{
479 LocalStaticGuardIdentifierNode()
480 : IdentifierNode(NodeKind::LocalStaticGuardIdentifier
) {}
482 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
484 uint32_t ScopeIndex
= 0;
487 struct ConversionOperatorIdentifierNode
: public IdentifierNode
{
488 ConversionOperatorIdentifierNode()
489 : IdentifierNode(NodeKind::ConversionOperatorIdentifier
) {}
491 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
493 // The type that this operator converts too.
494 TypeNode
*TargetType
= nullptr;
497 struct StructorIdentifierNode
: public IdentifierNode
{
498 StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier
) {}
499 explicit StructorIdentifierNode(bool IsDestructor
)
500 : IdentifierNode(NodeKind::StructorIdentifier
),
501 IsDestructor(IsDestructor
) {}
503 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
505 // The name of the class that this is a structor of.
506 IdentifierNode
*Class
= nullptr;
507 bool IsDestructor
= false;
510 struct ThunkSignatureNode
: public FunctionSignatureNode
{
511 ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature
) {}
513 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const override
;
514 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const override
;
516 struct ThisAdjustor
{
517 uint32_t StaticOffset
= 0;
518 int32_t VBPtrOffset
= 0;
519 int32_t VBOffsetOffset
= 0;
520 int32_t VtordispOffset
= 0;
523 ThisAdjustor ThisAdjust
;
526 struct PointerTypeNode
: public TypeNode
{
527 PointerTypeNode() : TypeNode(NodeKind::PointerType
) {}
528 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const override
;
529 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const override
;
531 // Is this a pointer, reference, or rvalue-reference?
532 PointerAffinity Affinity
= PointerAffinity::None
;
534 // If this is a member pointer, this is the class that the member is in.
535 QualifiedNameNode
*ClassParent
= nullptr;
537 // Represents a type X in "a pointer to X", "a reference to X", or
538 // "rvalue-reference to X"
539 TypeNode
*Pointee
= nullptr;
542 struct TagTypeNode
: public TypeNode
{
543 explicit TagTypeNode(TagKind Tag
) : TypeNode(NodeKind::TagType
), Tag(Tag
) {}
545 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const;
546 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const;
548 QualifiedNameNode
*QualifiedName
= nullptr;
552 struct ArrayTypeNode
: public TypeNode
{
553 ArrayTypeNode() : TypeNode(NodeKind::ArrayType
) {}
555 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const;
556 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const;
558 void outputDimensionsImpl(OutputStream
&OS
, OutputFlags Flags
) const;
559 void outputOneDimension(OutputStream
&OS
, OutputFlags Flags
, Node
*N
) const;
561 // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]`
562 NodeArrayNode
*Dimensions
= nullptr;
564 // The type of array element.
565 TypeNode
*ElementType
= nullptr;
568 struct IntrinsicNode
: public TypeNode
{
569 IntrinsicNode() : TypeNode(NodeKind::IntrinsicType
) {}
570 void output(OutputStream
&OS
, OutputFlags Flags
) const override
{}
573 struct CustomTypeNode
: public TypeNode
{
574 CustomTypeNode() : TypeNode(NodeKind::Custom
) {}
576 void outputPre(OutputStream
&OS
, OutputFlags Flags
) const override
;
577 void outputPost(OutputStream
&OS
, OutputFlags Flags
) const override
;
579 IdentifierNode
*Identifier
;
582 struct NodeArrayNode
: public Node
{
583 NodeArrayNode() : Node(NodeKind::NodeArray
) {}
585 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
587 void output(OutputStream
&OS
, OutputFlags Flags
, StringView Separator
) const;
593 struct QualifiedNameNode
: public Node
{
594 QualifiedNameNode() : Node(NodeKind::QualifiedName
) {}
596 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
598 NodeArrayNode
*Components
= nullptr;
600 IdentifierNode
*getUnqualifiedIdentifier() {
601 Node
*LastComponent
= Components
->Nodes
[Components
->Count
- 1];
602 return static_cast<IdentifierNode
*>(LastComponent
);
606 struct TemplateParameterReferenceNode
: public Node
{
607 TemplateParameterReferenceNode()
608 : Node(NodeKind::TemplateParameterReference
) {}
610 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
612 SymbolNode
*Symbol
= nullptr;
614 int ThunkOffsetCount
= 0;
615 std::array
<int64_t, 3> ThunkOffsets
;
616 PointerAffinity Affinity
= PointerAffinity::None
;
617 bool IsMemberPointer
= false;
620 struct IntegerLiteralNode
: public Node
{
621 IntegerLiteralNode() : Node(NodeKind::IntegerLiteral
) {}
622 IntegerLiteralNode(uint64_t Value
, bool IsNegative
)
623 : Node(NodeKind::IntegerLiteral
), Value(Value
), IsNegative(IsNegative
) {}
625 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
628 bool IsNegative
= false;
631 struct RttiBaseClassDescriptorNode
: public IdentifierNode
{
632 RttiBaseClassDescriptorNode()
633 : IdentifierNode(NodeKind::RttiBaseClassDescriptor
) {}
635 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
637 uint32_t NVOffset
= 0;
638 int32_t VBPtrOffset
= 0;
639 uint32_t VBTableOffset
= 0;
643 struct SymbolNode
: public Node
{
644 explicit SymbolNode(NodeKind K
) : Node(K
) {}
645 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
646 QualifiedNameNode
*Name
= nullptr;
649 struct SpecialTableSymbolNode
: public SymbolNode
{
650 explicit SpecialTableSymbolNode()
651 : SymbolNode(NodeKind::SpecialTableSymbol
) {}
653 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
654 QualifiedNameNode
*TargetName
= nullptr;
658 struct LocalStaticGuardVariableNode
: public SymbolNode
{
659 LocalStaticGuardVariableNode()
660 : SymbolNode(NodeKind::LocalStaticGuardVariable
) {}
662 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
664 bool IsVisible
= false;
667 struct EncodedStringLiteralNode
: public SymbolNode
{
668 EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral
) {}
670 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
672 StringView DecodedString
;
673 bool IsTruncated
= false;
674 CharKind Char
= CharKind::Char
;
677 struct VariableSymbolNode
: public SymbolNode
{
678 VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol
) {}
680 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
682 StorageClass SC
= StorageClass::None
;
683 TypeNode
*Type
= nullptr;
686 struct FunctionSymbolNode
: public SymbolNode
{
687 FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol
) {}
689 void output(OutputStream
&OS
, OutputFlags Flags
) const override
;
691 FunctionSignatureNode
*Signature
= nullptr;
694 } // namespace ms_demangle