LLVM  8.0.1
MicrosoftDemangle.h
Go to the documentation of this file.
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"
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 
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 
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 
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 
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 
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);
212  demangleFunctionIdentifierCode(StringView &MangledName,
214  StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
215  bool IsDestructor);
217  demangleConversionOperatorIdentifier(StringView &MangledName);
219  demangleLiteralOperatorIdentifier(StringView &MangledName);
220 
221  SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
223  demangleSpecialTableSymbolNode(StringView &MangledName,
226  demangleLocalStaticGuard(StringView &MangledName);
227  VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
228  StringView &MangledName,
229  StringView VariableName);
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
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:24
constexpr size_t AllocUnit
#define T
T * alloc(Args &&... ConstructorArgs)
#define P(N)
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition: JSON.cpp:511
CHAIN = SC CHAIN, Imm128 - System call.
char * allocUnalignedBuffer(size_t Length)
uint32_t Size
Definition: Profile.cpp:47
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
constexpr char Args[]
Key for Kernel::Metadata::mArgs.