xref: /openbsd-src/gnu/llvm/llvm/lib/Demangle/DLangDemangle.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
1*d415bd75Srobert //===--- DLangDemangle.cpp ------------------------------------------------===//
2*d415bd75Srobert //
3*d415bd75Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d415bd75Srobert // See https://llvm.org/LICENSE.txt for license information.
5*d415bd75Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d415bd75Srobert //
7*d415bd75Srobert //===----------------------------------------------------------------------===//
8*d415bd75Srobert ///
9*d415bd75Srobert /// \file
10*d415bd75Srobert /// This file defines a demangler for the D programming language as specified
11*d415bd75Srobert /// in the ABI specification, available at:
12*d415bd75Srobert /// https://dlang.org/spec/abi.html#name_mangling
13*d415bd75Srobert ///
14*d415bd75Srobert //===----------------------------------------------------------------------===//
15*d415bd75Srobert 
16*d415bd75Srobert #include "llvm/Demangle/Demangle.h"
17*d415bd75Srobert #include "llvm/Demangle/StringView.h"
18*d415bd75Srobert #include "llvm/Demangle/Utility.h"
19*d415bd75Srobert 
20*d415bd75Srobert #include <cctype>
21*d415bd75Srobert #include <cstring>
22*d415bd75Srobert #include <limits>
23*d415bd75Srobert 
24*d415bd75Srobert using namespace llvm;
25*d415bd75Srobert using llvm::itanium_demangle::OutputBuffer;
26*d415bd75Srobert using llvm::itanium_demangle::StringView;
27*d415bd75Srobert 
28*d415bd75Srobert namespace {
29*d415bd75Srobert 
30*d415bd75Srobert /// Demangle information structure.
31*d415bd75Srobert struct Demangler {
32*d415bd75Srobert   /// Initialize the information structure we use to pass around information.
33*d415bd75Srobert   ///
34*d415bd75Srobert   /// \param Mangled String to demangle.
35*d415bd75Srobert   Demangler(const char *Mangled);
36*d415bd75Srobert 
37*d415bd75Srobert   /// Extract and demangle the mangled symbol and append it to the output
38*d415bd75Srobert   /// string.
39*d415bd75Srobert   ///
40*d415bd75Srobert   /// \param Demangled Output buffer to write the demangled name.
41*d415bd75Srobert   ///
42*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
43*d415bd75Srobert   ///
44*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#name_mangling .
45*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#MangledName .
46*d415bd75Srobert   const char *parseMangle(OutputBuffer *Demangled);
47*d415bd75Srobert 
48*d415bd75Srobert private:
49*d415bd75Srobert   /// Extract and demangle a given mangled symbol and append it to the output
50*d415bd75Srobert   /// string.
51*d415bd75Srobert   ///
52*d415bd75Srobert   /// \param Demangled output buffer to write the demangled name.
53*d415bd75Srobert   /// \param Mangled mangled symbol to be demangled.
54*d415bd75Srobert   ///
55*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
56*d415bd75Srobert   ///
57*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#name_mangling .
58*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#MangledName .
59*d415bd75Srobert   const char *parseMangle(OutputBuffer *Demangled, const char *Mangled);
60*d415bd75Srobert 
61*d415bd75Srobert   /// Extract the number from a given string.
62*d415bd75Srobert   ///
63*d415bd75Srobert   /// \param Mangled string to extract the number.
64*d415bd75Srobert   /// \param Ret assigned result value.
65*d415bd75Srobert   ///
66*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
67*d415bd75Srobert   ///
68*d415bd75Srobert   /// \note A result larger than UINT_MAX is considered a failure.
69*d415bd75Srobert   ///
70*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#Number .
71*d415bd75Srobert   const char *decodeNumber(const char *Mangled, unsigned long &Ret);
72*d415bd75Srobert 
73*d415bd75Srobert   /// Extract the back reference position from a given string.
74*d415bd75Srobert   ///
75*d415bd75Srobert   /// \param Mangled string to extract the back reference position.
76*d415bd75Srobert   /// \param Ret assigned result value.
77*d415bd75Srobert   ///
78*d415bd75Srobert   /// \return the remaining string on success or nullptr on failure.
79*d415bd75Srobert   ///
80*d415bd75Srobert   /// \note Ret is always >= 0 on success, and unspecified on failure
81*d415bd75Srobert   ///
82*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#back_ref .
83*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#NumberBackRef .
84*d415bd75Srobert   const char *decodeBackrefPos(const char *Mangled, long &Ret);
85*d415bd75Srobert 
86*d415bd75Srobert   /// Extract the symbol pointed by the back reference form a given string.
87*d415bd75Srobert   ///
88*d415bd75Srobert   /// \param Mangled string to extract the back reference position.
89*d415bd75Srobert   /// \param Ret assigned result value.
90*d415bd75Srobert   ///
91*d415bd75Srobert   /// \return the remaining string on success or nullptr on failure.
92*d415bd75Srobert   ///
93*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#back_ref .
94*d415bd75Srobert   const char *decodeBackref(const char *Mangled, const char *&Ret);
95*d415bd75Srobert 
96*d415bd75Srobert   /// Extract and demangle backreferenced symbol from a given mangled symbol
97*d415bd75Srobert   /// and append it to the output string.
98*d415bd75Srobert   ///
99*d415bd75Srobert   /// \param Demangled output buffer to write the demangled name.
100*d415bd75Srobert   /// \param Mangled mangled symbol to be demangled.
101*d415bd75Srobert   ///
102*d415bd75Srobert   /// \return the remaining string on success or nullptr on failure.
103*d415bd75Srobert   ///
104*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#back_ref .
105*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
106*d415bd75Srobert   const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
107*d415bd75Srobert 
108*d415bd75Srobert   /// Extract and demangle backreferenced type from a given mangled symbol
109*d415bd75Srobert   /// and append it to the output string.
110*d415bd75Srobert   ///
111*d415bd75Srobert   /// \param Mangled mangled symbol to be demangled.
112*d415bd75Srobert   ///
113*d415bd75Srobert   /// \return the remaining string on success or nullptr on failure.
114*d415bd75Srobert   ///
115*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#back_ref .
116*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#TypeBackRef .
117*d415bd75Srobert   const char *parseTypeBackref(const char *Mangled);
118*d415bd75Srobert 
119*d415bd75Srobert   /// Check whether it is the beginning of a symbol name.
120*d415bd75Srobert   ///
121*d415bd75Srobert   /// \param Mangled string to extract the symbol name.
122*d415bd75Srobert   ///
123*d415bd75Srobert   /// \return true on success, false otherwise.
124*d415bd75Srobert   ///
125*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#SymbolName .
126*d415bd75Srobert   bool isSymbolName(const char *Mangled);
127*d415bd75Srobert 
128*d415bd75Srobert   /// Extract and demangle an identifier from a given mangled symbol append it
129*d415bd75Srobert   /// to the output string.
130*d415bd75Srobert   ///
131*d415bd75Srobert   /// \param Demangled Output buffer to write the demangled name.
132*d415bd75Srobert   /// \param Mangled Mangled symbol to be demangled.
133*d415bd75Srobert   ///
134*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
135*d415bd75Srobert   ///
136*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#SymbolName .
137*d415bd75Srobert   const char *parseIdentifier(OutputBuffer *Demangled, const char *Mangled);
138*d415bd75Srobert 
139*d415bd75Srobert   /// Extract and demangle the plain identifier from a given mangled symbol and
140*d415bd75Srobert   /// prepend/append it to the output string, with a special treatment for some
141*d415bd75Srobert   /// magic compiler generated symbols.
142*d415bd75Srobert   ///
143*d415bd75Srobert   /// \param Demangled Output buffer to write the demangled name.
144*d415bd75Srobert   /// \param Mangled Mangled symbol to be demangled.
145*d415bd75Srobert   /// \param Len Length of the mangled symbol name.
146*d415bd75Srobert   ///
147*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
148*d415bd75Srobert   ///
149*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#LName .
150*d415bd75Srobert   const char *parseLName(OutputBuffer *Demangled, const char *Mangled,
151*d415bd75Srobert                          unsigned long Len);
152*d415bd75Srobert 
153*d415bd75Srobert   /// Extract and demangle the qualified symbol from a given mangled symbol
154*d415bd75Srobert   /// append it to the output string.
155*d415bd75Srobert   ///
156*d415bd75Srobert   /// \param Demangled Output buffer to write the demangled name.
157*d415bd75Srobert   /// \param Mangled Mangled symbol to be demangled.
158*d415bd75Srobert   ///
159*d415bd75Srobert   /// \return The remaining string on success or nullptr on failure.
160*d415bd75Srobert   ///
161*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#QualifiedName .
162*d415bd75Srobert   const char *parseQualified(OutputBuffer *Demangled, const char *Mangled);
163*d415bd75Srobert 
164*d415bd75Srobert   /// Extract and demangle a type from a given mangled symbol append it to
165*d415bd75Srobert   /// the output string.
166*d415bd75Srobert   ///
167*d415bd75Srobert   /// \param Mangled mangled symbol to be demangled.
168*d415bd75Srobert   ///
169*d415bd75Srobert   /// \return the remaining string on success or nullptr on failure.
170*d415bd75Srobert   ///
171*d415bd75Srobert   /// \see https://dlang.org/spec/abi.html#Type .
172*d415bd75Srobert   const char *parseType(const char *Mangled);
173*d415bd75Srobert 
174*d415bd75Srobert   /// The string we are demangling.
175*d415bd75Srobert   const char *Str;
176*d415bd75Srobert   /// The index of the last back reference.
177*d415bd75Srobert   int LastBackref;
178*d415bd75Srobert };
179*d415bd75Srobert 
180*d415bd75Srobert } // namespace
181*d415bd75Srobert 
decodeNumber(const char * Mangled,unsigned long & Ret)182*d415bd75Srobert const char *Demangler::decodeNumber(const char *Mangled, unsigned long &Ret) {
183*d415bd75Srobert   // Return nullptr if trying to extract something that isn't a digit.
184*d415bd75Srobert   if (Mangled == nullptr || !std::isdigit(*Mangled))
185*d415bd75Srobert     return nullptr;
186*d415bd75Srobert 
187*d415bd75Srobert   unsigned long Val = 0;
188*d415bd75Srobert 
189*d415bd75Srobert   do {
190*d415bd75Srobert     unsigned long Digit = Mangled[0] - '0';
191*d415bd75Srobert 
192*d415bd75Srobert     // Check for overflow.
193*d415bd75Srobert     if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10)
194*d415bd75Srobert       return nullptr;
195*d415bd75Srobert 
196*d415bd75Srobert     Val = Val * 10 + Digit;
197*d415bd75Srobert     ++Mangled;
198*d415bd75Srobert   } while (std::isdigit(*Mangled));
199*d415bd75Srobert 
200*d415bd75Srobert   if (*Mangled == '\0')
201*d415bd75Srobert     return nullptr;
202*d415bd75Srobert 
203*d415bd75Srobert   Ret = Val;
204*d415bd75Srobert   return Mangled;
205*d415bd75Srobert }
206*d415bd75Srobert 
decodeBackrefPos(const char * Mangled,long & Ret)207*d415bd75Srobert const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) {
208*d415bd75Srobert   // Return nullptr if trying to extract something that isn't a digit
209*d415bd75Srobert   if (Mangled == nullptr || !std::isalpha(*Mangled))
210*d415bd75Srobert     return nullptr;
211*d415bd75Srobert 
212*d415bd75Srobert   // Any identifier or non-basic type that has been emitted to the mangled
213*d415bd75Srobert   // symbol before will not be emitted again, but is referenced by a special
214*d415bd75Srobert   // sequence encoding the relative position of the original occurrence in the
215*d415bd75Srobert   // mangled symbol name.
216*d415bd75Srobert   // Numbers in back references are encoded with base 26 by upper case letters
217*d415bd75Srobert   // A-Z for higher digits but lower case letters a-z for the last digit.
218*d415bd75Srobert   //    NumberBackRef:
219*d415bd75Srobert   //        [a-z]
220*d415bd75Srobert   //        [A-Z] NumberBackRef
221*d415bd75Srobert   //        ^
222*d415bd75Srobert   unsigned long Val = 0;
223*d415bd75Srobert 
224*d415bd75Srobert   while (std::isalpha(*Mangled)) {
225*d415bd75Srobert     // Check for overflow
226*d415bd75Srobert     if (Val > (std::numeric_limits<unsigned long>::max() - 25) / 26)
227*d415bd75Srobert       break;
228*d415bd75Srobert 
229*d415bd75Srobert     Val *= 26;
230*d415bd75Srobert 
231*d415bd75Srobert     if (Mangled[0] >= 'a' && Mangled[0] <= 'z') {
232*d415bd75Srobert       Val += Mangled[0] - 'a';
233*d415bd75Srobert       if ((long)Val <= 0)
234*d415bd75Srobert         break;
235*d415bd75Srobert       Ret = Val;
236*d415bd75Srobert       return Mangled + 1;
237*d415bd75Srobert     }
238*d415bd75Srobert 
239*d415bd75Srobert     Val += Mangled[0] - 'A';
240*d415bd75Srobert     ++Mangled;
241*d415bd75Srobert   }
242*d415bd75Srobert 
243*d415bd75Srobert   return nullptr;
244*d415bd75Srobert }
245*d415bd75Srobert 
decodeBackref(const char * Mangled,const char * & Ret)246*d415bd75Srobert const char *Demangler::decodeBackref(const char *Mangled, const char *&Ret) {
247*d415bd75Srobert   assert(Mangled != nullptr && *Mangled == 'Q' && "Invalid back reference!");
248*d415bd75Srobert   Ret = nullptr;
249*d415bd75Srobert 
250*d415bd75Srobert   // Position of 'Q'
251*d415bd75Srobert   const char *Qpos = Mangled;
252*d415bd75Srobert   long RefPos;
253*d415bd75Srobert   ++Mangled;
254*d415bd75Srobert 
255*d415bd75Srobert   Mangled = decodeBackrefPos(Mangled, RefPos);
256*d415bd75Srobert   if (Mangled == nullptr)
257*d415bd75Srobert     return nullptr;
258*d415bd75Srobert 
259*d415bd75Srobert   if (RefPos > Qpos - Str)
260*d415bd75Srobert     return nullptr;
261*d415bd75Srobert 
262*d415bd75Srobert   // Set the position of the back reference.
263*d415bd75Srobert   Ret = Qpos - RefPos;
264*d415bd75Srobert 
265*d415bd75Srobert   return Mangled;
266*d415bd75Srobert }
267*d415bd75Srobert 
parseSymbolBackref(OutputBuffer * Demangled,const char * Mangled)268*d415bd75Srobert const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
269*d415bd75Srobert                                           const char *Mangled) {
270*d415bd75Srobert   // An identifier back reference always points to a digit 0 to 9.
271*d415bd75Srobert   //    IdentifierBackRef:
272*d415bd75Srobert   //        Q NumberBackRef
273*d415bd75Srobert   //        ^
274*d415bd75Srobert   const char *Backref;
275*d415bd75Srobert   unsigned long Len;
276*d415bd75Srobert 
277*d415bd75Srobert   // Get position of the back reference
278*d415bd75Srobert   Mangled = decodeBackref(Mangled, Backref);
279*d415bd75Srobert 
280*d415bd75Srobert   // Must point to a simple identifier
281*d415bd75Srobert   Backref = decodeNumber(Backref, Len);
282*d415bd75Srobert   if (Backref == nullptr || strlen(Backref) < Len)
283*d415bd75Srobert     return nullptr;
284*d415bd75Srobert 
285*d415bd75Srobert   Backref = parseLName(Demangled, Backref, Len);
286*d415bd75Srobert   if (Backref == nullptr)
287*d415bd75Srobert     return nullptr;
288*d415bd75Srobert 
289*d415bd75Srobert   return Mangled;
290*d415bd75Srobert }
291*d415bd75Srobert 
parseTypeBackref(const char * Mangled)292*d415bd75Srobert const char *Demangler::parseTypeBackref(const char *Mangled) {
293*d415bd75Srobert   // A type back reference always points to a letter.
294*d415bd75Srobert   //    TypeBackRef:
295*d415bd75Srobert   //        Q NumberBackRef
296*d415bd75Srobert   //        ^
297*d415bd75Srobert   const char *Backref;
298*d415bd75Srobert 
299*d415bd75Srobert   // If we appear to be moving backwards through the mangle string, then
300*d415bd75Srobert   // bail as this may be a recursive back reference.
301*d415bd75Srobert   if (Mangled - Str >= LastBackref)
302*d415bd75Srobert     return nullptr;
303*d415bd75Srobert 
304*d415bd75Srobert   int SaveRefPos = LastBackref;
305*d415bd75Srobert   LastBackref = Mangled - Str;
306*d415bd75Srobert 
307*d415bd75Srobert   // Get position of the back reference.
308*d415bd75Srobert   Mangled = decodeBackref(Mangled, Backref);
309*d415bd75Srobert 
310*d415bd75Srobert   // Can't decode back reference.
311*d415bd75Srobert   if (Backref == nullptr)
312*d415bd75Srobert     return nullptr;
313*d415bd75Srobert 
314*d415bd75Srobert   // TODO: Add support for function type back references.
315*d415bd75Srobert   Backref = parseType(Backref);
316*d415bd75Srobert 
317*d415bd75Srobert   LastBackref = SaveRefPos;
318*d415bd75Srobert 
319*d415bd75Srobert   if (Backref == nullptr)
320*d415bd75Srobert     return nullptr;
321*d415bd75Srobert 
322*d415bd75Srobert   return Mangled;
323*d415bd75Srobert }
324*d415bd75Srobert 
isSymbolName(const char * Mangled)325*d415bd75Srobert bool Demangler::isSymbolName(const char *Mangled) {
326*d415bd75Srobert   long Ret;
327*d415bd75Srobert   const char *Qref = Mangled;
328*d415bd75Srobert 
329*d415bd75Srobert   if (std::isdigit(*Mangled))
330*d415bd75Srobert     return true;
331*d415bd75Srobert 
332*d415bd75Srobert   // TODO: Handle template instances.
333*d415bd75Srobert 
334*d415bd75Srobert   if (*Mangled != 'Q')
335*d415bd75Srobert     return false;
336*d415bd75Srobert 
337*d415bd75Srobert   Mangled = decodeBackrefPos(Mangled + 1, Ret);
338*d415bd75Srobert   if (Mangled == nullptr || Ret > Qref - Str)
339*d415bd75Srobert     return false;
340*d415bd75Srobert 
341*d415bd75Srobert   return std::isdigit(Qref[-Ret]);
342*d415bd75Srobert }
343*d415bd75Srobert 
parseMangle(OutputBuffer * Demangled,const char * Mangled)344*d415bd75Srobert const char *Demangler::parseMangle(OutputBuffer *Demangled,
345*d415bd75Srobert                                    const char *Mangled) {
346*d415bd75Srobert   // A D mangled symbol is comprised of both scope and type information.
347*d415bd75Srobert   //    MangleName:
348*d415bd75Srobert   //        _D QualifiedName Type
349*d415bd75Srobert   //        _D QualifiedName Z
350*d415bd75Srobert   //        ^
351*d415bd75Srobert   // The caller should have guaranteed that the start pointer is at the
352*d415bd75Srobert   // above location.
353*d415bd75Srobert   // Note that type is never a function type, but only the return type of
354*d415bd75Srobert   // a function or the type of a variable.
355*d415bd75Srobert   Mangled += 2;
356*d415bd75Srobert 
357*d415bd75Srobert   Mangled = parseQualified(Demangled, Mangled);
358*d415bd75Srobert 
359*d415bd75Srobert   if (Mangled != nullptr) {
360*d415bd75Srobert     // Artificial symbols end with 'Z' and have no type.
361*d415bd75Srobert     if (*Mangled == 'Z')
362*d415bd75Srobert       ++Mangled;
363*d415bd75Srobert     else {
364*d415bd75Srobert       Mangled = parseType(Mangled);
365*d415bd75Srobert     }
366*d415bd75Srobert   }
367*d415bd75Srobert 
368*d415bd75Srobert   return Mangled;
369*d415bd75Srobert }
370*d415bd75Srobert 
parseQualified(OutputBuffer * Demangled,const char * Mangled)371*d415bd75Srobert const char *Demangler::parseQualified(OutputBuffer *Demangled,
372*d415bd75Srobert                                       const char *Mangled) {
373*d415bd75Srobert   // Qualified names are identifiers separated by their encoded length.
374*d415bd75Srobert   // Nested functions also encode their argument types without specifying
375*d415bd75Srobert   // what they return.
376*d415bd75Srobert   //    QualifiedName:
377*d415bd75Srobert   //        SymbolFunctionName
378*d415bd75Srobert   //        SymbolFunctionName QualifiedName
379*d415bd75Srobert   //        ^
380*d415bd75Srobert   //    SymbolFunctionName:
381*d415bd75Srobert   //        SymbolName
382*d415bd75Srobert   //        SymbolName TypeFunctionNoReturn
383*d415bd75Srobert   //        SymbolName M TypeFunctionNoReturn
384*d415bd75Srobert   //        SymbolName M TypeModifiers TypeFunctionNoReturn
385*d415bd75Srobert   // The start pointer should be at the above location.
386*d415bd75Srobert 
387*d415bd75Srobert   // Whether it has more than one symbol
388*d415bd75Srobert   size_t NotFirst = false;
389*d415bd75Srobert   do {
390*d415bd75Srobert     // Skip over anonymous symbols.
391*d415bd75Srobert     if (*Mangled == '0') {
392*d415bd75Srobert       do
393*d415bd75Srobert         ++Mangled;
394*d415bd75Srobert       while (*Mangled == '0');
395*d415bd75Srobert 
396*d415bd75Srobert       continue;
397*d415bd75Srobert     }
398*d415bd75Srobert 
399*d415bd75Srobert     if (NotFirst)
400*d415bd75Srobert       *Demangled << '.';
401*d415bd75Srobert     NotFirst = true;
402*d415bd75Srobert 
403*d415bd75Srobert     Mangled = parseIdentifier(Demangled, Mangled);
404*d415bd75Srobert 
405*d415bd75Srobert   } while (Mangled && isSymbolName(Mangled));
406*d415bd75Srobert 
407*d415bd75Srobert   return Mangled;
408*d415bd75Srobert }
409*d415bd75Srobert 
parseIdentifier(OutputBuffer * Demangled,const char * Mangled)410*d415bd75Srobert const char *Demangler::parseIdentifier(OutputBuffer *Demangled,
411*d415bd75Srobert                                        const char *Mangled) {
412*d415bd75Srobert   unsigned long Len;
413*d415bd75Srobert 
414*d415bd75Srobert   if (Mangled == nullptr || *Mangled == '\0')
415*d415bd75Srobert     return nullptr;
416*d415bd75Srobert 
417*d415bd75Srobert   if (*Mangled == 'Q')
418*d415bd75Srobert     return parseSymbolBackref(Demangled, Mangled);
419*d415bd75Srobert 
420*d415bd75Srobert   // TODO: Parse lengthless template instances.
421*d415bd75Srobert 
422*d415bd75Srobert   const char *Endptr = decodeNumber(Mangled, Len);
423*d415bd75Srobert 
424*d415bd75Srobert   if (Endptr == nullptr || Len == 0)
425*d415bd75Srobert     return nullptr;
426*d415bd75Srobert 
427*d415bd75Srobert   if (strlen(Endptr) < Len)
428*d415bd75Srobert     return nullptr;
429*d415bd75Srobert 
430*d415bd75Srobert   Mangled = Endptr;
431*d415bd75Srobert 
432*d415bd75Srobert   // TODO: Parse template instances with a length prefix.
433*d415bd75Srobert 
434*d415bd75Srobert   // There can be multiple different declarations in the same function that
435*d415bd75Srobert   // have the same mangled name.  To make the mangled names unique, a fake
436*d415bd75Srobert   // parent in the form `__Sddd' is added to the symbol.
437*d415bd75Srobert   if (Len >= 4 && Mangled[0] == '_' && Mangled[1] == '_' && Mangled[2] == 'S') {
438*d415bd75Srobert     const char *NumPtr = Mangled + 3;
439*d415bd75Srobert     while (NumPtr < (Mangled + Len) && std::isdigit(*NumPtr))
440*d415bd75Srobert       ++NumPtr;
441*d415bd75Srobert 
442*d415bd75Srobert     if (Mangled + Len == NumPtr) {
443*d415bd75Srobert       // Skip over the fake parent.
444*d415bd75Srobert       Mangled += Len;
445*d415bd75Srobert       return parseIdentifier(Demangled, Mangled);
446*d415bd75Srobert     }
447*d415bd75Srobert 
448*d415bd75Srobert     // Else demangle it as a plain identifier.
449*d415bd75Srobert   }
450*d415bd75Srobert 
451*d415bd75Srobert   return parseLName(Demangled, Mangled, Len);
452*d415bd75Srobert }
453*d415bd75Srobert 
parseType(const char * Mangled)454*d415bd75Srobert const char *Demangler::parseType(const char *Mangled) {
455*d415bd75Srobert   if (*Mangled == '\0')
456*d415bd75Srobert     return nullptr;
457*d415bd75Srobert 
458*d415bd75Srobert   switch (*Mangled) {
459*d415bd75Srobert   // TODO: Parse type qualifiers.
460*d415bd75Srobert   // TODO: Parse function types.
461*d415bd75Srobert   // TODO: Parse compound types.
462*d415bd75Srobert   // TODO: Parse delegate types.
463*d415bd75Srobert   // TODO: Parse tuple types.
464*d415bd75Srobert 
465*d415bd75Srobert   // Basic types.
466*d415bd75Srobert   case 'i':
467*d415bd75Srobert     ++Mangled;
468*d415bd75Srobert     // TODO: Add type name dumping
469*d415bd75Srobert     return Mangled;
470*d415bd75Srobert 
471*d415bd75Srobert     // TODO: Add support for the rest of the basic types.
472*d415bd75Srobert 
473*d415bd75Srobert   // Back referenced type.
474*d415bd75Srobert   case 'Q':
475*d415bd75Srobert     return parseTypeBackref(Mangled);
476*d415bd75Srobert 
477*d415bd75Srobert   default: // unhandled.
478*d415bd75Srobert     return nullptr;
479*d415bd75Srobert   }
480*d415bd75Srobert }
481*d415bd75Srobert 
parseLName(OutputBuffer * Demangled,const char * Mangled,unsigned long Len)482*d415bd75Srobert const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
483*d415bd75Srobert                                   unsigned long Len) {
484*d415bd75Srobert   switch (Len) {
485*d415bd75Srobert   case 6:
486*d415bd75Srobert     if (strncmp(Mangled, "__initZ", Len + 1) == 0) {
487*d415bd75Srobert       // The static initializer for a given symbol.
488*d415bd75Srobert       Demangled->prepend("initializer for ");
489*d415bd75Srobert       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
490*d415bd75Srobert       Mangled += Len;
491*d415bd75Srobert       return Mangled;
492*d415bd75Srobert     }
493*d415bd75Srobert     if (strncmp(Mangled, "__vtblZ", Len + 1) == 0) {
494*d415bd75Srobert       // The vtable symbol for a given class.
495*d415bd75Srobert       Demangled->prepend("vtable for ");
496*d415bd75Srobert       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
497*d415bd75Srobert       Mangled += Len;
498*d415bd75Srobert       return Mangled;
499*d415bd75Srobert     }
500*d415bd75Srobert     break;
501*d415bd75Srobert 
502*d415bd75Srobert   case 7:
503*d415bd75Srobert     if (strncmp(Mangled, "__ClassZ", Len + 1) == 0) {
504*d415bd75Srobert       // The classinfo symbol for a given class.
505*d415bd75Srobert       Demangled->prepend("ClassInfo for ");
506*d415bd75Srobert       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
507*d415bd75Srobert       Mangled += Len;
508*d415bd75Srobert       return Mangled;
509*d415bd75Srobert     }
510*d415bd75Srobert     break;
511*d415bd75Srobert 
512*d415bd75Srobert   case 11:
513*d415bd75Srobert     if (strncmp(Mangled, "__InterfaceZ", Len + 1) == 0) {
514*d415bd75Srobert       // The interface symbol for a given class.
515*d415bd75Srobert       Demangled->prepend("Interface for ");
516*d415bd75Srobert       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
517*d415bd75Srobert       Mangled += Len;
518*d415bd75Srobert       return Mangled;
519*d415bd75Srobert     }
520*d415bd75Srobert     break;
521*d415bd75Srobert 
522*d415bd75Srobert   case 12:
523*d415bd75Srobert     if (strncmp(Mangled, "__ModuleInfoZ", Len + 1) == 0) {
524*d415bd75Srobert       // The ModuleInfo symbol for a given module.
525*d415bd75Srobert       Demangled->prepend("ModuleInfo for ");
526*d415bd75Srobert       Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
527*d415bd75Srobert       Mangled += Len;
528*d415bd75Srobert       return Mangled;
529*d415bd75Srobert     }
530*d415bd75Srobert     break;
531*d415bd75Srobert   }
532*d415bd75Srobert 
533*d415bd75Srobert   *Demangled << StringView(Mangled, Len);
534*d415bd75Srobert   Mangled += Len;
535*d415bd75Srobert 
536*d415bd75Srobert   return Mangled;
537*d415bd75Srobert }
538*d415bd75Srobert 
Demangler(const char * Mangled)539*d415bd75Srobert Demangler::Demangler(const char *Mangled)
540*d415bd75Srobert     : Str(Mangled), LastBackref(strlen(Mangled)) {}
541*d415bd75Srobert 
parseMangle(OutputBuffer * Demangled)542*d415bd75Srobert const char *Demangler::parseMangle(OutputBuffer *Demangled) {
543*d415bd75Srobert   return parseMangle(Demangled, this->Str);
544*d415bd75Srobert }
545*d415bd75Srobert 
dlangDemangle(const char * MangledName)546*d415bd75Srobert char *llvm::dlangDemangle(const char *MangledName) {
547*d415bd75Srobert   if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0)
548*d415bd75Srobert     return nullptr;
549*d415bd75Srobert 
550*d415bd75Srobert   OutputBuffer Demangled;
551*d415bd75Srobert   if (strcmp(MangledName, "_Dmain") == 0) {
552*d415bd75Srobert     Demangled << "D main";
553*d415bd75Srobert   } else {
554*d415bd75Srobert 
555*d415bd75Srobert     Demangler D = Demangler(MangledName);
556*d415bd75Srobert     MangledName = D.parseMangle(&Demangled);
557*d415bd75Srobert 
558*d415bd75Srobert     // Check that the entire symbol was successfully demangled.
559*d415bd75Srobert     if (MangledName == nullptr || *MangledName != '\0') {
560*d415bd75Srobert       std::free(Demangled.getBuffer());
561*d415bd75Srobert       return nullptr;
562*d415bd75Srobert     }
563*d415bd75Srobert   }
564*d415bd75Srobert 
565*d415bd75Srobert   // OutputBuffer's internal buffer is not null terminated and therefore we need
566*d415bd75Srobert   // to add it to comply with C null terminated strings.
567*d415bd75Srobert   if (Demangled.getCurrentPosition() > 0) {
568*d415bd75Srobert     Demangled << '\0';
569*d415bd75Srobert     Demangled.setCurrentPosition(Demangled.getCurrentPosition() - 1);
570*d415bd75Srobert     return Demangled.getBuffer();
571*d415bd75Srobert   }
572*d415bd75Srobert 
573*d415bd75Srobert   std::free(Demangled.getBuffer());
574*d415bd75Srobert   return nullptr;
575*d415bd75Srobert }
576