]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Demangle/MicrosoftDemangle.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Demangle / MicrosoftDemangle.h
1 //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
11 #define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
12
13 #include "llvm/Demangle/Compiler.h"
14 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
15 #include "llvm/Demangle/StringView.h"
16 #include "llvm/Demangle/Utility.h"
17
18 #include <utility>
19
20 namespace llvm {
21 namespace ms_demangle {
22 // This memory allocator is extremely fast, but it doesn't call dtors
23 // for allocated objects. That means you can't use STL containers
24 // (such as std::vector) with this allocator. But it pays off --
25 // the demangler is 3x faster with this allocator compared to one with
26 // STL containers.
27 constexpr size_t AllocUnit = 4096;
28
29 class ArenaAllocator {
30   struct AllocatorNode {
31     uint8_t *Buf = nullptr;
32     size_t Used = 0;
33     size_t Capacity = 0;
34     AllocatorNode *Next = nullptr;
35   };
36
37   void addNode(size_t Capacity) {
38     AllocatorNode *NewHead = new AllocatorNode;
39     NewHead->Buf = new uint8_t[Capacity];
40     NewHead->Next = Head;
41     NewHead->Capacity = Capacity;
42     Head = NewHead;
43     NewHead->Used = 0;
44   }
45
46 public:
47   ArenaAllocator() { addNode(AllocUnit); }
48
49   ~ArenaAllocator() {
50     while (Head) {
51       assert(Head->Buf);
52       delete[] Head->Buf;
53       AllocatorNode *Next = Head->Next;
54       delete Head;
55       Head = Next;
56     }
57   }
58
59   char *allocUnalignedBuffer(size_t Length) {
60     uint8_t *Buf = Head->Buf + Head->Used;
61
62     Head->Used += Length;
63     if (Head->Used > Head->Capacity) {
64       // It's possible we need a buffer which is larger than our default unit
65       // size, so we need to be careful to add a node with capacity that is at
66       // least as large as what we need.
67       addNode(std::max(AllocUnit, Length));
68       Head->Used = Length;
69       Buf = Head->Buf;
70     }
71
72     return reinterpret_cast<char *>(Buf);
73   }
74
75   template <typename T, typename... Args> T *allocArray(size_t Count) {
76
77     size_t Size = Count * sizeof(T);
78     assert(Head && Head->Buf);
79
80     size_t P = (size_t)Head->Buf + Head->Used;
81     uintptr_t AlignedP =
82         (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
83     uint8_t *PP = (uint8_t *)AlignedP;
84     size_t Adjustment = AlignedP - P;
85
86     Head->Used += Size + Adjustment;
87     if (Head->Used < Head->Capacity)
88       return new (PP) T[Count]();
89
90     addNode(AllocUnit);
91     Head->Used = Size;
92     return new (Head->Buf) T[Count]();
93   }
94
95   template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
96
97     size_t Size = sizeof(T);
98     assert(Head && Head->Buf);
99
100     size_t P = (size_t)Head->Buf + Head->Used;
101     uintptr_t AlignedP =
102         (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
103     uint8_t *PP = (uint8_t *)AlignedP;
104     size_t Adjustment = AlignedP - P;
105
106     Head->Used += Size + Adjustment;
107     if (Head->Used < Head->Capacity)
108       return new (PP) T(std::forward<Args>(ConstructorArgs)...);
109
110     addNode(AllocUnit);
111     Head->Used = Size;
112     return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
113   }
114
115 private:
116   AllocatorNode *Head = nullptr;
117 };
118
119 struct BackrefContext {
120   static constexpr size_t Max = 10;
121
122   TypeNode *FunctionParams[Max];
123   size_t FunctionParamCount = 0;
124
125   // The first 10 BackReferences in a mangled name can be back-referenced by
126   // special name @[0-9]. This is a storage for the first 10 BackReferences.
127   NamedIdentifierNode *Names[Max];
128   size_t NamesCount = 0;
129 };
130
131 enum class QualifierMangleMode { Drop, Mangle, Result };
132
133 enum NameBackrefBehavior : uint8_t {
134   NBB_None = 0,          // don't save any names as backrefs.
135   NBB_Template = 1 << 0, // save template instanations.
136   NBB_Simple = 1 << 1,   // save simple names.
137 };
138
139 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
140
141 // Demangler class takes the main role in demangling symbols.
142 // It has a set of functions to parse mangled symbols into Type instances.
143 // It also has a set of functions to convert Type instances to strings.
144 class Demangler {
145 public:
146   Demangler() = default;
147   virtual ~Demangler() = default;
148
149   // You are supposed to call parse() first and then check if error is true.  If
150   // it is false, call output() to write the formatted name to the given stream.
151   SymbolNode *parse(StringView &MangledName);
152
153   TagTypeNode *parseTagUniqueName(StringView &MangledName);
154
155   // True if an error occurred.
156   bool Error = false;
157
158   void dumpBackReferences();
159
160 private:
161   SymbolNode *demangleEncodedSymbol(StringView &MangledName,
162                                     QualifiedNameNode *QN);
163
164   VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
165                                                StorageClass SC);
166   FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
167
168   Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
169
170   // Parser functions. This is a recursive-descent parser.
171   TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
172   PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
173   CustomTypeNode *demangleCustomType(StringView &MangledName);
174   TagTypeNode *demangleClassType(StringView &MangledName);
175   PointerTypeNode *demanglePointerType(StringView &MangledName);
176   PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
177   FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
178                                               bool HasThisQuals);
179
180   ArrayTypeNode *demangleArrayType(StringView &MangledName);
181
182   NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
183   NodeArrayNode *demangleFunctionParameterList(StringView &MangledName);
184
185   std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
186   uint64_t demangleUnsigned(StringView &MangledName);
187   int64_t demangleSigned(StringView &MangledName);
188
189   void memorizeString(StringView s);
190   void memorizeIdentifier(IdentifierNode *Identifier);
191
192   /// Allocate a copy of \p Borrowed into memory that we own.
193   StringView copyString(StringView Borrowed);
194
195   QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
196   QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
197
198   IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
199                                               bool Memorize);
200   IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
201                                                 NameBackrefBehavior NBB);
202
203   QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
204                                             IdentifierNode *UnqualifiedName);
205   IdentifierNode *demangleNameScopePiece(StringView &MangledName);
206
207   NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
208   IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
209                                                     NameBackrefBehavior NBB);
210   IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
211   IdentifierNode *
212   demangleFunctionIdentifierCode(StringView &MangledName,
213                                  FunctionIdentifierCodeGroup Group);
214   StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
215                                                      bool IsDestructor);
216   ConversionOperatorIdentifierNode *
217   demangleConversionOperatorIdentifier(StringView &MangledName);
218   LiteralOperatorIdentifierNode *
219   demangleLiteralOperatorIdentifier(StringView &MangledName);
220
221   SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
222   SpecialTableSymbolNode *
223   demangleSpecialTableSymbolNode(StringView &MangledName,
224                                  SpecialIntrinsicKind SIK);
225   LocalStaticGuardVariableNode *
226   demangleLocalStaticGuard(StringView &MangledName);
227   VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
228                                               StringView &MangledName,
229                                               StringView VariableName);
230   VariableSymbolNode *
231   demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
232                                       StringView &MangledName);
233   FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
234                                            bool IsDestructor);
235
236   NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
237                                           bool Memorize);
238   NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
239   NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
240   EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
241   FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
242
243   StringView demangleSimpleString(StringView &MangledName, bool Memorize);
244
245   FuncClass demangleFunctionClass(StringView &MangledName);
246   CallingConv demangleCallingConvention(StringView &MangledName);
247   StorageClass demangleVariableStorageClass(StringView &MangledName);
248   bool demangleThrowSpecification(StringView &MangledName);
249   wchar_t demangleWcharLiteral(StringView &MangledName);
250   uint8_t demangleCharLiteral(StringView &MangledName);
251
252   std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
253
254   // Memory allocator.
255   ArenaAllocator Arena;
256
257   // A single type uses one global back-ref table for all function params.
258   // This means back-refs can even go "into" other types.  Examples:
259   //
260   //  // Second int* is a back-ref to first.
261   //  void foo(int *, int*);
262   //
263   //  // Second int* is not a back-ref to first (first is not a function param).
264   //  int* foo(int*);
265   //
266   //  // Second int* is a back-ref to first (ALL function types share the same
267   //  // back-ref map.
268   //  using F = void(*)(int*);
269   //  F G(int *);
270   BackrefContext Backrefs;
271 };
272
273 } // namespace ms_demangle
274 } // namespace llvm
275
276 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H