LLVM  10.0.0svn
MicrosoftDemangle.h
Go to the documentation of this file.
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_MICROSOFT_DEMANGLE_H
10 #define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
11 
15 #include "llvm/Demangle/Utility.h"
16 
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 
29  struct AllocatorNode {
30  uint8_t *Buf = nullptr;
31  size_t Used = 0;
32  size_t Capacity = 0;
33  AllocatorNode *Next = nullptr;
34  };
35 
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:
46  ArenaAllocator() { addNode(AllocUnit); }
47 
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  char *allocUnalignedBuffer(size_t Size) {
59  assert(Head && Head->Buf);
60 
61  uint8_t *P = Head->Buf + Head->Used;
62 
63  Head->Used += Size;
64  if (Head->Used <= Head->Capacity)
65  return reinterpret_cast<char *>(P);
66 
67  addNode(std::max(AllocUnit, Size));
68  Head->Used = Size;
69  return reinterpret_cast<char *>(Head->Buf);
70  }
71 
72  template <typename T, typename... Args> T *allocArray(size_t Count) {
73  size_t Size = Count * sizeof(T);
74  assert(Head && Head->Buf);
75 
76  size_t P = (size_t)Head->Buf + Head->Used;
77  uintptr_t AlignedP =
78  (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
79  uint8_t *PP = (uint8_t *)AlignedP;
80  size_t Adjustment = AlignedP - P;
81 
82  Head->Used += Size + Adjustment;
83  if (Head->Used <= Head->Capacity)
84  return new (PP) T[Count]();
85 
86  addNode(std::max(AllocUnit, Size));
87  Head->Used = Size;
88  return new (Head->Buf) T[Count]();
89  }
90 
91  template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
92  constexpr size_t Size = sizeof(T);
93  assert(Head && Head->Buf);
94 
95  size_t P = (size_t)Head->Buf + Head->Used;
96  uintptr_t AlignedP =
97  (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
98  uint8_t *PP = (uint8_t *)AlignedP;
99  size_t Adjustment = AlignedP - P;
100 
101  Head->Used += Size + Adjustment;
102  if (Head->Used <= Head->Capacity)
103  return new (PP) T(std::forward<Args>(ConstructorArgs)...);
104 
105  static_assert(Size < AllocUnit, "");
106  addNode(AllocUnit);
107  Head->Used = Size;
108  return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
109  }
110 
111 private:
112  AllocatorNode *Head = nullptr;
113 };
114 
116  static constexpr size_t Max = 10;
117 
118  TypeNode *FunctionParams[Max];
119  size_t FunctionParamCount = 0;
120 
121  // The first 10 BackReferences in a mangled name can be back-referenced by
122  // special name @[0-9]. This is a storage for the first 10 BackReferences.
123  NamedIdentifierNode *Names[Max];
124  size_t NamesCount = 0;
125 };
126 
128 
129 enum NameBackrefBehavior : uint8_t {
130  NBB_None = 0, // don't save any names as backrefs.
131  NBB_Template = 1 << 0, // save template instanations.
132  NBB_Simple = 1 << 1, // save simple names.
133 };
134 
136 
137 // Demangler class takes the main role in demangling symbols.
138 // It has a set of functions to parse mangled symbols into Type instances.
139 // It also has a set of functions to convert Type instances to strings.
140 class Demangler {
141 public:
142  Demangler() = default;
143  virtual ~Demangler() = default;
144 
145  // You are supposed to call parse() first and then check if error is true. If
146  // it is false, call output() to write the formatted name to the given stream.
147  SymbolNode *parse(StringView &MangledName);
148 
149  TagTypeNode *parseTagUniqueName(StringView &MangledName);
150 
151  // True if an error occurred.
152  bool Error = false;
153 
154  void dumpBackReferences();
155 
156 private:
157  SymbolNode *demangleEncodedSymbol(StringView &MangledName,
158  QualifiedNameNode *QN);
159  SymbolNode *demangleDeclarator(StringView &MangledName);
160  SymbolNode *demangleMD5Name(StringView &MangledName);
161 
162  VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
163  StorageClass SC);
164  FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
165 
166  Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
167 
168  // Parser functions. This is a recursive-descent parser.
169  TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
170  PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
171  CustomTypeNode *demangleCustomType(StringView &MangledName);
172  TagTypeNode *demangleClassType(StringView &MangledName);
173  PointerTypeNode *demanglePointerType(StringView &MangledName);
174  PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
175  FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
176  bool HasThisQuals);
177 
178  ArrayTypeNode *demangleArrayType(StringView &MangledName);
179 
180  NodeArrayNode *demangleFunctionParameterList(StringView &MangledName,
181  bool &IsVariadic);
182  NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
183 
184  std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
185  uint64_t demangleUnsigned(StringView &MangledName);
186  int64_t demangleSigned(StringView &MangledName);
187 
188  void memorizeString(StringView s);
189  void memorizeIdentifier(IdentifierNode *Identifier);
190 
191  /// Allocate a copy of \p Borrowed into memory that we own.
192  StringView copyString(StringView Borrowed);
193 
194  QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
195  QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
196 
197  IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
198  bool Memorize);
199  IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
200  NameBackrefBehavior NBB);
201 
202  QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
203  IdentifierNode *UnqualifiedName);
204  IdentifierNode *demangleNameScopePiece(StringView &MangledName);
205 
206  NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
207  IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
208  NameBackrefBehavior NBB);
210  translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
211  IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
213  demangleFunctionIdentifierCode(StringView &MangledName,
215  StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
216  bool IsDestructor);
218  demangleConversionOperatorIdentifier(StringView &MangledName);
220  demangleLiteralOperatorIdentifier(StringView &MangledName);
221 
222  SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
224  demangleSpecialTableSymbolNode(StringView &MangledName,
227  demangleLocalStaticGuard(StringView &MangledName, bool IsThread);
228  VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
229  StringView &MangledName,
230  StringView VariableName);
232  demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
233  StringView &MangledName);
234  FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
235  bool IsDestructor);
236 
237  NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
238  bool Memorize);
239  NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
240  NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
241  EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
242  FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
243 
244  StringView demangleSimpleString(StringView &MangledName, bool Memorize);
245 
246  FuncClass demangleFunctionClass(StringView &MangledName);
247  CallingConv demangleCallingConvention(StringView &MangledName);
248  StorageClass demangleVariableStorageClass(StringView &MangledName);
249  bool demangleThrowSpecification(StringView &MangledName);
250  wchar_t demangleWcharLiteral(StringView &MangledName);
251  uint8_t demangleCharLiteral(StringView &MangledName);
252 
253  std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
254 
255  // Memory allocator.
256  ArenaAllocator Arena;
257 
258  // A single type uses one global back-ref table for all function params.
259  // This means back-refs can even go "into" other types. Examples:
260  //
261  // // Second int* is a back-ref to first.
262  // void foo(int *, int*);
263  //
264  // // Second int* is not a back-ref to first (first is not a function param).
265  // int* foo(int*);
266  //
267  // // Second int* is a back-ref to first (ALL function types share the same
268  // // back-ref map.
269  // using F = void(*)(int*);
270  // F G(int *);
271  BackrefContext Backrefs;
272 };
273 
274 } // namespace ms_demangle
275 } // namespace llvm
276 
277 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
char * allocUnalignedBuffer(size_t Size)
constexpr size_t AllocUnit
T * alloc(Args &&... ConstructorArgs)
#define P(N)
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
CHAIN = SC CHAIN, Imm128 - System call.
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition: LineTable.cpp:54
constexpr char Args[]
Key for Kernel::Metadata::mArgs.