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