xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Demangle/MicrosoftDemangle.h (revision 415efcecd8b80f68e76376ef2b854cb6f5c84b5a)
1 //===------------------------- MicrosoftDemangle.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 #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
10 #define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
11 
12 #include "llvm/Demangle/Demangle.h"
13 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
14 
15 #include <cassert>
16 #include <string_view>
17 #include <utility>
18 
19 namespace llvm {
20 namespace ms_demangle {
21 // This memory allocator is extremely fast, but it doesn't call dtors
22 // for allocated objects. That means you can't use STL containers
23 // (such as std::vector) with this allocator. But it pays off --
24 // the demangler is 3x faster with this allocator compared to one with
25 // STL containers.
26 constexpr size_t AllocUnit = 4096;
27 
28 class ArenaAllocator {
29   struct AllocatorNode {
30     uint8_t *Buf = nullptr;
31     size_t Used = 0;
32     size_t Capacity = 0;
33     AllocatorNode *Next = nullptr;
34   };
35 
addNode(size_t Capacity)36   void addNode(size_t Capacity) {
37     AllocatorNode *NewHead = new AllocatorNode;
38     NewHead->Buf = new uint8_t[Capacity];
39     NewHead->Next = Head;
40     NewHead->Capacity = Capacity;
41     Head = NewHead;
42     NewHead->Used = 0;
43   }
44 
45 public:
ArenaAllocator()46   ArenaAllocator() { addNode(AllocUnit); }
47 
~ArenaAllocator()48   ~ArenaAllocator() {
49     while (Head) {
50       assert(Head->Buf);
51       delete[] Head->Buf;
52       AllocatorNode *Next = Head->Next;
53       delete Head;
54       Head = Next;
55     }
56   }
57 
58   // Delete the copy constructor and the copy assignment operator.
59   ArenaAllocator(const ArenaAllocator &) = delete;
60   ArenaAllocator &operator=(const ArenaAllocator &) = delete;
61 
allocUnalignedBuffer(size_t Size)62   char *allocUnalignedBuffer(size_t Size) {
63     assert(Head && Head->Buf);
64 
65     uint8_t *P = Head->Buf + Head->Used;
66 
67     Head->Used += Size;
68     if (Head->Used <= Head->Capacity)
69       return reinterpret_cast<char *>(P);
70 
71     addNode(std::max(AllocUnit, Size));
72     Head->Used = Size;
73     return reinterpret_cast<char *>(Head->Buf);
74   }
75 
allocArray(size_t Count)76   template <typename T, typename... Args> T *allocArray(size_t Count) {
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(std::max(AllocUnit, Size));
91     Head->Used = Size;
92     return new (Head->Buf) T[Count]();
93   }
94 
alloc(Args &&...ConstructorArgs)95   template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
96     constexpr size_t Size = sizeof(T);
97     assert(Head && Head->Buf);
98 
99     size_t P = (size_t)Head->Buf + Head->Used;
100     uintptr_t AlignedP =
101         (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
102     uint8_t *PP = (uint8_t *)AlignedP;
103     size_t Adjustment = AlignedP - P;
104 
105     Head->Used += Size + Adjustment;
106     if (Head->Used <= Head->Capacity)
107       return new (PP) T(std::forward<Args>(ConstructorArgs)...);
108 
109     static_assert(Size < AllocUnit);
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   friend std::optional<size_t>
146   llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName);
147 
148 public:
149   Demangler() = default;
150   virtual ~Demangler() = default;
151 
152   // You are supposed to call parse() first and then check if error is true.  If
153   // it is false, call output() to write the formatted name to the given stream.
154   SymbolNode *parse(std::string_view &MangledName);
155 
156   TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
157 
158   // True if an error occurred.
159   bool Error = false;
160 
161   void dumpBackReferences();
162 
163 private:
164   SymbolNode *demangleEncodedSymbol(std::string_view &MangledName,
165                                     QualifiedNameNode *QN);
166   SymbolNode *demangleDeclarator(std::string_view &MangledName);
167   SymbolNode *demangleMD5Name(std::string_view &MangledName);
168   SymbolNode *demangleTypeinfoName(std::string_view &MangledName);
169 
170   VariableSymbolNode *demangleVariableEncoding(std::string_view &MangledName,
171                                                StorageClass SC);
172   FunctionSymbolNode *demangleFunctionEncoding(std::string_view &MangledName);
173 
174   Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName);
175 
176   // Parser functions. This is a recursive-descent parser.
177   TypeNode *demangleType(std::string_view &MangledName,
178                          QualifierMangleMode QMM);
179   PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName);
180   CustomTypeNode *demangleCustomType(std::string_view &MangledName);
181   TagTypeNode *demangleClassType(std::string_view &MangledName);
182   PointerTypeNode *demanglePointerType(std::string_view &MangledName);
183   PointerTypeNode *demangleMemberPointerType(std::string_view &MangledName);
184   FunctionSignatureNode *demangleFunctionType(std::string_view &MangledName,
185                                               bool HasThisQuals);
186 
187   ArrayTypeNode *demangleArrayType(std::string_view &MangledName);
188 
189   NodeArrayNode *demangleFunctionParameterList(std::string_view &MangledName,
190                                                bool &IsVariadic);
191   NodeArrayNode *demangleTemplateParameterList(std::string_view &MangledName);
192 
193   std::pair<uint64_t, bool> demangleNumber(std::string_view &MangledName);
194   uint64_t demangleUnsigned(std::string_view &MangledName);
195   int64_t demangleSigned(std::string_view &MangledName);
196 
197   void memorizeString(std::string_view s);
198   void memorizeIdentifier(IdentifierNode *Identifier);
199 
200   /// Allocate a copy of \p Borrowed into memory that we own.
201   std::string_view copyString(std::string_view Borrowed);
202 
203   QualifiedNameNode *
204   demangleFullyQualifiedTypeName(std::string_view &MangledName);
205   QualifiedNameNode *
206   demangleFullyQualifiedSymbolName(std::string_view &MangledName);
207 
208   IdentifierNode *demangleUnqualifiedTypeName(std::string_view &MangledName,
209                                               bool Memorize);
210   IdentifierNode *demangleUnqualifiedSymbolName(std::string_view &MangledName,
211                                                 NameBackrefBehavior NBB);
212 
213   QualifiedNameNode *demangleNameScopeChain(std::string_view &MangledName,
214                                             IdentifierNode *UnqualifiedName);
215   IdentifierNode *demangleNameScopePiece(std::string_view &MangledName);
216 
217   NamedIdentifierNode *demangleBackRefName(std::string_view &MangledName);
218   IdentifierNode *
219   demangleTemplateInstantiationName(std::string_view &MangledName,
220                                     NameBackrefBehavior NBB);
221   IntrinsicFunctionKind
222   translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
223   IdentifierNode *demangleFunctionIdentifierCode(std::string_view &MangledName);
224   IdentifierNode *
225   demangleFunctionIdentifierCode(std::string_view &MangledName,
226                                  FunctionIdentifierCodeGroup Group);
227   StructorIdentifierNode *
228   demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor);
229   ConversionOperatorIdentifierNode *
230   demangleConversionOperatorIdentifier(std::string_view &MangledName);
231   LiteralOperatorIdentifierNode *
232   demangleLiteralOperatorIdentifier(std::string_view &MangledName);
233 
234   SymbolNode *demangleSpecialIntrinsic(std::string_view &MangledName);
235   SpecialTableSymbolNode *
236   demangleSpecialTableSymbolNode(std::string_view &MangledName,
237                                  SpecialIntrinsicKind SIK);
238   LocalStaticGuardVariableNode *
239   demangleLocalStaticGuard(std::string_view &MangledName, bool IsThread);
240   VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
241                                               std::string_view &MangledName,
242                                               std::string_view VariableName);
243   VariableSymbolNode *
244   demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
245                                       std::string_view &MangledName);
246   FunctionSymbolNode *demangleInitFiniStub(std::string_view &MangledName,
247                                            bool IsDestructor);
248 
249   NamedIdentifierNode *demangleSimpleName(std::string_view &MangledName,
250                                           bool Memorize);
251   NamedIdentifierNode *
252   demangleAnonymousNamespaceName(std::string_view &MangledName);
253   NamedIdentifierNode *
254   demangleLocallyScopedNamePiece(std::string_view &MangledName);
255   EncodedStringLiteralNode *
256   demangleStringLiteral(std::string_view &MangledName);
257   FunctionSymbolNode *demangleVcallThunkNode(std::string_view &MangledName);
258 
259   std::string_view demangleSimpleString(std::string_view &MangledName,
260                                         bool Memorize);
261 
262   FuncClass demangleFunctionClass(std::string_view &MangledName);
263   CallingConv demangleCallingConvention(std::string_view &MangledName);
264   StorageClass demangleVariableStorageClass(std::string_view &MangledName);
265   bool demangleThrowSpecification(std::string_view &MangledName);
266   wchar_t demangleWcharLiteral(std::string_view &MangledName);
267   uint8_t demangleCharLiteral(std::string_view &MangledName);
268 
269   std::pair<Qualifiers, bool> demangleQualifiers(std::string_view &MangledName);
270 
271   // Memory allocator.
272   ArenaAllocator Arena;
273 
274   // A single type uses one global back-ref table for all function params.
275   // This means back-refs can even go "into" other types.  Examples:
276   //
277   //  // Second int* is a back-ref to first.
278   //  void foo(int *, int*);
279   //
280   //  // Second int* is not a back-ref to first (first is not a function param).
281   //  int* foo(int*);
282   //
283   //  // Second int* is a back-ref to first (ALL function types share the same
284   //  // back-ref map.
285   //  using F = void(*)(int*);
286   //  F G(int *);
287   BackrefContext Backrefs;
288 };
289 
290 } // namespace ms_demangle
291 } // namespace llvm
292 
293 #endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
294