[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / include / llvm / Demangle / MicrosoftDemangle.h
blob382e79401c437b0a64700cdc7cced2c7c3eb8b60
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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
10 #define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H
12 #include "llvm/Demangle/DemangleConfig.h"
13 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
14 #include "llvm/Demangle/StringView.h"
15 #include "llvm/Demangle/Utility.h"
17 #include <utility>
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;
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;
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;
45 public:
46 ArenaAllocator() { addNode(AllocUnit); }
48 ~ArenaAllocator() {
49 while (Head) {
50 assert(Head->Buf);
51 delete[] Head->Buf;
52 AllocatorNode *Next = Head->Next;
53 delete Head;
54 Head = Next;
58 char *allocUnalignedBuffer(size_t Size) {
59 assert(Head && Head->Buf);
61 uint8_t *P = Head->Buf + Head->Used;
63 Head->Used += Size;
64 if (Head->Used <= Head->Capacity)
65 return reinterpret_cast<char *>(P);
67 addNode(std::max(AllocUnit, Size));
68 Head->Used = Size;
69 return reinterpret_cast<char *>(Head->Buf);
72 template <typename T, typename... Args> T *allocArray(size_t Count) {
73 size_t Size = Count * sizeof(T);
74 assert(Head && Head->Buf);
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;
82 Head->Used += Size + Adjustment;
83 if (Head->Used <= Head->Capacity)
84 return new (PP) T[Count]();
86 addNode(std::max(AllocUnit, Size));
87 Head->Used = Size;
88 return new (Head->Buf) T[Count]();
91 template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
92 constexpr size_t Size = sizeof(T);
93 assert(Head && Head->Buf);
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;
101 Head->Used += Size + Adjustment;
102 if (Head->Used <= Head->Capacity)
103 return new (PP) T(std::forward<Args>(ConstructorArgs)...);
105 static_assert(Size < AllocUnit, "");
106 addNode(AllocUnit);
107 Head->Used = Size;
108 return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
111 private:
112 AllocatorNode *Head = nullptr;
115 struct BackrefContext {
116 static constexpr size_t Max = 10;
118 TypeNode *FunctionParams[Max];
119 size_t FunctionParamCount = 0;
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;
127 enum class QualifierMangleMode { Drop, Mangle, Result };
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.
135 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
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;
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);
149 TagTypeNode *parseTagUniqueName(StringView &MangledName);
151 // True if an error occurred.
152 bool Error = false;
154 void dumpBackReferences();
156 private:
157 SymbolNode *demangleEncodedSymbol(StringView &MangledName,
158 QualifiedNameNode *QN);
159 SymbolNode *demangleDeclarator(StringView &MangledName);
160 SymbolNode *demangleMD5Name(StringView &MangledName);
162 VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
163 StorageClass SC);
164 FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
166 Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
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);
178 ArrayTypeNode *demangleArrayType(StringView &MangledName);
180 NodeArrayNode *demangleFunctionParameterList(StringView &MangledName,
181 bool &IsVariadic);
182 NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
184 std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
185 uint64_t demangleUnsigned(StringView &MangledName);
186 int64_t demangleSigned(StringView &MangledName);
188 void memorizeString(StringView s);
189 void memorizeIdentifier(IdentifierNode *Identifier);
191 /// Allocate a copy of \p Borrowed into memory that we own.
192 StringView copyString(StringView Borrowed);
194 QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
195 QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
197 IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
198 bool Memorize);
199 IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
200 NameBackrefBehavior NBB);
202 QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
203 IdentifierNode *UnqualifiedName);
204 IdentifierNode *demangleNameScopePiece(StringView &MangledName);
206 NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
207 IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
208 NameBackrefBehavior NBB);
209 IntrinsicFunctionKind
210 translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
211 IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
212 IdentifierNode *
213 demangleFunctionIdentifierCode(StringView &MangledName,
214 FunctionIdentifierCodeGroup Group);
215 StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
216 bool IsDestructor);
217 ConversionOperatorIdentifierNode *
218 demangleConversionOperatorIdentifier(StringView &MangledName);
219 LiteralOperatorIdentifierNode *
220 demangleLiteralOperatorIdentifier(StringView &MangledName);
222 SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
223 SpecialTableSymbolNode *
224 demangleSpecialTableSymbolNode(StringView &MangledName,
225 SpecialIntrinsicKind SIK);
226 LocalStaticGuardVariableNode *
227 demangleLocalStaticGuard(StringView &MangledName, bool IsThread);
228 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
229 StringView &MangledName,
230 StringView VariableName);
231 VariableSymbolNode *
232 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
233 StringView &MangledName);
234 FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
235 bool IsDestructor);
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);
244 StringView demangleSimpleString(StringView &MangledName, bool Memorize);
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);
253 std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
255 // Memory allocator.
256 ArenaAllocator Arena;
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:
261 // // Second int* is a back-ref to first.
262 // void foo(int *, int*);
264 // // Second int* is not a back-ref to first (first is not a function param).
265 // int* foo(int*);
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;
274 } // namespace ms_demangle
275 } // namespace llvm
277 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H