1 //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
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
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"
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
26 constexpr size_t AllocUnit
= 4096;
28 class ArenaAllocator
{
29 struct AllocatorNode
{
30 uint8_t *Buf
= nullptr;
33 AllocatorNode
*Next
= nullptr;
36 void addNode(size_t Capacity
) {
37 AllocatorNode
*NewHead
= new AllocatorNode
;
38 NewHead
->Buf
= new uint8_t[Capacity
];
40 NewHead
->Capacity
= Capacity
;
46 ArenaAllocator() { addNode(AllocUnit
); }
52 AllocatorNode
*Next
= Head
->Next
;
58 char *allocUnalignedBuffer(size_t Size
) {
59 assert(Head
&& Head
->Buf
);
61 uint8_t *P
= Head
->Buf
+ Head
->Used
;
64 if (Head
->Used
<= Head
->Capacity
)
65 return reinterpret_cast<char *>(P
);
67 addNode(std::max(AllocUnit
, 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
;
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
));
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
;
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
, "");
108 return new (Head
->Buf
) T(std::forward
<Args
>(ConstructorArgs
)...);
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.
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.
154 void dumpBackReferences();
157 SymbolNode
*demangleEncodedSymbol(StringView
&MangledName
,
158 QualifiedNameNode
*QN
);
159 SymbolNode
*demangleDeclarator(StringView
&MangledName
);
160 SymbolNode
*demangleMD5Name(StringView
&MangledName
);
161 SymbolNode
*demangleTypeinfoName(StringView
&MangledName
);
163 VariableSymbolNode
*demangleVariableEncoding(StringView
&MangledName
,
165 FunctionSymbolNode
*demangleFunctionEncoding(StringView
&MangledName
);
167 Qualifiers
demanglePointerExtQualifiers(StringView
&MangledName
);
169 // Parser functions. This is a recursive-descent parser.
170 TypeNode
*demangleType(StringView
&MangledName
, QualifierMangleMode QMM
);
171 PrimitiveTypeNode
*demanglePrimitiveType(StringView
&MangledName
);
172 CustomTypeNode
*demangleCustomType(StringView
&MangledName
);
173 TagTypeNode
*demangleClassType(StringView
&MangledName
);
174 PointerTypeNode
*demanglePointerType(StringView
&MangledName
);
175 PointerTypeNode
*demangleMemberPointerType(StringView
&MangledName
);
176 FunctionSignatureNode
*demangleFunctionType(StringView
&MangledName
,
179 ArrayTypeNode
*demangleArrayType(StringView
&MangledName
);
181 NodeArrayNode
*demangleFunctionParameterList(StringView
&MangledName
,
183 NodeArrayNode
*demangleTemplateParameterList(StringView
&MangledName
);
185 std::pair
<uint64_t, bool> demangleNumber(StringView
&MangledName
);
186 uint64_t demangleUnsigned(StringView
&MangledName
);
187 int64_t demangleSigned(StringView
&MangledName
);
189 void memorizeString(StringView s
);
190 void memorizeIdentifier(IdentifierNode
*Identifier
);
192 /// Allocate a copy of \p Borrowed into memory that we own.
193 StringView
copyString(StringView Borrowed
);
195 QualifiedNameNode
*demangleFullyQualifiedTypeName(StringView
&MangledName
);
196 QualifiedNameNode
*demangleFullyQualifiedSymbolName(StringView
&MangledName
);
198 IdentifierNode
*demangleUnqualifiedTypeName(StringView
&MangledName
,
200 IdentifierNode
*demangleUnqualifiedSymbolName(StringView
&MangledName
,
201 NameBackrefBehavior NBB
);
203 QualifiedNameNode
*demangleNameScopeChain(StringView
&MangledName
,
204 IdentifierNode
*UnqualifiedName
);
205 IdentifierNode
*demangleNameScopePiece(StringView
&MangledName
);
207 NamedIdentifierNode
*demangleBackRefName(StringView
&MangledName
);
208 IdentifierNode
*demangleTemplateInstantiationName(StringView
&MangledName
,
209 NameBackrefBehavior NBB
);
210 IntrinsicFunctionKind
211 translateIntrinsicFunctionCode(char CH
, FunctionIdentifierCodeGroup Group
);
212 IdentifierNode
*demangleFunctionIdentifierCode(StringView
&MangledName
);
214 demangleFunctionIdentifierCode(StringView
&MangledName
,
215 FunctionIdentifierCodeGroup Group
);
216 StructorIdentifierNode
*demangleStructorIdentifier(StringView
&MangledName
,
218 ConversionOperatorIdentifierNode
*
219 demangleConversionOperatorIdentifier(StringView
&MangledName
);
220 LiteralOperatorIdentifierNode
*
221 demangleLiteralOperatorIdentifier(StringView
&MangledName
);
223 SymbolNode
*demangleSpecialIntrinsic(StringView
&MangledName
);
224 SpecialTableSymbolNode
*
225 demangleSpecialTableSymbolNode(StringView
&MangledName
,
226 SpecialIntrinsicKind SIK
);
227 LocalStaticGuardVariableNode
*
228 demangleLocalStaticGuard(StringView
&MangledName
, bool IsThread
);
229 VariableSymbolNode
*demangleUntypedVariable(ArenaAllocator
&Arena
,
230 StringView
&MangledName
,
231 StringView VariableName
);
233 demangleRttiBaseClassDescriptorNode(ArenaAllocator
&Arena
,
234 StringView
&MangledName
);
235 FunctionSymbolNode
*demangleInitFiniStub(StringView
&MangledName
,
238 NamedIdentifierNode
*demangleSimpleName(StringView
&MangledName
,
240 NamedIdentifierNode
*demangleAnonymousNamespaceName(StringView
&MangledName
);
241 NamedIdentifierNode
*demangleLocallyScopedNamePiece(StringView
&MangledName
);
242 EncodedStringLiteralNode
*demangleStringLiteral(StringView
&MangledName
);
243 FunctionSymbolNode
*demangleVcallThunkNode(StringView
&MangledName
);
245 StringView
demangleSimpleString(StringView
&MangledName
, bool Memorize
);
247 FuncClass
demangleFunctionClass(StringView
&MangledName
);
248 CallingConv
demangleCallingConvention(StringView
&MangledName
);
249 StorageClass
demangleVariableStorageClass(StringView
&MangledName
);
250 bool demangleThrowSpecification(StringView
&MangledName
);
251 wchar_t demangleWcharLiteral(StringView
&MangledName
);
252 uint8_t demangleCharLiteral(StringView
&MangledName
);
254 std::pair
<Qualifiers
, bool> demangleQualifiers(StringView
&MangledName
);
257 ArenaAllocator Arena
;
259 // A single type uses one global back-ref table for all function params.
260 // This means back-refs can even go "into" other types. Examples:
262 // // Second int* is a back-ref to first.
263 // void foo(int *, int*);
265 // // Second int* is not a back-ref to first (first is not a function param).
268 // // Second int* is a back-ref to first (ALL function types share the same
270 // using F = void(*)(int*);
272 BackrefContext Backrefs
;
275 } // namespace ms_demangle
278 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H