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
);
162 VariableSymbolNode
*demangleVariableEncoding(StringView
&MangledName
,
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
,
178 ArrayTypeNode
*demangleArrayType(StringView
&MangledName
);
180 NodeArrayNode
*demangleFunctionParameterList(StringView
&MangledName
,
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
,
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
);
213 demangleFunctionIdentifierCode(StringView
&MangledName
,
214 FunctionIdentifierCodeGroup Group
);
215 StructorIdentifierNode
*demangleStructorIdentifier(StringView
&MangledName
,
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
);
232 demangleRttiBaseClassDescriptorNode(ArenaAllocator
&Arena
,
233 StringView
&MangledName
);
234 FunctionSymbolNode
*demangleInitFiniStub(StringView
&MangledName
,
237 NamedIdentifierNode
*demangleSimpleName(StringView
&MangledName
,
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
);
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).
267 // // Second int* is a back-ref to first (ALL function types share the same
269 // using F = void(*)(int*);
271 BackrefContext Backrefs
;
274 } // namespace ms_demangle
277 #endif // LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H