LLVM  15.0.0git
MicrosoftDemangle.cpp
Go to the documentation of this file.
1 //===- MicrosoftDemangle.cpp ----------------------------------------------===//
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 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a demangler for MSVC-style mangled symbols.
10 //
11 // This file has no dependencies on the rest of LLVM so that it can be
12 // easily reused in other programs such as libcxxabi.
13 //
14 //===----------------------------------------------------------------------===//
15 
17 #include "llvm/Demangle/Demangle.h"
19 
22 #include "llvm/Demangle/Utility.h"
23 
24 #include <array>
25 #include <cctype>
26 #include <cstdio>
27 #include <tuple>
28 
29 using namespace llvm;
30 using namespace ms_demangle;
31 
32 static bool startsWithDigit(StringView S) {
33  return !S.empty() && std::isdigit(S.front());
34 }
35 
36 
37 struct NodeList {
38  Node *N = nullptr;
39  NodeList *Next = nullptr;
40 };
41 
42 static bool isMemberPointer(StringView MangledName, bool &Error) {
43  Error = false;
44  switch (MangledName.popFront()) {
45  case '$':
46  // This is probably an rvalue reference (e.g. $$Q), and you cannot have an
47  // rvalue reference to a member.
48  return false;
49  case 'A':
50  // 'A' indicates a reference, and you cannot have a reference to a member
51  // function or member.
52  return false;
53  case 'P':
54  case 'Q':
55  case 'R':
56  case 'S':
57  // These 4 values indicate some kind of pointer, but we still don't know
58  // what.
59  break;
60  default:
61  // isMemberPointer() is called only if isPointerType() returns true,
62  // and it rejects other prefixes.
64  }
65 
66  // If it starts with a number, then 6 indicates a non-member function
67  // pointer, and 8 indicates a member function pointer.
68  if (startsWithDigit(MangledName)) {
69  if (MangledName[0] != '6' && MangledName[0] != '8') {
70  Error = true;
71  return false;
72  }
73  return (MangledName[0] == '8');
74  }
75 
76  // Remove ext qualifiers since those can appear on either type and are
77  // therefore not indicative.
78  MangledName.consumeFront('E'); // 64-bit
79  MangledName.consumeFront('I'); // restrict
80  MangledName.consumeFront('F'); // unaligned
81 
82  if (MangledName.empty()) {
83  Error = true;
84  return false;
85  }
86 
87  // The next value should be either ABCD (non-member) or QRST (member).
88  switch (MangledName.front()) {
89  case 'A':
90  case 'B':
91  case 'C':
92  case 'D':
93  return false;
94  case 'Q':
95  case 'R':
96  case 'S':
97  case 'T':
98  return true;
99  default:
100  Error = true;
101  return false;
102  }
103 }
104 
106 consumeSpecialIntrinsicKind(StringView &MangledName) {
107  if (MangledName.consumeFront("?_7"))
109  if (MangledName.consumeFront("?_8"))
111  if (MangledName.consumeFront("?_9"))
113  if (MangledName.consumeFront("?_A"))
115  if (MangledName.consumeFront("?_B"))
117  if (MangledName.consumeFront("?_C"))
119  if (MangledName.consumeFront("?_P"))
121  if (MangledName.consumeFront("?_R0"))
123  if (MangledName.consumeFront("?_R1"))
125  if (MangledName.consumeFront("?_R2"))
127  if (MangledName.consumeFront("?_R3"))
129  if (MangledName.consumeFront("?_R4"))
131  if (MangledName.consumeFront("?_S"))
133  if (MangledName.consumeFront("?__E"))
135  if (MangledName.consumeFront("?__F"))
137  if (MangledName.consumeFront("?__J"))
140 }
141 
142 static bool startsWithLocalScopePattern(StringView S) {
143  if (!S.consumeFront('?'))
144  return false;
145 
146  size_t End = S.find('?');
147  if (End == StringView::npos)
148  return false;
149  StringView Candidate = S.substr(0, End);
150  if (Candidate.empty())
151  return false;
152 
153  // \?[0-9]\?
154  // ?@? is the discriminator 0.
155  if (Candidate.size() == 1)
156  return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9');
157 
158  // If it's not 0-9, then it's an encoded number terminated with an @
159  if (Candidate.back() != '@')
160  return false;
161  Candidate = Candidate.dropBack();
162 
163  // An encoded number starts with B-P and all subsequent digits are in A-P.
164  // Note that the reason the first digit cannot be A is two fold. First, it
165  // would create an ambiguity with ?A which delimits the beginning of an
166  // anonymous namespace. Second, A represents 0, and you don't start a multi
167  // digit number with a leading 0. Presumably the anonymous namespace
168  // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J.
169  if (Candidate[0] < 'B' || Candidate[0] > 'P')
170  return false;
171  Candidate = Candidate.dropFront();
172  while (!Candidate.empty()) {
173  if (Candidate[0] < 'A' || Candidate[0] > 'P')
174  return false;
175  Candidate = Candidate.dropFront();
176  }
177 
178  return true;
179 }
180 
181 static bool isTagType(StringView S) {
182  switch (S.front()) {
183  case 'T': // union
184  case 'U': // struct
185  case 'V': // class
186  case 'W': // enum
187  return true;
188  }
189  return false;
190 }
191 
192 static bool isCustomType(StringView S) { return S[0] == '?'; }
193 
194 static bool isPointerType(StringView S) {
195  if (S.startsWith("$$Q")) // foo &&
196  return true;
197 
198  switch (S.front()) {
199  case 'A': // foo &
200  case 'P': // foo *
201  case 'Q': // foo *const
202  case 'R': // foo *volatile
203  case 'S': // foo *const volatile
204  return true;
205  }
206  return false;
207 }
208 
209 static bool isArrayType(StringView S) { return S[0] == 'Y'; }
210 
211 static bool isFunctionType(StringView S) {
212  return S.startsWith("$$A8@@") || S.startsWith("$$A6");
213 }
214 
216 demangleFunctionRefQualifier(StringView &MangledName) {
217  if (MangledName.consumeFront('G'))
219  else if (MangledName.consumeFront('H'))
222 }
223 
224 static std::pair<Qualifiers, PointerAffinity>
225 demanglePointerCVQualifiers(StringView &MangledName) {
226  if (MangledName.consumeFront("$$Q"))
227  return std::make_pair(Q_None, PointerAffinity::RValueReference);
228 
229  switch (MangledName.popFront()) {
230  case 'A':
231  return std::make_pair(Q_None, PointerAffinity::Reference);
232  case 'P':
233  return std::make_pair(Q_None, PointerAffinity::Pointer);
234  case 'Q':
235  return std::make_pair(Q_Const, PointerAffinity::Pointer);
236  case 'R':
237  return std::make_pair(Q_Volatile, PointerAffinity::Pointer);
238  case 'S':
239  return std::make_pair(Qualifiers(Q_Const | Q_Volatile),
241  }
242  // This function is only called if isPointerType() returns true,
243  // and it only returns true for the six cases listed above.
245 }
246 
247 StringView Demangler::copyString(StringView Borrowed) {
248  char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
249  std::memcpy(Stable, Borrowed.begin(), Borrowed.size());
250 
251  return {Stable, Borrowed.size()};
252 }
253 
255 Demangler::demangleSpecialTableSymbolNode(StringView &MangledName,
258  switch (K) {
260  NI->Name = "`vftable'";
261  break;
263  NI->Name = "`vbtable'";
264  break;
266  NI->Name = "`local vftable'";
267  break;
269  NI->Name = "`RTTI Complete Object Locator'";
270  break;
271  default:
273  }
274  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
276  STSN->Name = QN;
277  bool IsMember = false;
278  if (MangledName.empty()) {
279  Error = true;
280  return nullptr;
281  }
282  char Front = MangledName.popFront();
283  if (Front != '6' && Front != '7') {
284  Error = true;
285  return nullptr;
286  }
287 
288  std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
289  if (!MangledName.consumeFront('@'))
290  STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);
291  return STSN;
292 }
293 
295 Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) {
298  LSGI->IsThread = IsThread;
299  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
302  LSGVN->Name = QN;
303 
304  if (MangledName.consumeFront("4IA"))
305  LSGVN->IsVisible = false;
306  else if (MangledName.consumeFront("5"))
307  LSGVN->IsVisible = true;
308  else {
309  Error = true;
310  return nullptr;
311  }
312 
313  if (!MangledName.empty())
314  LSGI->ScopeIndex = demangleUnsigned(MangledName);
315  return LSGVN;
316 }
317 
319  StringView Name) {
321  Id->Name = Name;
322  return Id;
323 }
324 
326  IdentifierNode *Identifier) {
328  QN->Components = Arena.alloc<NodeArrayNode>();
329  QN->Components->Count = 1;
330  QN->Components->Nodes = Arena.allocArray<Node *>(1);
331  QN->Components->Nodes[0] = Identifier;
332  return QN;
333 }
334 
336  StringView Name) {
338  return synthesizeQualifiedName(Arena, Id);
339 }
340 
342  TypeNode *Type,
343  StringView VariableName) {
345  VSN->Type = Type;
346  VSN->Name = synthesizeQualifiedName(Arena, VariableName);
347  return VSN;
348 }
349 
350 VariableSymbolNode *Demangler::demangleUntypedVariable(
351  ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) {
352  NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName);
353  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
355  VSN->Name = QN;
356  if (MangledName.consumeFront("8"))
357  return VSN;
358 
359  Error = true;
360  return nullptr;
361 }
362 
364 Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
365  StringView &MangledName) {
368  RBCDN->NVOffset = demangleUnsigned(MangledName);
369  RBCDN->VBPtrOffset = demangleSigned(MangledName);
370  RBCDN->VBTableOffset = demangleUnsigned(MangledName);
371  RBCDN->Flags = demangleUnsigned(MangledName);
372  if (Error)
373  return nullptr;
374 
376  VSN->Name = demangleNameScopeChain(MangledName, RBCDN);
377  MangledName.consumeFront('8');
378  return VSN;
379 }
380 
381 FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName,
382  bool IsDestructor) {
385  DSIN->IsDestructor = IsDestructor;
386 
387  bool IsKnownStaticDataMember = false;
388  if (MangledName.consumeFront('?'))
389  IsKnownStaticDataMember = true;
390 
391  SymbolNode *Symbol = demangleDeclarator(MangledName);
392  if (Error)
393  return nullptr;
394 
395  FunctionSymbolNode *FSN = nullptr;
396 
397  if (Symbol->kind() == NodeKind::VariableSymbol) {
398  DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
399 
400  // Older versions of clang mangled this type of symbol incorrectly. They
401  // would omit the leading ? and they would only emit a single @ at the end.
402  // The correct mangling is a leading ? and 2 trailing @ signs. Handle
403  // both cases.
404  int AtCount = IsKnownStaticDataMember ? 2 : 1;
405  for (int I = 0; I < AtCount; ++I) {
406  if (MangledName.consumeFront('@'))
407  continue;
408  Error = true;
409  return nullptr;
410  }
411 
412  FSN = demangleFunctionEncoding(MangledName);
413  if (FSN)
414  FSN->Name = synthesizeQualifiedName(Arena, DSIN);
415  } else {
416  if (IsKnownStaticDataMember) {
417  // This was supposed to be a static data member, but we got a function.
418  Error = true;
419  return nullptr;
420  }
421 
422  FSN = static_cast<FunctionSymbolNode *>(Symbol);
423  DSIN->Name = Symbol->Name;
424  FSN->Name = synthesizeQualifiedName(Arena, DSIN);
425  }
426 
427  return FSN;
428 }
429 
430 SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) {
432 
433  switch (SIK) {
435  return nullptr;
436  case SpecialIntrinsicKind::StringLiteralSymbol:
437  return demangleStringLiteral(MangledName);
438  case SpecialIntrinsicKind::Vftable:
439  case SpecialIntrinsicKind::Vbtable:
440  case SpecialIntrinsicKind::LocalVftable:
441  case SpecialIntrinsicKind::RttiCompleteObjLocator:
442  return demangleSpecialTableSymbolNode(MangledName, SIK);
443  case SpecialIntrinsicKind::VcallThunk:
444  return demangleVcallThunkNode(MangledName);
445  case SpecialIntrinsicKind::LocalStaticGuard:
446  return demangleLocalStaticGuard(MangledName, /*IsThread=*/false);
447  case SpecialIntrinsicKind::LocalStaticThreadGuard:
448  return demangleLocalStaticGuard(MangledName, /*IsThread=*/true);
449  case SpecialIntrinsicKind::RttiTypeDescriptor: {
450  TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
451  if (Error)
452  break;
453  if (!MangledName.consumeFront("@8"))
454  break;
455  if (!MangledName.empty())
456  break;
457  return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");
458  }
459  case SpecialIntrinsicKind::RttiBaseClassArray:
460  return demangleUntypedVariable(Arena, MangledName,
461  "`RTTI Base Class Array'");
462  case SpecialIntrinsicKind::RttiClassHierarchyDescriptor:
463  return demangleUntypedVariable(Arena, MangledName,
464  "`RTTI Class Hierarchy Descriptor'");
465  case SpecialIntrinsicKind::RttiBaseClassDescriptor:
466  return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
467  case SpecialIntrinsicKind::DynamicInitializer:
468  return demangleInitFiniStub(MangledName, /*IsDestructor=*/false);
469  case SpecialIntrinsicKind::DynamicAtexitDestructor:
470  return demangleInitFiniStub(MangledName, /*IsDestructor=*/true);
471  case SpecialIntrinsicKind::Typeof:
472  case SpecialIntrinsicKind::UdtReturning:
473  // It's unclear which tools produces these manglings, so demangling
474  // support is not (yet?) implemented.
475  break;
477  DEMANGLE_UNREACHABLE; // Never returned by consumeSpecialIntrinsicKind.
478  }
479  Error = true;
480  return nullptr;
481 }
482 
484 Demangler::demangleFunctionIdentifierCode(StringView &MangledName) {
485  assert(MangledName.startsWith('?'));
486  MangledName = MangledName.dropFront();
487  if (MangledName.empty()) {
488  Error = true;
489  return nullptr;
490  }
491 
492  if (MangledName.consumeFront("__"))
493  return demangleFunctionIdentifierCode(
494  MangledName, FunctionIdentifierCodeGroup::DoubleUnder);
495  if (MangledName.consumeFront("_"))
496  return demangleFunctionIdentifierCode(MangledName,
497  FunctionIdentifierCodeGroup::Under);
498  return demangleFunctionIdentifierCode(MangledName,
500 }
501 
503 Demangler::demangleStructorIdentifier(StringView &MangledName,
504  bool IsDestructor) {
506  N->IsDestructor = IsDestructor;
507  return N;
508 }
509 
511 Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) {
514  return N;
515 }
516 
518 Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) {
521  N->Name = demangleSimpleString(MangledName, /*Memorize=*/false);
522  return N;
523 }
524 
526 Demangler::translateIntrinsicFunctionCode(char CH,
528  using IFK = IntrinsicFunctionKind;
529  if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) {
530  Error = true;
531  return IFK::None;
532  }
533 
534  // Not all ? identifiers are intrinsics *functions*. This function only maps
535  // operator codes for the special functions, all others are handled elsewhere,
536  // hence the IFK::None entries in the table.
537  static IFK Basic[36] = {
538  IFK::None, // ?0 # Foo::Foo()
539  IFK::None, // ?1 # Foo::~Foo()
540  IFK::New, // ?2 # operator new
541  IFK::Delete, // ?3 # operator delete
542  IFK::Assign, // ?4 # operator=
543  IFK::RightShift, // ?5 # operator>>
544  IFK::LeftShift, // ?6 # operator<<
545  IFK::LogicalNot, // ?7 # operator!
546  IFK::Equals, // ?8 # operator==
547  IFK::NotEquals, // ?9 # operator!=
548  IFK::ArraySubscript, // ?A # operator[]
549  IFK::None, // ?B # Foo::operator <type>()
550  IFK::Pointer, // ?C # operator->
551  IFK::Dereference, // ?D # operator*
552  IFK::Increment, // ?E # operator++
553  IFK::Decrement, // ?F # operator--
554  IFK::Minus, // ?G # operator-
555  IFK::Plus, // ?H # operator+
556  IFK::BitwiseAnd, // ?I # operator&
557  IFK::MemberPointer, // ?J # operator->*
558  IFK::Divide, // ?K # operator/
559  IFK::Modulus, // ?L # operator%
560  IFK::LessThan, // ?M operator<
561  IFK::LessThanEqual, // ?N operator<=
562  IFK::GreaterThan, // ?O operator>
563  IFK::GreaterThanEqual, // ?P operator>=
564  IFK::Comma, // ?Q operator,
565  IFK::Parens, // ?R operator()
566  IFK::BitwiseNot, // ?S operator~
567  IFK::BitwiseXor, // ?T operator^
568  IFK::BitwiseOr, // ?U operator|
569  IFK::LogicalAnd, // ?V operator&&
570  IFK::LogicalOr, // ?W operator||
571  IFK::TimesEqual, // ?X operator*=
572  IFK::PlusEqual, // ?Y operator+=
573  IFK::MinusEqual, // ?Z operator-=
574  };
575  static IFK Under[36] = {
576  IFK::DivEqual, // ?_0 operator/=
577  IFK::ModEqual, // ?_1 operator%=
578  IFK::RshEqual, // ?_2 operator>>=
579  IFK::LshEqual, // ?_3 operator<<=
580  IFK::BitwiseAndEqual, // ?_4 operator&=
581  IFK::BitwiseOrEqual, // ?_5 operator|=
582  IFK::BitwiseXorEqual, // ?_6 operator^=
583  IFK::None, // ?_7 # vftable
584  IFK::None, // ?_8 # vbtable
585  IFK::None, // ?_9 # vcall
586  IFK::None, // ?_A # typeof
587  IFK::None, // ?_B # local static guard
588  IFK::None, // ?_C # string literal
589  IFK::VbaseDtor, // ?_D # vbase destructor
590  IFK::VecDelDtor, // ?_E # vector deleting destructor
591  IFK::DefaultCtorClosure, // ?_F # default constructor closure
592  IFK::ScalarDelDtor, // ?_G # scalar deleting destructor
593  IFK::VecCtorIter, // ?_H # vector constructor iterator
594  IFK::VecDtorIter, // ?_I # vector destructor iterator
595  IFK::VecVbaseCtorIter, // ?_J # vector vbase constructor iterator
596  IFK::VdispMap, // ?_K # virtual displacement map
597  IFK::EHVecCtorIter, // ?_L # eh vector constructor iterator
598  IFK::EHVecDtorIter, // ?_M # eh vector destructor iterator
599  IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
600  IFK::CopyCtorClosure, // ?_O # copy constructor closure
601  IFK::None, // ?_P<name> # udt returning <name>
602  IFK::None, // ?_Q # <unknown>
603  IFK::None, // ?_R0 - ?_R4 # RTTI Codes
604  IFK::None, // ?_S # local vftable
605  IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure
606  IFK::ArrayNew, // ?_U operator new[]
607  IFK::ArrayDelete, // ?_V operator delete[]
608  IFK::None, // ?_W <unused>
609  IFK::None, // ?_X <unused>
610  IFK::None, // ?_Y <unused>
611  IFK::None, // ?_Z <unused>
612  };
613  static IFK DoubleUnder[36] = {
614  IFK::None, // ?__0 <unused>
615  IFK::None, // ?__1 <unused>
616  IFK::None, // ?__2 <unused>
617  IFK::None, // ?__3 <unused>
618  IFK::None, // ?__4 <unused>
619  IFK::None, // ?__5 <unused>
620  IFK::None, // ?__6 <unused>
621  IFK::None, // ?__7 <unused>
622  IFK::None, // ?__8 <unused>
623  IFK::None, // ?__9 <unused>
624  IFK::ManVectorCtorIter, // ?__A managed vector ctor iterator
625  IFK::ManVectorDtorIter, // ?__B managed vector dtor iterator
626  IFK::EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator
627  IFK::EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iter
628  IFK::None, // ?__E dynamic initializer for `T'
629  IFK::None, // ?__F dynamic atexit destructor for `T'
630  IFK::VectorCopyCtorIter, // ?__G vector copy constructor iter
631  IFK::VectorVbaseCopyCtorIter, // ?__H vector vbase copy ctor iter
632  IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor
633  // iter
634  IFK::None, // ?__J local static thread guard
635  IFK::None, // ?__K operator ""_name
636  IFK::CoAwait, // ?__L operator co_await
637  IFK::Spaceship, // ?__M operator<=>
638  IFK::None, // ?__N <unused>
639  IFK::None, // ?__O <unused>
640  IFK::None, // ?__P <unused>
641  IFK::None, // ?__Q <unused>
642  IFK::None, // ?__R <unused>
643  IFK::None, // ?__S <unused>
644  IFK::None, // ?__T <unused>
645  IFK::None, // ?__U <unused>
646  IFK::None, // ?__V <unused>
647  IFK::None, // ?__W <unused>
648  IFK::None, // ?__X <unused>
649  IFK::None, // ?__Y <unused>
650  IFK::None, // ?__Z <unused>
651  };
652 
653  int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10);
654  switch (Group) {
656  return Basic[Index];
657  case FunctionIdentifierCodeGroup::Under:
658  return Under[Index];
659  case FunctionIdentifierCodeGroup::DoubleUnder:
660  return DoubleUnder[Index];
661  }
663 }
664 
666 Demangler::demangleFunctionIdentifierCode(StringView &MangledName,
668  if (MangledName.empty()) {
669  Error = true;
670  return nullptr;
671  }
672  switch (Group) {
674  switch (char CH = MangledName.popFront()) {
675  case '0':
676  case '1':
677  return demangleStructorIdentifier(MangledName, CH == '1');
678  case 'B':
679  return demangleConversionOperatorIdentifier(MangledName);
680  default:
682  translateIntrinsicFunctionCode(CH, Group));
683  }
684  case FunctionIdentifierCodeGroup::Under:
686  translateIntrinsicFunctionCode(MangledName.popFront(), Group));
687  case FunctionIdentifierCodeGroup::DoubleUnder:
688  switch (char CH = MangledName.popFront()) {
689  case 'K':
690  return demangleLiteralOperatorIdentifier(MangledName);
691  default:
693  translateIntrinsicFunctionCode(CH, Group));
694  }
695  }
696 
698 }
699 
700 SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName,
702  if (MangledName.empty()) {
703  Error = true;
704  return nullptr;
705  }
706 
707  // Read a variable.
708  switch (MangledName.front()) {
709  case '0':
710  case '1':
711  case '2':
712  case '3':
713  case '4': {
714  StorageClass SC = demangleVariableStorageClass(MangledName);
715  return demangleVariableEncoding(MangledName, SC);
716  }
717  }
718  FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
719 
720  IdentifierNode *UQN = Name->getUnqualifiedIdentifier();
721  if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
723  static_cast<ConversionOperatorIdentifierNode *>(UQN);
724  if (FSN)
725  COIN->TargetType = FSN->Signature->ReturnType;
726  }
727  return FSN;
728 }
729 
730 SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) {
731  // What follows is a main symbol name. This may include namespaces or class
732  // back references.
733  QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
734  if (Error)
735  return nullptr;
736 
737  SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
738  if (Error)
739  return nullptr;
740  Symbol->Name = QN;
741 
743  if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
745  static_cast<ConversionOperatorIdentifierNode *>(UQN);
746  if (!COIN->TargetType) {
747  Error = true;
748  return nullptr;
749  }
750  }
751  return Symbol;
752 }
753 
754 SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) {
755  assert(MangledName.startsWith("??@"));
756  // This is an MD5 mangled name. We can't demangle it, just return the
757  // mangled name.
758  // An MD5 mangled name is ??@ followed by 32 characters and a terminating @.
759  size_t MD5Last = MangledName.find('@', strlen("??@"));
760  if (MD5Last == StringView::npos) {
761  Error = true;
762  return nullptr;
763  }
764  const char *Start = MangledName.begin();
765  MangledName = MangledName.dropFront(MD5Last + 1);
766 
767  // There are two additional special cases for MD5 names:
768  // 1. For complete object locators where the object name is long enough
769  // for the object to have an MD5 name, the complete object locator is
770  // called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual
771  // leading "??_R4". This is handled here.
772  // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after
773  // 2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8
774  // instead of_CT??@...@8 with just one MD5 name. Since we don't yet
775  // demangle catchable types anywhere, this isn't handled for MD5 names
776  // either.
777  MangledName.consumeFront("??_R4@");
778 
779  StringView MD5(Start, MangledName.begin());
780  SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol);
781  S->Name = synthesizeQualifiedName(Arena, MD5);
782 
783  return S;
784 }
785 
786 SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) {
787  assert(MangledName.startsWith('.'));
788  MangledName.consumeFront('.');
789 
790  TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
791  if (Error || !MangledName.empty()) {
792  Error = true;
793  return nullptr;
794  }
795  return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'");
796 }
797 
798 // Parser entry point.
799 SymbolNode *Demangler::parse(StringView &MangledName) {
800  // Typeinfo names are strings stored in RTTI data. They're not symbol names.
801  // It's still useful to demangle them. They're the only demangled entity
802  // that doesn't start with a "?" but a ".".
803  if (MangledName.startsWith('.'))
804  return demangleTypeinfoName(MangledName);
805 
806  if (MangledName.startsWith("??@"))
807  return demangleMD5Name(MangledName);
808 
809  // MSVC-style mangled symbols must start with '?'.
810  if (!MangledName.startsWith('?')) {
811  Error = true;
812  return nullptr;
813  }
814 
815  MangledName.consumeFront('?');
816 
817  // ?$ is a template instantiation, but all other names that start with ? are
818  // operators / special names.
819  if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
820  return SI;
821 
822  return demangleDeclarator(MangledName);
823 }
824 
825 TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
826  if (!MangledName.consumeFront(".?A"))
827  return nullptr;
828  MangledName.consumeFront(".?A");
829  if (MangledName.empty())
830  return nullptr;
831 
832  return demangleClassType(MangledName);
833 }
834 
835 // <type-encoding> ::= <storage-class> <variable-type>
836 // <storage-class> ::= 0 # private static member
837 // ::= 1 # protected static member
838 // ::= 2 # public static member
839 // ::= 3 # global
840 // ::= 4 # static local
841 
842 VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName,
843  StorageClass SC) {
845 
846  VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
847  VSN->SC = SC;
848 
849  if (Error)
850  return nullptr;
851 
852  // <variable-type> ::= <type> <cvr-qualifiers>
853  // ::= <type> <pointee-cvr-qualifiers> # pointers, references
854  switch (VSN->Type->kind()) {
855  case NodeKind::PointerType: {
856  PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type);
857 
858  Qualifiers ExtraChildQuals = Q_None;
859  PTN->Quals = Qualifiers(VSN->Type->Quals |
860  demanglePointerExtQualifiers(MangledName));
861 
862  bool IsMember = false;
863  std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
864 
865  if (PTN->ClassParent) {
866  QualifiedNameNode *BackRefName =
867  demangleFullyQualifiedTypeName(MangledName);
868  (void)BackRefName;
869  }
870  PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals);
871 
872  break;
873  }
874  default:
875  VSN->Type->Quals = demangleQualifiers(MangledName).first;
876  break;
877  }
878 
879  return VSN;
880 }
881 
882 // Sometimes numbers are encoded in mangled symbols. For example,
883 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
884 // length 20), so we need some way to embed numbers as part of symbols.
885 // This function parses it.
886 //
887 // <number> ::= [?] <non-negative integer>
888 //
889 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
890 // ::= <hex digit>+ @ # when Number == 0 or >= 10
891 //
892 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
893 std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
894  bool IsNegative = MangledName.consumeFront('?');
895 
896  if (startsWithDigit(MangledName)) {
897  uint64_t Ret = MangledName[0] - '0' + 1;
898  MangledName = MangledName.dropFront(1);
899  return {Ret, IsNegative};
900  }
901 
902  uint64_t Ret = 0;
903  for (size_t i = 0; i < MangledName.size(); ++i) {
904  char C = MangledName[i];
905  if (C == '@') {
906  MangledName = MangledName.dropFront(i + 1);
907  return {Ret, IsNegative};
908  }
909  if ('A' <= C && C <= 'P') {
910  Ret = (Ret << 4) + (C - 'A');
911  continue;
912  }
913  break;
914  }
915 
916  Error = true;
917  return {0ULL, false};
918 }
919 
920 uint64_t Demangler::demangleUnsigned(StringView &MangledName) {
921  bool IsNegative = false;
922  uint64_t Number = 0;
923  std::tie(Number, IsNegative) = demangleNumber(MangledName);
924  if (IsNegative)
925  Error = true;
926  return Number;
927 }
928 
929 int64_t Demangler::demangleSigned(StringView &MangledName) {
930  bool IsNegative = false;
931  uint64_t Number = 0;
932  std::tie(Number, IsNegative) = demangleNumber(MangledName);
933  if (Number > INT64_MAX)
934  Error = true;
935  int64_t I = static_cast<int64_t>(Number);
936  return IsNegative ? -I : I;
937 }
938 
939 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
940 // Memorize it.
941 void Demangler::memorizeString(StringView S) {
942  if (Backrefs.NamesCount >= BackrefContext::Max)
943  return;
944  for (size_t i = 0; i < Backrefs.NamesCount; ++i)
945  if (S == Backrefs.Names[i]->Name)
946  return;
948  N->Name = S;
949  Backrefs.Names[Backrefs.NamesCount++] = N;
950 }
951 
952 NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) {
953  assert(startsWithDigit(MangledName));
954 
955  size_t I = MangledName[0] - '0';
956  if (I >= Backrefs.NamesCount) {
957  Error = true;
958  return nullptr;
959  }
960 
961  MangledName = MangledName.dropFront();
962  return Backrefs.Names[I];
963 }
964 
965 void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
966  // Render this class template name into a string buffer so that we can
967  // memorize it for the purpose of back-referencing.
968  OutputBuffer OB;
969  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
970  // FIXME: Propagate out-of-memory as an error?
971  std::terminate();
972  Identifier->output(OB, OF_Default);
973  StringView Owned = copyString(OB);
974  memorizeString(Owned);
975  std::free(OB.getBuffer());
976 }
977 
979 Demangler::demangleTemplateInstantiationName(StringView &MangledName,
980  NameBackrefBehavior NBB) {
981  assert(MangledName.startsWith("?$"));
982  MangledName.consumeFront("?$");
983 
984  BackrefContext OuterContext;
985  std::swap(OuterContext, Backrefs);
986 
988  demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
989  if (!Error)
990  Identifier->TemplateParams = demangleTemplateParameterList(MangledName);
991 
992  std::swap(OuterContext, Backrefs);
993  if (Error)
994  return nullptr;
995 
996  if (NBB & NBB_Template) {
997  // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
998  // Structors and conversion operators only makes sense in a leaf name, so
999  // reject them in NBB_Template contexts.
1000  if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier ||
1001  Identifier->kind() == NodeKind::StructorIdentifier) {
1002  Error = true;
1003  return nullptr;
1004  }
1005 
1006  memorizeIdentifier(Identifier);
1007  }
1008 
1009  return Identifier;
1010 }
1011 
1012 NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName,
1013  bool Memorize) {
1014  StringView S = demangleSimpleString(MangledName, Memorize);
1015  if (Error)
1016  return nullptr;
1017 
1019  Name->Name = S;
1020  return Name;
1021 }
1022 
1023 static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); }
1024 
1025 static uint8_t rebasedHexDigitToNumber(char C) {
1027  return (C <= 'J') ? (C - 'A') : (10 + C - 'K');
1028 }
1029 
1030 uint8_t Demangler::demangleCharLiteral(StringView &MangledName) {
1031  assert(!MangledName.empty());
1032  if (!MangledName.startsWith('?'))
1033  return MangledName.popFront();
1034 
1035  MangledName = MangledName.dropFront();
1036  if (MangledName.empty())
1037  goto CharLiteralError;
1038 
1039  if (MangledName.consumeFront('$')) {
1040  // Two hex digits
1041  if (MangledName.size() < 2)
1042  goto CharLiteralError;
1043  StringView Nibbles = MangledName.substr(0, 2);
1044  if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1]))
1045  goto CharLiteralError;
1046  // Don't append the null terminator.
1047  uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]);
1048  uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]);
1049  MangledName = MangledName.dropFront(2);
1050  return (C1 << 4) | C2;
1051  }
1052 
1053  if (startsWithDigit(MangledName)) {
1054  const char *Lookup = ",/\\:. \n\t'-";
1055  char C = Lookup[MangledName[0] - '0'];
1056  MangledName = MangledName.dropFront();
1057  return C;
1058  }
1059 
1060  if (MangledName[0] >= 'a' && MangledName[0] <= 'z') {
1061  char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1062  '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1063  '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1064  '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1065  char C = Lookup[MangledName[0] - 'a'];
1066  MangledName = MangledName.dropFront();
1067  return C;
1068  }
1069 
1070  if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') {
1071  char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1072  '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1073  '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1074  '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1075  char C = Lookup[MangledName[0] - 'A'];
1076  MangledName = MangledName.dropFront();
1077  return C;
1078  }
1079 
1080 CharLiteralError:
1081  Error = true;
1082  return '\0';
1083 }
1084 
1085 wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) {
1086  uint8_t C1, C2;
1087 
1088  C1 = demangleCharLiteral(MangledName);
1089  if (Error || MangledName.empty())
1090  goto WCharLiteralError;
1091  C2 = demangleCharLiteral(MangledName);
1092  if (Error)
1093  goto WCharLiteralError;
1094 
1095  return ((wchar_t)C1 << 8) | (wchar_t)C2;
1096 
1097 WCharLiteralError:
1098  Error = true;
1099  return L'\0';
1100 }
1101 
1102 static void writeHexDigit(char *Buffer, uint8_t Digit) {
1103  assert(Digit <= 15);
1104  *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
1105 }
1106 
1107 static void outputHex(OutputBuffer &OB, unsigned C) {
1108  assert (C != 0);
1109 
1110  // It's easier to do the math if we can work from right to left, but we need
1111  // to print the numbers from left to right. So render this into a temporary
1112  // buffer first, then output the temporary buffer. Each byte is of the form
1113  // \xAB, which means that each byte needs 4 characters. Since there are at
1114  // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1115  char TempBuffer[17];
1116 
1117  ::memset(TempBuffer, 0, sizeof(TempBuffer));
1118  constexpr int MaxPos = sizeof(TempBuffer) - 1;
1119 
1120  int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0.
1121  while (C != 0) {
1122  for (int I = 0; I < 2; ++I) {
1123  writeHexDigit(&TempBuffer[Pos--], C % 16);
1124  C /= 16;
1125  }
1126  }
1127  TempBuffer[Pos--] = 'x';
1128  assert(Pos >= 0);
1129  TempBuffer[Pos--] = '\\';
1130  OB << StringView(&TempBuffer[Pos + 1]);
1131 }
1132 
1133 static void outputEscapedChar(OutputBuffer &OB, unsigned C) {
1134  switch (C) {
1135  case '\0': // nul
1136  OB << "\\0";
1137  return;
1138  case '\'': // single quote
1139  OB << "\\\'";
1140  return;
1141  case '\"': // double quote
1142  OB << "\\\"";
1143  return;
1144  case '\\': // backslash
1145  OB << "\\\\";
1146  return;
1147  case '\a': // bell
1148  OB << "\\a";
1149  return;
1150  case '\b': // backspace
1151  OB << "\\b";
1152  return;
1153  case '\f': // form feed
1154  OB << "\\f";
1155  return;
1156  case '\n': // new line
1157  OB << "\\n";
1158  return;
1159  case '\r': // carriage return
1160  OB << "\\r";
1161  return;
1162  case '\t': // tab
1163  OB << "\\t";
1164  return;
1165  case '\v': // vertical tab
1166  OB << "\\v";
1167  return;
1168  default:
1169  break;
1170  }
1171 
1172  if (C > 0x1F && C < 0x7F) {
1173  // Standard ascii char.
1174  OB << (char)C;
1175  return;
1176  }
1177 
1178  outputHex(OB, C);
1179 }
1180 
1181 static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) {
1182  const uint8_t *End = StringBytes + Length - 1;
1183  unsigned Count = 0;
1184  while (Length > 0 && *End == 0) {
1185  --Length;
1186  --End;
1187  ++Count;
1188  }
1189  return Count;
1190 }
1191 
1192 static unsigned countEmbeddedNulls(const uint8_t *StringBytes,
1193  unsigned Length) {
1194  unsigned Result = 0;
1195  for (unsigned I = 0; I < Length; ++I) {
1196  if (*StringBytes++ == 0)
1197  ++Result;
1198  }
1199  return Result;
1200 }
1201 
1202 // A mangled (non-wide) string literal stores the total length of the string it
1203 // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
1204 // (passed in StringBytes, NumChars).
1205 static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars,
1206  uint64_t NumBytes) {
1207  assert(NumBytes > 0);
1208 
1209  // If the number of bytes is odd, this is guaranteed to be a char string.
1210  if (NumBytes % 2 == 1)
1211  return 1;
1212 
1213  // All strings can encode at most 32 bytes of data. If it's less than that,
1214  // then we encoded the entire string. In this case we check for a 1-byte,
1215  // 2-byte, or 4-byte null terminator.
1216  if (NumBytes < 32) {
1217  unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars);
1218  if (TrailingNulls >= 4 && NumBytes % 4 == 0)
1219  return 4;
1220  if (TrailingNulls >= 2)
1221  return 2;
1222  return 1;
1223  }
1224 
1225  // The whole string was not able to be encoded. Try to look at embedded null
1226  // terminators to guess. The heuristic is that we count all embedded null
1227  // terminators. If more than 2/3 are null, it's a char32. If more than 1/3
1228  // are null, it's a char16. Otherwise it's a char8. This obviously isn't
1229  // perfect and is biased towards languages that have ascii alphabets, but this
1230  // was always going to be best effort since the encoding is lossy.
1231  unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars);
1232  if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
1233  return 4;
1234  if (Nulls >= NumChars / 3)
1235  return 2;
1236  return 1;
1237 }
1238 
1239 static unsigned decodeMultiByteChar(const uint8_t *StringBytes,
1240  unsigned CharIndex, unsigned CharBytes) {
1241  assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4);
1242  unsigned Offset = CharIndex * CharBytes;
1243  unsigned Result = 0;
1244  StringBytes = StringBytes + Offset;
1245  for (unsigned I = 0; I < CharBytes; ++I) {
1246  unsigned C = static_cast<unsigned>(StringBytes[I]);
1247  Result |= C << (8 * I);
1248  }
1249  return Result;
1250 }
1251 
1252 FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) {
1255  FSN->Signature = Arena.alloc<ThunkSignatureNode>();
1257 
1258  FSN->Name = demangleNameScopeChain(MangledName, VTIN);
1259  if (!Error)
1260  Error = !MangledName.consumeFront("$B");
1261  if (!Error)
1262  VTIN->OffsetInVTable = demangleUnsigned(MangledName);
1263  if (!Error)
1264  Error = !MangledName.consumeFront('A');
1265  if (!Error)
1266  FSN->Signature->CallConvention = demangleCallingConvention(MangledName);
1267  return (Error) ? nullptr : FSN;
1268 }
1269 
1271 Demangler::demangleStringLiteral(StringView &MangledName) {
1272  // This function uses goto, so declare all variables up front.
1273  OutputBuffer OB;
1274  StringView CRC;
1275  uint64_t StringByteSize;
1276  bool IsWcharT = false;
1277  bool IsNegative = false;
1278  size_t CrcEndPos = 0;
1279 
1281 
1282  // Must happen before the first `goto StringLiteralError`.
1283  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1284  // FIXME: Propagate out-of-memory as an error?
1285  std::terminate();
1286 
1287  // Prefix indicating the beginning of a string literal
1288  if (!MangledName.consumeFront("@_"))
1289  goto StringLiteralError;
1290  if (MangledName.empty())
1291  goto StringLiteralError;
1292 
1293  // Char Type (regular or wchar_t)
1294  switch (MangledName.popFront()) {
1295  case '1':
1296  IsWcharT = true;
1298  case '0':
1299  break;
1300  default:
1301  goto StringLiteralError;
1302  }
1303 
1304  // Encoded Length
1305  std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
1306  if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
1307  goto StringLiteralError;
1308 
1309  // CRC 32 (always 8 characters plus a terminator)
1310  CrcEndPos = MangledName.find('@');
1311  if (CrcEndPos == StringView::npos)
1312  goto StringLiteralError;
1313  CRC = MangledName.substr(0, CrcEndPos);
1314  MangledName = MangledName.dropFront(CrcEndPos + 1);
1315  if (MangledName.empty())
1316  goto StringLiteralError;
1317 
1318  if (IsWcharT) {
1319  Result->Char = CharKind::Wchar;
1320  if (StringByteSize > 64)
1321  Result->IsTruncated = true;
1322 
1323  while (!MangledName.consumeFront('@')) {
1324  if (MangledName.size() < 2)
1325  goto StringLiteralError;
1326  wchar_t W = demangleWcharLiteral(MangledName);
1327  if (StringByteSize != 2 || Result->IsTruncated)
1329  StringByteSize -= 2;
1330  if (Error)
1331  goto StringLiteralError;
1332  }
1333  } else {
1334  // The max byte length is actually 32, but some compilers mangled strings
1335  // incorrectly, so we have to assume it can go higher.
1336  constexpr unsigned MaxStringByteLength = 32 * 4;
1337  uint8_t StringBytes[MaxStringByteLength];
1338 
1339  unsigned BytesDecoded = 0;
1340  while (!MangledName.consumeFront('@')) {
1341  if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
1342  goto StringLiteralError;
1343  StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
1344  }
1345 
1346  if (StringByteSize > BytesDecoded)
1347  Result->IsTruncated = true;
1348 
1349  unsigned CharBytes =
1350  guessCharByteSize(StringBytes, BytesDecoded, StringByteSize);
1351  assert(StringByteSize % CharBytes == 0);
1352  switch (CharBytes) {
1353  case 1:
1354  Result->Char = CharKind::Char;
1355  break;
1356  case 2:
1357  Result->Char = CharKind::Char16;
1358  break;
1359  case 4:
1360  Result->Char = CharKind::Char32;
1361  break;
1362  default:
1364  }
1365  const unsigned NumChars = BytesDecoded / CharBytes;
1366  for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
1367  unsigned NextChar =
1368  decodeMultiByteChar(StringBytes, CharIndex, CharBytes);
1369  if (CharIndex + 1 < NumChars || Result->IsTruncated)
1370  outputEscapedChar(OB, NextChar);
1371  }
1372  }
1373 
1374  Result->DecodedString = copyString(OB);
1375  std::free(OB.getBuffer());
1376  return Result;
1377 
1378 StringLiteralError:
1379  Error = true;
1380  std::free(OB.getBuffer());
1381  return nullptr;
1382 }
1383 
1384 // Returns MangledName's prefix before the first '@', or an error if
1385 // MangledName contains no '@' or the prefix has length 0.
1386 StringView Demangler::demangleSimpleString(StringView &MangledName,
1387  bool Memorize) {
1388  StringView S;
1389  for (size_t i = 0; i < MangledName.size(); ++i) {
1390  if (MangledName[i] != '@')
1391  continue;
1392  if (i == 0)
1393  break;
1394  S = MangledName.substr(0, i);
1395  MangledName = MangledName.dropFront(i + 1);
1396 
1397  if (Memorize)
1398  memorizeString(S);
1399  return S;
1400  }
1401 
1402  Error = true;
1403  return {};
1404 }
1405 
1407 Demangler::demangleAnonymousNamespaceName(StringView &MangledName) {
1408  assert(MangledName.startsWith("?A"));
1409  MangledName.consumeFront("?A");
1410 
1412  Node->Name = "`anonymous namespace'";
1413  size_t EndPos = MangledName.find('@');
1414  if (EndPos == StringView::npos) {
1415  Error = true;
1416  return nullptr;
1417  }
1418  StringView NamespaceKey = MangledName.substr(0, EndPos);
1419  memorizeString(NamespaceKey);
1420  MangledName = MangledName.substr(EndPos + 1);
1421  return Node;
1422 }
1423 
1425 Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
1426  assert(startsWithLocalScopePattern(MangledName));
1427 
1429  MangledName.consumeFront('?');
1430  uint64_t Number = 0;
1431  bool IsNegative = false;
1432  std::tie(Number, IsNegative) = demangleNumber(MangledName);
1433  assert(!IsNegative);
1434 
1435  // One ? to terminate the number
1436  MangledName.consumeFront('?');
1437 
1438  assert(!Error);
1439  Node *Scope = parse(MangledName);
1440  if (Error)
1441  return nullptr;
1442 
1443  // Render the parent symbol's name into a buffer.
1444  OutputBuffer OB;
1445  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1446  // FIXME: Propagate out-of-memory as an error?
1447  std::terminate();
1448  OB << '`';
1449  Scope->output(OB, OF_Default);
1450  OB << '\'';
1451  OB << "::`" << Number << "'";
1452 
1453  Identifier->Name = copyString(OB);
1454  std::free(OB.getBuffer());
1455  return Identifier;
1456 }
1457 
1458 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
1460 Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
1462  demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
1463  if (Error)
1464  return nullptr;
1465  assert(Identifier);
1466 
1467  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1468  if (Error)
1469  return nullptr;
1470  assert(QN);
1471  return QN;
1472 }
1473 
1474 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1475 // Symbol names have slightly different rules regarding what can appear
1476 // so we separate out the implementations for flexibility.
1478 Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
1479  // This is the final component of a symbol name (i.e. the leftmost component
1480  // of a mangled name. Since the only possible template instantiation that
1481  // can appear in this context is a function template, and since those are
1482  // not saved for the purposes of name backreferences, only backref simple
1483  // names.
1485  demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
1486  if (Error)
1487  return nullptr;
1488 
1489  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1490  if (Error)
1491  return nullptr;
1492 
1493  if (Identifier->kind() == NodeKind::StructorIdentifier) {
1494  if (QN->Components->Count < 2) {
1495  Error = true;
1496  return nullptr;
1497  }
1498  StructorIdentifierNode *SIN =
1499  static_cast<StructorIdentifierNode *>(Identifier);
1500  Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2];
1501  SIN->Class = static_cast<IdentifierNode *>(ClassNode);
1502  }
1503  assert(QN);
1504  return QN;
1505 }
1506 
1507 IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
1508  bool Memorize) {
1509  // An inner-most name can be a back-reference, because a fully-qualified name
1510  // (e.g. Scope + Inner) can contain other fully qualified names inside of
1511  // them (for example template parameters), and these nested parameters can
1512  // refer to previously mangled types.
1513  if (startsWithDigit(MangledName))
1514  return demangleBackRefName(MangledName);
1515 
1516  if (MangledName.startsWith("?$"))
1517  return demangleTemplateInstantiationName(MangledName, NBB_Template);
1518 
1519  return demangleSimpleName(MangledName, Memorize);
1520 }
1521 
1523 Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
1524  NameBackrefBehavior NBB) {
1525  if (startsWithDigit(MangledName))
1526  return demangleBackRefName(MangledName);
1527  if (MangledName.startsWith("?$"))
1528  return demangleTemplateInstantiationName(MangledName, NBB);
1529  if (MangledName.startsWith('?'))
1530  return demangleFunctionIdentifierCode(MangledName);
1531  return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0);
1532 }
1533 
1534 IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) {
1535  if (startsWithDigit(MangledName))
1536  return demangleBackRefName(MangledName);
1537 
1538  if (MangledName.startsWith("?$"))
1539  return demangleTemplateInstantiationName(MangledName, NBB_Template);
1540 
1541  if (MangledName.startsWith("?A"))
1542  return demangleAnonymousNamespaceName(MangledName);
1543 
1544  if (startsWithLocalScopePattern(MangledName))
1545  return demangleLocallyScopedNamePiece(MangledName);
1546 
1547  return demangleSimpleName(MangledName, /*Memorize=*/true);
1548 }
1549 
1551  size_t Count) {
1552  NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
1553  N->Count = Count;
1554  N->Nodes = Arena.allocArray<Node *>(Count);
1555  for (size_t I = 0; I < Count; ++I) {
1556  N->Nodes[I] = Head->N;
1557  Head = Head->Next;
1558  }
1559  return N;
1560 }
1561 
1563 Demangler::demangleNameScopeChain(StringView &MangledName,
1564  IdentifierNode *UnqualifiedName) {
1565  NodeList *Head = Arena.alloc<NodeList>();
1566 
1567  Head->N = UnqualifiedName;
1568 
1569  size_t Count = 1;
1570  while (!MangledName.consumeFront("@")) {
1571  ++Count;
1572  NodeList *NewHead = Arena.alloc<NodeList>();
1573  NewHead->Next = Head;
1574  Head = NewHead;
1575 
1576  if (MangledName.empty()) {
1577  Error = true;
1578  return nullptr;
1579  }
1580 
1581  assert(!Error);
1582  IdentifierNode *Elem = demangleNameScopePiece(MangledName);
1583  if (Error)
1584  return nullptr;
1585 
1586  Head->N = Elem;
1587  }
1588 
1589  QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
1590  QN->Components = nodeListToNodeArray(Arena, Head, Count);
1591  return QN;
1592 }
1593 
1594 FuncClass Demangler::demangleFunctionClass(StringView &MangledName) {
1595  switch (MangledName.popFront()) {
1596  case '9':
1598  case 'A':
1599  return FC_Private;
1600  case 'B':
1601  return FuncClass(FC_Private | FC_Far);
1602  case 'C':
1603  return FuncClass(FC_Private | FC_Static);
1604  case 'D':
1605  return FuncClass(FC_Private | FC_Static | FC_Far);
1606  case 'E':
1607  return FuncClass(FC_Private | FC_Virtual);
1608  case 'F':
1609  return FuncClass(FC_Private | FC_Virtual | FC_Far);
1610  case 'G':
1612  case 'H':
1614  case 'I':
1615  return FuncClass(FC_Protected);
1616  case 'J':
1617  return FuncClass(FC_Protected | FC_Far);
1618  case 'K':
1619  return FuncClass(FC_Protected | FC_Static);
1620  case 'L':
1621  return FuncClass(FC_Protected | FC_Static | FC_Far);
1622  case 'M':
1623  return FuncClass(FC_Protected | FC_Virtual);
1624  case 'N':
1626  case 'O':
1628  case 'P':
1630  case 'Q':
1631  return FuncClass(FC_Public);
1632  case 'R':
1633  return FuncClass(FC_Public | FC_Far);
1634  case 'S':
1635  return FuncClass(FC_Public | FC_Static);
1636  case 'T':
1637  return FuncClass(FC_Public | FC_Static | FC_Far);
1638  case 'U':
1639  return FuncClass(FC_Public | FC_Virtual);
1640  case 'V':
1641  return FuncClass(FC_Public | FC_Virtual | FC_Far);
1642  case 'W':
1644  case 'X':
1646  case 'Y':
1647  return FuncClass(FC_Global);
1648  case 'Z':
1649  return FuncClass(FC_Global | FC_Far);
1650  case '$': {
1652  if (MangledName.consumeFront('R'))
1653  VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx);
1654  if (MangledName.empty())
1655  break;
1656  switch (MangledName.popFront()) {
1657  case '0':
1658  return FuncClass(FC_Private | FC_Virtual | VFlag);
1659  case '1':
1660  return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far);
1661  case '2':
1662  return FuncClass(FC_Protected | FC_Virtual | VFlag);
1663  case '3':
1664  return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far);
1665  case '4':
1666  return FuncClass(FC_Public | FC_Virtual | VFlag);
1667  case '5':
1668  return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far);
1669  }
1670  }
1671  }
1672 
1673  Error = true;
1674  return FC_Public;
1675 }
1676 
1677 CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
1678  if (MangledName.empty()) {
1679  Error = true;
1680  return CallingConv::None;
1681  }
1682 
1683  switch (MangledName.popFront()) {
1684  case 'A':
1685  case 'B':
1686  return CallingConv::Cdecl;
1687  case 'C':
1688  case 'D':
1689  return CallingConv::Pascal;
1690  case 'E':
1691  case 'F':
1692  return CallingConv::Thiscall;
1693  case 'G':
1694  case 'H':
1695  return CallingConv::Stdcall;
1696  case 'I':
1697  case 'J':
1698  return CallingConv::Fastcall;
1699  case 'M':
1700  case 'N':
1701  return CallingConv::Clrcall;
1702  case 'O':
1703  case 'P':
1704  return CallingConv::Eabi;
1705  case 'Q':
1706  return CallingConv::Vectorcall;
1707  case 'S':
1708  return CallingConv::Swift;
1709  case 'W':
1710  return CallingConv::SwiftAsync;
1711  }
1712 
1713  return CallingConv::None;
1714 }
1715 
1716 StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) {
1717  assert(MangledName.front() >= '0' && MangledName.front() <= '4');
1718 
1719  switch (MangledName.popFront()) {
1720  case '0':
1721  return StorageClass::PrivateStatic;
1722  case '1':
1723  return StorageClass::ProtectedStatic;
1724  case '2':
1725  return StorageClass::PublicStatic;
1726  case '3':
1727  return StorageClass::Global;
1728  case '4':
1729  return StorageClass::FunctionLocalStatic;
1730  }
1732 }
1733 
1734 std::pair<Qualifiers, bool>
1735 Demangler::demangleQualifiers(StringView &MangledName) {
1736  if (MangledName.empty()) {
1737  Error = true;
1738  return std::make_pair(Q_None, false);
1739  }
1740 
1741  switch (MangledName.popFront()) {
1742  // Member qualifiers
1743  case 'Q':
1744  return std::make_pair(Q_None, true);
1745  case 'R':
1746  return std::make_pair(Q_Const, true);
1747  case 'S':
1748  return std::make_pair(Q_Volatile, true);
1749  case 'T':
1750  return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true);
1751  // Non-Member qualifiers
1752  case 'A':
1753  return std::make_pair(Q_None, false);
1754  case 'B':
1755  return std::make_pair(Q_Const, false);
1756  case 'C':
1757  return std::make_pair(Q_Volatile, false);
1758  case 'D':
1759  return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false);
1760  }
1761  Error = true;
1762  return std::make_pair(Q_None, false);
1763 }
1764 
1765 // <variable-type> ::= <type> <cvr-qualifiers>
1766 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
1767 TypeNode *Demangler::demangleType(StringView &MangledName,
1768  QualifierMangleMode QMM) {
1769  Qualifiers Quals = Q_None;
1770  bool IsMember = false;
1771  if (QMM == QualifierMangleMode::Mangle) {
1772  std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1773  } else if (QMM == QualifierMangleMode::Result) {
1774  if (MangledName.consumeFront('?'))
1775  std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1776  }
1777 
1778  if (MangledName.empty()) {
1779  Error = true;
1780  return nullptr;
1781  }
1782 
1783  TypeNode *Ty = nullptr;
1784  if (isTagType(MangledName))
1785  Ty = demangleClassType(MangledName);
1786  else if (isPointerType(MangledName)) {
1787  if (isMemberPointer(MangledName, Error))
1788  Ty = demangleMemberPointerType(MangledName);
1789  else if (!Error)
1790  Ty = demanglePointerType(MangledName);
1791  else
1792  return nullptr;
1793  } else if (isArrayType(MangledName))
1794  Ty = demangleArrayType(MangledName);
1795  else if (isFunctionType(MangledName)) {
1796  if (MangledName.consumeFront("$$A8@@"))
1797  Ty = demangleFunctionType(MangledName, true);
1798  else {
1799  assert(MangledName.startsWith("$$A6"));
1800  MangledName.consumeFront("$$A6");
1801  Ty = demangleFunctionType(MangledName, false);
1802  }
1803  } else if (isCustomType(MangledName)) {
1804  Ty = demangleCustomType(MangledName);
1805  } else {
1806  Ty = demanglePrimitiveType(MangledName);
1807  }
1808 
1809  if (!Ty || Error)
1810  return Ty;
1811  Ty->Quals = Qualifiers(Ty->Quals | Quals);
1812  return Ty;
1813 }
1814 
1815 bool Demangler::demangleThrowSpecification(StringView &MangledName) {
1816  if (MangledName.consumeFront("_E"))
1817  return true;
1818  if (MangledName.consumeFront('Z'))
1819  return false;
1820 
1821  Error = true;
1822  return false;
1823 }
1824 
1825 FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName,
1826  bool HasThisQuals) {
1828 
1829  if (HasThisQuals) {
1830  FTy->Quals = demanglePointerExtQualifiers(MangledName);
1831  FTy->RefQualifier = demangleFunctionRefQualifier(MangledName);
1832  FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
1833  }
1834 
1835  // Fields that appear on both member and non-member functions.
1836  FTy->CallConvention = demangleCallingConvention(MangledName);
1837 
1838  // <return-type> ::= <type>
1839  // ::= @ # structors (they have no declared return type)
1840  bool IsStructor = MangledName.consumeFront('@');
1841  if (!IsStructor)
1842  FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
1843 
1844  FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
1845 
1846  FTy->IsNoexcept = demangleThrowSpecification(MangledName);
1847 
1848  return FTy;
1849 }
1850 
1852 Demangler::demangleFunctionEncoding(StringView &MangledName) {
1853  FuncClass ExtraFlags = FC_None;
1854  if (MangledName.consumeFront("$$J0"))
1855  ExtraFlags = FC_ExternC;
1856 
1857  if (MangledName.empty()) {
1858  Error = true;
1859  return nullptr;
1860  }
1861 
1862  FuncClass FC = demangleFunctionClass(MangledName);
1863  FC = FuncClass(ExtraFlags | FC);
1864 
1865  FunctionSignatureNode *FSN = nullptr;
1866  ThunkSignatureNode *TTN = nullptr;
1867  if (FC & FC_StaticThisAdjust) {
1868  TTN = Arena.alloc<ThunkSignatureNode>();
1869  TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
1870  } else if (FC & FC_VirtualThisAdjust) {
1871  TTN = Arena.alloc<ThunkSignatureNode>();
1872  if (FC & FC_VirtualThisAdjustEx) {
1873  TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName);
1874  TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName);
1875  }
1876  TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName);
1877  TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
1878  }
1879 
1880  if (FC & FC_NoParameterList) {
1881  // This is an extern "C" function whose full signature hasn't been mangled.
1882  // This happens when we need to mangle a local symbol inside of an extern
1883  // "C" function.
1884  FSN = Arena.alloc<FunctionSignatureNode>();
1885  } else {
1886  bool HasThisQuals = !(FC & (FC_Global | FC_Static));
1887  FSN = demangleFunctionType(MangledName, HasThisQuals);
1888  }
1889 
1890  if (Error)
1891  return nullptr;
1892 
1893  if (TTN) {
1894  *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
1895  FSN = TTN;
1896  }
1897  FSN->FunctionClass = FC;
1898 
1900  Symbol->Signature = FSN;
1901  return Symbol;
1902 }
1903 
1904 CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) {
1905  assert(MangledName.startsWith('?'));
1906  MangledName.popFront();
1907 
1908  CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
1909  CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
1910  if (!MangledName.consumeFront('@'))
1911  Error = true;
1912  if (Error)
1913  return nullptr;
1914  return CTN;
1915 }
1916 
1917 // Reads a primitive type.
1918 PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) {
1919  if (MangledName.consumeFront("$$T"))
1920  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr);
1921 
1922  switch (MangledName.popFront()) {
1923  case 'X':
1924  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void);
1925  case 'D':
1926  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char);
1927  case 'C':
1928  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar);
1929  case 'E':
1930  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar);
1931  case 'F':
1932  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short);
1933  case 'G':
1934  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort);
1935  case 'H':
1936  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int);
1937  case 'I':
1938  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint);
1939  case 'J':
1940  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long);
1941  case 'K':
1942  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong);
1943  case 'M':
1945  case 'N':
1947  case 'O':
1948  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble);
1949  case '_': {
1950  if (MangledName.empty()) {
1951  Error = true;
1952  return nullptr;
1953  }
1954  switch (MangledName.popFront()) {
1955  case 'N':
1957  case 'J':
1959  case 'K':
1960  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64);
1961  case 'W':
1962  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar);
1963  case 'Q':
1964  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8);
1965  case 'S':
1966  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16);
1967  case 'U':
1968  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32);
1969  }
1970  break;
1971  }
1972  }
1973  Error = true;
1974  return nullptr;
1975 }
1976 
1977 TagTypeNode *Demangler::demangleClassType(StringView &MangledName) {
1978  TagTypeNode *TT = nullptr;
1979 
1980  switch (MangledName.popFront()) {
1981  case 'T':
1982  TT = Arena.alloc<TagTypeNode>(TagKind::Union);
1983  break;
1984  case 'U':
1985  TT = Arena.alloc<TagTypeNode>(TagKind::Struct);
1986  break;
1987  case 'V':
1988  TT = Arena.alloc<TagTypeNode>(TagKind::Class);
1989  break;
1990  case 'W':
1991  if (!MangledName.consumeFront('4')) {
1992  Error = true;
1993  return nullptr;
1994  }
1995  TT = Arena.alloc<TagTypeNode>(TagKind::Enum);
1996  break;
1997  default:
1998  assert(false);
1999  }
2000 
2001  TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName);
2002  return TT;
2003 }
2004 
2005 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
2006 // # the E is required for 64-bit non-static pointers
2007 PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) {
2009 
2010  std::tie(Pointer->Quals, Pointer->Affinity) =
2011  demanglePointerCVQualifiers(MangledName);
2012 
2013  if (MangledName.consumeFront("6")) {
2014  Pointer->Pointee = demangleFunctionType(MangledName, false);
2015  return Pointer;
2016  }
2017 
2018  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2019  Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2020 
2021  Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
2022  return Pointer;
2023 }
2024 
2025 PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) {
2027 
2028  std::tie(Pointer->Quals, Pointer->Affinity) =
2029  demanglePointerCVQualifiers(MangledName);
2030  assert(Pointer->Affinity == PointerAffinity::Pointer);
2031 
2032  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2033  Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2034 
2035  // isMemberPointer() only returns true if there is at least one character
2036  // after the qualifiers.
2037  if (MangledName.consumeFront("8")) {
2038  Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2039  Pointer->Pointee = demangleFunctionType(MangledName, true);
2040  } else {
2041  Qualifiers PointeeQuals = Q_None;
2042  bool IsMember = false;
2043  std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
2044  assert(IsMember || Error);
2045  Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2046 
2047  Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
2048  if (Pointer->Pointee)
2049  Pointer->Pointee->Quals = PointeeQuals;
2050  }
2051 
2052  return Pointer;
2053 }
2054 
2055 Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) {
2056  Qualifiers Quals = Q_None;
2057  if (MangledName.consumeFront('E'))
2058  Quals = Qualifiers(Quals | Q_Pointer64);
2059  if (MangledName.consumeFront('I'))
2060  Quals = Qualifiers(Quals | Q_Restrict);
2061  if (MangledName.consumeFront('F'))
2062  Quals = Qualifiers(Quals | Q_Unaligned);
2063 
2064  return Quals;
2065 }
2066 
2067 ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) {
2068  assert(MangledName.front() == 'Y');
2069  MangledName.popFront();
2070 
2071  uint64_t Rank = 0;
2072  bool IsNegative = false;
2073  std::tie(Rank, IsNegative) = demangleNumber(MangledName);
2074  if (IsNegative || Rank == 0) {
2075  Error = true;
2076  return nullptr;
2077  }
2078 
2079  ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>();
2080  NodeList *Head = Arena.alloc<NodeList>();
2081  NodeList *Tail = Head;
2082 
2083  for (uint64_t I = 0; I < Rank; ++I) {
2084  uint64_t D = 0;
2085  std::tie(D, IsNegative) = demangleNumber(MangledName);
2086  if (Error || IsNegative) {
2087  Error = true;
2088  return nullptr;
2089  }
2090  Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative);
2091  if (I + 1 < Rank) {
2092  Tail->Next = Arena.alloc<NodeList>();
2093  Tail = Tail->Next;
2094  }
2095  }
2096  ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank);
2097 
2098  if (MangledName.consumeFront("$$C")) {
2099  bool IsMember = false;
2100  std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName);
2101  if (IsMember) {
2102  Error = true;
2103  return nullptr;
2104  }
2105  }
2106 
2107  ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
2108  return ATy;
2109 }
2110 
2111 // Reads a function's parameters.
2112 NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName,
2113  bool &IsVariadic) {
2114  // Empty parameter list.
2115  if (MangledName.consumeFront('X'))
2116  return nullptr;
2117 
2118  NodeList *Head = Arena.alloc<NodeList>();
2119  NodeList **Current = &Head;
2120  size_t Count = 0;
2121  while (!Error && !MangledName.startsWith('@') &&
2122  !MangledName.startsWith('Z')) {
2123  ++Count;
2124 
2125  if (startsWithDigit(MangledName)) {
2126  size_t N = MangledName[0] - '0';
2127  if (N >= Backrefs.FunctionParamCount) {
2128  Error = true;
2129  return nullptr;
2130  }
2131  MangledName = MangledName.dropFront();
2132 
2133  *Current = Arena.alloc<NodeList>();
2134  (*Current)->N = Backrefs.FunctionParams[N];
2135  Current = &(*Current)->Next;
2136  continue;
2137  }
2138 
2139  size_t OldSize = MangledName.size();
2140 
2141  *Current = Arena.alloc<NodeList>();
2142  TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop);
2143  if (!TN || Error)
2144  return nullptr;
2145 
2146  (*Current)->N = TN;
2147 
2148  size_t CharsConsumed = OldSize - MangledName.size();
2149  assert(CharsConsumed != 0);
2150 
2151  // Single-letter types are ignored for backreferences because memorizing
2152  // them doesn't save anything.
2153  if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1)
2154  Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN;
2155 
2156  Current = &(*Current)->Next;
2157  }
2158 
2159  if (Error)
2160  return nullptr;
2161 
2162  NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count);
2163  // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
2164  // list or '@' (non variadic). Careful not to consume "@Z", as in that case
2165  // the following Z could be a throw specifier.
2166  if (MangledName.consumeFront('@'))
2167  return NA;
2168 
2169  if (MangledName.consumeFront('Z')) {
2170  IsVariadic = true;
2171  return NA;
2172  }
2173 
2175 }
2176 
2177 NodeArrayNode *
2178 Demangler::demangleTemplateParameterList(StringView &MangledName) {
2179  NodeList *Head = nullptr;
2180  NodeList **Current = &Head;
2181  size_t Count = 0;
2182 
2183  while (!MangledName.startsWith('@')) {
2184  if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
2185  MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) {
2186  // parameter pack separator
2187  continue;
2188  }
2189 
2190  ++Count;
2191 
2192  // Template parameter lists don't participate in back-referencing.
2193  *Current = Arena.alloc<NodeList>();
2194 
2195  NodeList &TP = **Current;
2196 
2197  TemplateParameterReferenceNode *TPRN = nullptr;
2198  if (MangledName.consumeFront("$$Y")) {
2199  // Template alias
2200  TP.N = demangleFullyQualifiedTypeName(MangledName);
2201  } else if (MangledName.consumeFront("$$B")) {
2202  // Array
2203  TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2204  } else if (MangledName.consumeFront("$$C")) {
2205  // Type has qualifiers.
2206  TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
2207  } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") ||
2208  MangledName.startsWith("$I") || MangledName.startsWith("$J")) {
2209  // Pointer to member
2210  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2211  TPRN->IsMemberPointer = true;
2212 
2213  MangledName = MangledName.dropFront();
2214  // 1 - single inheritance <name>
2215  // H - multiple inheritance <name> <number>
2216  // I - virtual inheritance <name> <number> <number>
2217  // J - unspecified inheritance <name> <number> <number> <number>
2218  char InheritanceSpecifier = MangledName.popFront();
2219  SymbolNode *S = nullptr;
2220  if (MangledName.startsWith('?')) {
2221  S = parse(MangledName);
2222  if (Error || !S->Name) {
2223  Error = true;
2224  return nullptr;
2225  }
2226  memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
2227  }
2228 
2229  switch (InheritanceSpecifier) {
2230  case 'J':
2231  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2232  demangleSigned(MangledName);
2234  case 'I':
2235  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2236  demangleSigned(MangledName);
2238  case 'H':
2239  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2240  demangleSigned(MangledName);
2242  case '1':
2243  break;
2244  default:
2246  }
2247  TPRN->Affinity = PointerAffinity::Pointer;
2248  TPRN->Symbol = S;
2249  } else if (MangledName.startsWith("$E?")) {
2250  MangledName.consumeFront("$E");
2251  // Reference to symbol
2252  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2253  TPRN->Symbol = parse(MangledName);
2254  TPRN->Affinity = PointerAffinity::Reference;
2255  } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) {
2256  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2257 
2258  // Data member pointer.
2259  MangledName = MangledName.dropFront();
2260  char InheritanceSpecifier = MangledName.popFront();
2261 
2262  switch (InheritanceSpecifier) {
2263  case 'G':
2264  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2265  demangleSigned(MangledName);
2267  case 'F':
2268  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2269  demangleSigned(MangledName);
2270  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2271  demangleSigned(MangledName);
2272  break;
2273  default:
2275  }
2276  TPRN->IsMemberPointer = true;
2277 
2278  } else if (MangledName.consumeFront("$0")) {
2279  // Integral non-type template parameter
2280  bool IsNegative = false;
2281  uint64_t Value = 0;
2282  std::tie(Value, IsNegative) = demangleNumber(MangledName);
2283 
2284  TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative);
2285  } else {
2286  TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2287  }
2288  if (Error)
2289  return nullptr;
2290 
2291  Current = &TP.Next;
2292  }
2293 
2294  // The loop above returns nullptr on Error.
2295  assert(!Error);
2296 
2297  // Template parameter lists cannot be variadic, so it can only be terminated
2298  // by @ (as opposed to 'Z' in the function parameter case).
2299  assert(MangledName.startsWith('@')); // The above loop exits only on '@'.
2300  MangledName.consumeFront('@');
2301  return nodeListToNodeArray(Arena, Head, Count);
2302 }
2303 
2304 void Demangler::dumpBackReferences() {
2305  std::printf("%d function parameter backreferences\n",
2306  (int)Backrefs.FunctionParamCount);
2307 
2308  // Create an output stream so we can render each type.
2309  OutputBuffer OB;
2310  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
2311  std::terminate();
2312  for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
2313  OB.setCurrentPosition(0);
2314 
2315  TypeNode *T = Backrefs.FunctionParams[I];
2316  T->output(OB, OF_Default);
2317 
2318  StringView B = OB;
2319  std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.begin());
2320  }
2321  std::free(OB.getBuffer());
2322 
2323  if (Backrefs.FunctionParamCount > 0)
2324  std::printf("\n");
2325  std::printf("%d name backreferences\n", (int)Backrefs.NamesCount);
2326  for (size_t I = 0; I < Backrefs.NamesCount; ++I) {
2327  std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(),
2328  Backrefs.Names[I]->Name.begin());
2329  }
2330  if (Backrefs.NamesCount > 0)
2331  std::printf("\n");
2332 }
2333 
2334 char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
2335  char *Buf, size_t *N,
2336  int *Status, MSDemangleFlags Flags) {
2337  Demangler D;
2338  OutputBuffer OB;
2339 
2340  StringView Name{MangledName};
2341  SymbolNode *AST = D.parse(Name);
2342  if (!D.Error && NMangled)
2343  *NMangled = Name.begin() - MangledName;
2344 
2345  if (Flags & MSDF_DumpBackrefs)
2346  D.dumpBackReferences();
2347 
2348  OutputFlags OF = OF_Default;
2349  if (Flags & MSDF_NoCallingConvention)
2351  if (Flags & MSDF_NoAccessSpecifier)
2352  OF = OutputFlags(OF | OF_NoAccessSpecifier);
2353  if (Flags & MSDF_NoReturnType)
2354  OF = OutputFlags(OF | OF_NoReturnType);
2355  if (Flags & MSDF_NoMemberType)
2356  OF = OutputFlags(OF | OF_NoMemberType);
2357  if (Flags & MSDF_NoVariableType)
2358  OF = OutputFlags(OF | OF_NoVariableType);
2359 
2360  int InternalStatus = demangle_success;
2361  if (D.Error)
2362  InternalStatus = demangle_invalid_mangled_name;
2363  else if (!initializeOutputBuffer(Buf, N, OB, 1024))
2364  InternalStatus = demangle_memory_alloc_failure;
2365  else {
2366  AST->output(OB, OF);
2367  OB += '\0';
2368  if (N != nullptr)
2369  *N = OB.getCurrentPosition();
2370  Buf = OB.getBuffer();
2371  }
2372 
2373  if (Status)
2374  *Status = InternalStatus;
2375  return InternalStatus == demangle_success ? Buf : nullptr;
2376 }
llvm::ms_demangle::DynamicStructorIdentifierNode
Definition: MicrosoftDemangleNodes.h:371
isArrayType
static bool isArrayType(StringView S)
Definition: MicrosoftDemangle.cpp:209
synthesizeQualifiedName
static QualifiedNameNode * synthesizeQualifiedName(ArenaAllocator &Arena, IdentifierNode *Identifier)
Definition: MicrosoftDemangle.cpp:325
llvm::ms_demangle::FunctionSignatureNode::FunctionClass
FuncClass FunctionClass
Definition: MicrosoftDemangleNodes.h:337
i
i
Definition: README.txt:29
consumeSpecialIntrinsicKind
static SpecialIntrinsicKind consumeSpecialIntrinsicKind(StringView &MangledName)
Definition: MicrosoftDemangle.cpp:106
llvm::X86II::OB
@ OB
Definition: X86BaseInfo.h:801
llvm::ms_demangle::DynamicStructorIdentifierNode::Name
QualifiedNameNode * Name
Definition: MicrosoftDemangleNodes.h:378
llvm::ms_demangle::ArenaAllocator::allocUnalignedBuffer
char * allocUnalignedBuffer(size_t Size)
Definition: MicrosoftDemangle.h:56
llvm::ms_demangle::FunctionRefQualifier::Reference
@ Reference
llvm::ms_demangle::NameBackrefBehavior
NameBackrefBehavior
Definition: MicrosoftDemangle.h:127
llvm::ms_demangle::SpecialIntrinsicKind::DynamicInitializer
@ DynamicInitializer
llvm::ms_demangle::NodeArrayNode::Nodes
Node ** Nodes
Definition: MicrosoftDemangleNodes.h:521
llvm::ms_demangle::FC_Private
@ FC_Private
Definition: MicrosoftDemangleNodes.h:212
llvm::ms_demangle::OF_Default
@ OF_Default
Definition: MicrosoftDemangleNodes.h:76
llvm::ms_demangle::ArrayTypeNode
Definition: MicrosoftDemangleNodes.h:484
llvm::ms_demangle::Node
Definition: MicrosoftDemangleNodes.h:258
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::ms_demangle::SpecialIntrinsicKind::Vbtable
@ Vbtable
llvm::ms_demangle::SpecialIntrinsicKind::RttiClassHierarchyDescriptor
@ RttiClassHierarchyDescriptor
llvm::ms_demangle::TemplateParameterReferenceNode::Symbol
SymbolNode * Symbol
Definition: MicrosoftDemangleNodes.h:544
llvm::ms_demangle::IntegerLiteralNode
Definition: MicrosoftDemangleNodes.h:552
llvm::ARM::PredBlockMask::TT
@ TT
llvm::ms_demangle::TemplateParameterReferenceNode::Affinity
PointerAffinity Affinity
Definition: MicrosoftDemangleNodes.h:548
llvm::ms_demangle::CustomTypeNode
Definition: MicrosoftDemangleNodes.h:505
isMemberPointer
static bool isMemberPointer(StringView MangledName, bool &Error)
Definition: MicrosoftDemangle.cpp:42
llvm::ms_demangle::QualifiedNameNode::Components
NodeArrayNode * Components
Definition: MicrosoftDemangleNodes.h:530
llvm::ms_demangle::SpecialIntrinsicKind::LocalVftable
@ LocalVftable
demanglePointerCVQualifiers
static std::pair< Qualifiers, PointerAffinity > demanglePointerCVQualifiers(StringView &MangledName)
Definition: MicrosoftDemangle.cpp:225
llvm::ms_demangle::SpecialTableSymbolNode::TargetName
QualifiedNameNode * TargetName
Definition: MicrosoftDemangleNodes.h:586
llvm::MSDF_NoAccessSpecifier
@ MSDF_NoAccessSpecifier
Definition: Demangle.h:37
T
writeHexDigit
static void writeHexDigit(char *Buffer, uint8_t Digit)
Definition: MicrosoftDemangle.cpp:1102
llvm::pdb::Int64
@ Int64
Definition: PDBTypes.h:400
llvm::ms_demangle::ThunkSignatureNode::ThisAdjustor::VBPtrOffset
int32_t VBPtrOffset
Definition: MicrosoftDemangleNodes.h:450
llvm::ms_demangle::PointerAffinity::Pointer
@ Pointer
llvm::ms_demangle::TemplateParameterReferenceNode::IsMemberPointer
bool IsMemberPointer
Definition: MicrosoftDemangleNodes.h:549
C1
instcombine should handle this C2 when C1
Definition: README.txt:263
llvm::ms_demangle::FunctionIdentifierCodeGroup
FunctionIdentifierCodeGroup
Definition: MicrosoftDemangle.h:133
decodeMultiByteChar
static unsigned decodeMultiByteChar(const uint8_t *StringBytes, unsigned CharIndex, unsigned CharBytes)
Definition: MicrosoftDemangle.cpp:1239
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:241
CH
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference CH
Definition: README-X86-64.txt:44
llvm::ms_demangle::Q_Restrict
@ Q_Restrict
Definition: MicrosoftDemangleNodes.h:41
R600_InstFlag::FC
@ FC
Definition: R600Defines.h:32
llvm::ms_demangle::FunctionSignatureNode
Definition: MicrosoftDemangleNodes.h:322
llvm::ms_demangle::FunctionSymbolNode::Signature
FunctionSignatureNode * Signature
Definition: MicrosoftDemangleNodes.h:623
llvm::ms_demangle::SpecialTableSymbolNode::Quals
Qualifiers Quals
Definition: MicrosoftDemangleNodes.h:587
llvm::ms_demangle::Q_Unaligned
@ Q_Unaligned
Definition: MicrosoftDemangleNodes.h:40
rebasedHexDigitToNumber
static uint8_t rebasedHexDigitToNumber(char C)
Definition: MicrosoftDemangle.cpp:1025
llvm::ms_demangle::IntrinsicFunctionIdentifierNode
Definition: MicrosoftDemangleNodes.h:390
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Utility.h
llvm::CallingConv::Tail
@ Tail
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
Definition: CallingConv.h:81
llvm::ms_demangle::DynamicStructorIdentifierNode::Variable
VariableSymbolNode * Variable
Definition: MicrosoftDemangleNodes.h:377
llvm::ms_demangle::ArenaAllocator::allocArray
T * allocArray(size_t Count)
Definition: MicrosoftDemangle.h:70
llvm::MipsISD::Ret
@ Ret
Definition: MipsISelLowering.h:119
llvm::ms_demangle::Q_Const
@ Q_Const
Definition: MicrosoftDemangleNodes.h:36
llvm::ms_demangle::ArrayTypeNode::Dimensions
NodeArrayNode * Dimensions
Definition: MicrosoftDemangleNodes.h:494
llvm::ms_demangle::Qualifiers
Qualifiers
Definition: MicrosoftDemangleNodes.h:34
llvm::ms_demangle::SpecialIntrinsicKind::UdtReturning
@ UdtReturning
llvm::codeview::PointerMode::Pointer
@ Pointer
llvm::pdb::Double
@ Double
Definition: PDBTypes.h:402
llvm::ms_demangle::TemplateParameterReferenceNode
Definition: MicrosoftDemangleNodes.h:538
llvm::ms_demangle::QualifiedNameNode
Definition: MicrosoftDemangleNodes.h:525
isTagType
static bool isTagType(StringView S)
Definition: MicrosoftDemangle.cpp:181
llvm::ms_demangle::SpecialIntrinsicKind::RttiCompleteObjLocator
@ RttiCompleteObjLocator
llvm::ms_demangle::VariableSymbolNode::SC
StorageClass SC
Definition: MicrosoftDemangleNodes.h:614
llvm::ms_demangle::FC_Global
@ FC_Global
Definition: MicrosoftDemangleNodes.h:213
llvm::ms_demangle::StorageClass
StorageClass
Definition: MicrosoftDemangleNodes.h:45
llvm::ms_demangle::FC_Static
@ FC_Static
Definition: MicrosoftDemangleNodes.h:214
llvm::ms_demangle::SpecialIntrinsicKind::LocalStaticThreadGuard
@ LocalStaticThreadGuard
llvm::ms_demangle::SymbolNode::output
void output(OutputBuffer &OB, OutputFlags Flags) const override
Definition: MicrosoftDemangleNodes.cpp:582
llvm::ms_demangle::OF_NoVariableType
@ OF_NoVariableType
Definition: MicrosoftDemangleNodes.h:82
llvm::ms_demangle::CallingConv
CallingConv
Definition: MicrosoftDemangleNodes.h:58
llvm::ms_demangle::OF_NoCallingConvention
@ OF_NoCallingConvention
Definition: MicrosoftDemangleNodes.h:77
llvm::PPCISD::SC
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Definition: PPCISelLowering.h:418
llvm::ms_demangle::FC_NoParameterList
@ FC_NoParameterList
Definition: MicrosoftDemangleNodes.h:218
llvm::ms_demangle::IntrinsicFunctionKind
IntrinsicFunctionKind
Definition: MicrosoftDemangleNodes.h:117
llvm::ms_demangle::FunctionSignatureNode::CallConvention
CallingConv CallConvention
Definition: MicrosoftDemangleNodes.h:334
llvm::ms_demangle::FunctionSignatureNode::ReturnType
TypeNode * ReturnType
Definition: MicrosoftDemangleNodes.h:342
llvm::ms_demangle::SpecialIntrinsicKind
SpecialIntrinsicKind
Definition: MicrosoftDemangleNodes.h:186
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::ms_demangle::FunctionRefQualifier::None
@ None
llvm::ms_demangle::QualifiedNameNode::getUnqualifiedIdentifier
IdentifierNode * getUnqualifiedIdentifier()
Definition: MicrosoftDemangleNodes.h:532
llvm::ms_demangle::FunctionIdentifierCodeGroup::DoubleUnder
@ DoubleUnder
outputEscapedChar
static void outputEscapedChar(OutputBuffer &OB, unsigned C)
Definition: MicrosoftDemangle.cpp:1133
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::ms_demangle::ArenaAllocator::alloc
T * alloc(Args &&... ConstructorArgs)
Definition: MicrosoftDemangle.h:89
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
demangleFunctionRefQualifier
static FunctionRefQualifier demangleFunctionRefQualifier(StringView &MangledName)
Definition: MicrosoftDemangle.cpp:216
NodeList
Definition: MicrosoftDemangle.cpp:37
llvm::ms_demangle::LocalStaticGuardVariableNode
Definition: MicrosoftDemangleNodes.h:590
StringView::npos
static const size_t npos
Definition: StringView.h:30
llvm::ms_demangle::PointerTypeNode::Pointee
TypeNode * Pointee
Definition: MicrosoftDemangleNodes.h:471
DEMANGLE_FALLTHROUGH
#define DEMANGLE_FALLTHROUGH
Definition: DemangleConfig.h:82
llvm::ms_demangle::FC_StaticThisAdjust
@ FC_StaticThisAdjust
Definition: MicrosoftDemangleNodes.h:221
INT64_MAX
#define INT64_MAX
Definition: DataTypes.h:71
llvm::ms_demangle::RttiBaseClassDescriptorNode::VBPtrOffset
int32_t VBPtrOffset
Definition: MicrosoftDemangleNodes.h:570
llvm::ms_demangle::OF_NoReturnType
@ OF_NoReturnType
Definition: MicrosoftDemangleNodes.h:81
llvm::ms_demangle::ThunkSignatureNode::ThisAdjustor::StaticOffset
uint32_t StaticOffset
Definition: MicrosoftDemangleNodes.h:449
startsWithDigit
static bool startsWithDigit(StringView S)
Definition: MicrosoftDemangle.cpp:32
llvm::ms_demangle::LocalStaticGuardIdentifierNode
Definition: MicrosoftDemangleNodes.h:409
llvm::ms_demangle::QualifierMangleMode
QualifierMangleMode
Definition: MicrosoftDemangle.h:125
llvm::MSDF_NoCallingConvention
@ MSDF_NoCallingConvention
Definition: Demangle.h:38
llvm::ms_demangle::IdentifierNode
Definition: MicrosoftDemangleNodes.h:354
llvm::ms_demangle::RttiBaseClassDescriptorNode::NVOffset
uint32_t NVOffset
Definition: MicrosoftDemangleNodes.h:569
llvm::None
const NoneType None
Definition: None.h:24
llvm::MSDF_NoVariableType
@ MSDF_NoVariableType
Definition: Demangle.h:41
llvm::ms_demangle::LocalStaticGuardIdentifierNode::IsThread
bool IsThread
Definition: MicrosoftDemangleNodes.h:415
llvm::ms_demangle::TagTypeNode
Definition: MicrosoftDemangleNodes.h:474
llvm::ms_demangle::SpecialIntrinsicKind::RttiBaseClassArray
@ RttiBaseClassArray
StringView.h
llvm::ms_demangle::SpecialIntrinsicKind::StringLiteralSymbol
@ StringLiteralSymbol
llvm::ms_demangle::OF_NoMemberType
@ OF_NoMemberType
Definition: MicrosoftDemangleNodes.h:80
llvm::ms_demangle::SymbolNode
Definition: MicrosoftDemangleNodes.h:575
llvm::ms_demangle::LocalStaticGuardVariableNode::IsVisible
bool IsVisible
Definition: MicrosoftDemangleNodes.h:596
llvm::ms_demangle::Node::kind
NodeKind kind() const
Definition: MicrosoftDemangleNodes.h:262
llvm::ms_demangle::FunctionSignatureNode::RefQualifier
FunctionRefQualifier RefQualifier
Definition: MicrosoftDemangleNodes.h:339
llvm::ms_demangle::ConversionOperatorIdentifierNode
Definition: MicrosoftDemangleNodes.h:419
llvm::ms_demangle::StructorIdentifierNode::Class
IdentifierNode * Class
Definition: MicrosoftDemangleNodes.h:438
llvm::ms_demangle::ThunkSignatureNode
Definition: MicrosoftDemangleNodes.h:442
nodeListToNodeArray
static NodeArrayNode * nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, size_t Count)
Definition: MicrosoftDemangle.cpp:1550
llvm::ms_demangle::VariableSymbolNode::Type
TypeNode * Type
Definition: MicrosoftDemangleNodes.h:615
llvm::ms_demangle::NamedIdentifierNode
Definition: MicrosoftDemangleNodes.h:382
llvm::ms_demangle::NodeArrayNode::Count
size_t Count
Definition: MicrosoftDemangleNodes.h:522
guessCharByteSize
static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, uint64_t NumBytes)
Definition: MicrosoftDemangle.cpp:1205
llvm::ms_demangle::PrimitiveTypeNode
Definition: MicrosoftDemangleNodes.h:312
isPointerType
static bool isPointerType(StringView S)
Definition: MicrosoftDemangle.cpp:194
llvm::ms_demangle::FC_Public
@ FC_Public
Definition: MicrosoftDemangleNodes.h:210
uint64_t
llvm::pdb::Unknown
@ Unknown
Definition: PDBTypes.h:396
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
llvm::ms_demangle::Q_None
@ Q_None
Definition: MicrosoftDemangleNodes.h:35
llvm::ms_demangle::FC_VirtualThisAdjustEx
@ FC_VirtualThisAdjustEx
Definition: MicrosoftDemangleNodes.h:220
llvm::ms_demangle::DynamicStructorIdentifierNode::IsDestructor
bool IsDestructor
Definition: MicrosoftDemangleNodes.h:379
llvm::ms_demangle::LiteralOperatorIdentifierNode
Definition: MicrosoftDemangleNodes.h:400
llvm::MSDF_NoReturnType
@ MSDF_NoReturnType
Definition: Demangle.h:39
llvm::ms_demangle::FunctionIdentifierCodeGroup::Under
@ Under
countEmbeddedNulls
static unsigned countEmbeddedNulls(const uint8_t *StringBytes, unsigned Length)
Definition: MicrosoftDemangle.cpp:1192
llvm::ms_demangle::SpecialIntrinsicKind::Typeof
@ Typeof
llvm::MD5
Definition: MD5.h:41
Qualifiers
Qualifiers
Definition: ItaniumDemangle.h:389
llvm::NVPTX::PTXLdStInstCode::Float
@ Float
Definition: NVPTX.h:118
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::ms_demangle::NamedIdentifierNode::Name
StringView Name
Definition: MicrosoftDemangleNodes.h:387
llvm::ms_demangle::SpecialTableSymbolNode
Definition: MicrosoftDemangleNodes.h:581
llvm::ms_demangle::SpecialIntrinsicKind::Vftable
@ Vftable
llvm::ms_demangle::Q_Volatile
@ Q_Volatile
Definition: MicrosoftDemangleNodes.h:37
MicrosoftDemangleNodes.h
llvm::ms_demangle::FC_None
@ FC_None
Definition: MicrosoftDemangleNodes.h:209
llvm::ms_demangle::CustomTypeNode::Identifier
IdentifierNode * Identifier
Definition: MicrosoftDemangleNodes.h:511
llvm::ms_demangle::FunctionRefQualifier::RValueReference
@ RValueReference
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::demangle_success
@ demangle_success
Definition: Demangle.h:28
DEMANGLE_UNREACHABLE
#define DEMANGLE_UNREACHABLE
Definition: DemangleConfig.h:58
llvm::ms_demangle::PointerTypeNode
Definition: MicrosoftDemangleNodes.h:458
synthesizeNamedIdentifier
static NamedIdentifierNode * synthesizeNamedIdentifier(ArenaAllocator &Arena, StringView Name)
Definition: MicrosoftDemangle.cpp:318
llvm::ms_demangle::TemplateParameterReferenceNode::ThunkOffsets
std::array< int64_t, 3 > ThunkOffsets
Definition: MicrosoftDemangleNodes.h:547
isCustomType
static bool isCustomType(StringView S)
Definition: MicrosoftDemangle.cpp:192
Status
Definition: SIModeRegister.cpp:29
llvm::ms_demangle::RttiBaseClassDescriptorNode
Definition: MicrosoftDemangleNodes.h:563
llvm::ms_demangle::FuncClass
FuncClass
Definition: MicrosoftDemangleNodes.h:208
llvm::ms_demangle::BackrefContext
Definition: MicrosoftDemangle.h:113
llvm::ms_demangle::ConversionOperatorIdentifierNode::TargetType
TypeNode * TargetType
Definition: MicrosoftDemangleNodes.h:426
llvm::ms_demangle::Q_Pointer64
@ Q_Pointer64
Definition: MicrosoftDemangleNodes.h:42
Demangle.h
llvm::ms_demangle::SpecialIntrinsicKind::DynamicAtexitDestructor
@ DynamicAtexitDestructor
llvm::ms_demangle::SpecialIntrinsicKind::RttiBaseClassDescriptor
@ RttiBaseClassDescriptor
llvm::MSDemangleFlags
MSDemangleFlags
Definition: Demangle.h:34
isRebasedHexDigit
static bool isRebasedHexDigit(char C)
Definition: MicrosoftDemangle.cpp:1023
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
llvm::ms_demangle::FC_VirtualThisAdjust
@ FC_VirtualThisAdjust
Definition: MicrosoftDemangleNodes.h:219
Number
uint32_t Number
Definition: Profile.cpp:47
outputHex
static void outputHex(OutputBuffer &OB, unsigned C)
Definition: MicrosoftDemangle.cpp:1107
parse
static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition: LineTable.cpp:54
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::ms_demangle::VcallThunkIdentifierNode
Definition: MicrosoftDemangleNodes.h:363
llvm::ms_demangle::ThunkSignatureNode::ThisAdjust
ThisAdjustor ThisAdjust
Definition: MicrosoftDemangleNodes.h:455
llvm::ms_demangle::Demangler
Definition: MicrosoftDemangle.h:138
llvm::MSDF_DumpBackrefs
@ MSDF_DumpBackrefs
Definition: Demangle.h:36
llvm::pdb::Bool
@ Bool
Definition: PDBTypes.h:407
llvm::ms_demangle::FunctionRefQualifier
FunctionRefQualifier
Definition: MicrosoftDemangleNodes.h:55
llvm::object::Comma
@ Comma
Definition: COFFModuleDefinition.cpp:35
llvm::demangle_invalid_mangled_name
@ demangle_invalid_mangled_name
Definition: Demangle.h:26
llvm::ms_demangle::RttiBaseClassDescriptorNode::VBTableOffset
uint32_t VBTableOffset
Definition: MicrosoftDemangleNodes.h:571
DemangleConfig.h
llvm::ms_demangle::OF_NoAccessSpecifier
@ OF_NoAccessSpecifier
Definition: MicrosoftDemangleNodes.h:79
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
initializeOutputBuffer
bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB, size_t InitSize)
Definition: Utility.h:201
llvm::ms_demangle::FunctionSignatureNode::Params
NodeArrayNode * Params
Definition: MicrosoftDemangleNodes.h:348
llvm::ms_demangle::TypeNode::Quals
Qualifiers Quals
Definition: MicrosoftDemangleNodes.h:309
llvm::ms_demangle::ArrayTypeNode::ElementType
TypeNode * ElementType
Definition: MicrosoftDemangleNodes.h:497
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::ms_demangle::ThunkSignatureNode::ThisAdjustor::VBOffsetOffset
int32_t VBOffsetOffset
Definition: MicrosoftDemangleNodes.h:451
llvm::ms_demangle::ArenaAllocator
Definition: MicrosoftDemangle.h:26
llvm::ms_demangle::ThunkSignatureNode::ThisAdjustor::VtordispOffset
int32_t VtordispOffset
Definition: MicrosoftDemangleNodes.h:452
llvm::ms_demangle::SpecialIntrinsicKind::RttiTypeDescriptor
@ RttiTypeDescriptor
NodeList::Next
NodeList * Next
Definition: MicrosoftDemangle.cpp:39
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::ms_demangle::SpecialIntrinsicKind::None
@ None
llvm::object::Identifier
@ Identifier
Definition: COFFModuleDefinition.cpp:34
llvm::ms_demangle::FunctionSignatureNode::IsVariadic
bool IsVariadic
Definition: MicrosoftDemangleNodes.h:345
Lookup
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
Definition: X86FloatingPoint.cpp:597
llvm::microsoftDemangle
char * microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf, size_t *n_buf, int *status, MSDemangleFlags Flags=MSDF_None)
Demangles the Microsoft symbol pointed at by mangled_name and returns it.
Definition: MicrosoftDemangle.cpp:2334
llvm::ms_demangle::PointerTypeNode::ClassParent
QualifiedNameNode * ClassParent
Definition: MicrosoftDemangleNodes.h:467
llvm::tgtok::Class
@ Class
Definition: TGLexer.h:50
llvm::ms_demangle::SpecialIntrinsicKind::LocalStaticGuard
@ LocalStaticGuard
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
llvm::ms_demangle::FC_Far
@ FC_Far
Definition: MicrosoftDemangleNodes.h:216
isFunctionType
static bool isFunctionType(StringView S)
Definition: MicrosoftDemangle.cpp:211
startsWithLocalScopePattern
static bool startsWithLocalScopePattern(StringView S)
Definition: MicrosoftDemangle.cpp:142
llvm::ms_demangle::FC_Protected
@ FC_Protected
Definition: MicrosoftDemangleNodes.h:211
llvm::ms_demangle::PointerAffinity::Reference
@ Reference
llvm::ms_demangle::StructorIdentifierNode
Definition: MicrosoftDemangleNodes.h:429
llvm::ms_demangle::FC_Virtual
@ FC_Virtual
Definition: MicrosoftDemangleNodes.h:215
llvm::ms_demangle::TemplateParameterReferenceNode::ThunkOffsetCount
int ThunkOffsetCount
Definition: MicrosoftDemangleNodes.h:546
N
#define N
llvm::codeview::Basic
@ Basic
Definition: CodeView.h:152
llvm::ms_demangle::FC_ExternC
@ FC_ExternC
Definition: MicrosoftDemangleNodes.h:217
countTrailingNullBytes
static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length)
Definition: MicrosoftDemangle.cpp:1181
llvm::ms_demangle::NodeArrayNode
Definition: MicrosoftDemangleNodes.h:514
NodeList::N
Node * N
Definition: MicrosoftDemangle.cpp:38
llvm::ms_demangle::NBB_Simple
@ NBB_Simple
Definition: MicrosoftDemangle.h:130
llvm::ms_demangle::SymbolNode::Name
QualifiedNameNode * Name
Definition: MicrosoftDemangleNodes.h:578
llvm::ms_demangle::VariableSymbolNode
Definition: MicrosoftDemangleNodes.h:609
llvm::ms_demangle::NBB_Template
@ NBB_Template
Definition: MicrosoftDemangle.h:129
MicrosoftDemangle.h
llvm::ms_demangle::TypeNode
Definition: MicrosoftDemangleNodes.h:298
llvm::ms_demangle::FunctionSignatureNode::IsNoexcept
bool IsNoexcept
Definition: MicrosoftDemangleNodes.h:351
llvm::ms_demangle::RttiBaseClassDescriptorNode::Flags
uint32_t Flags
Definition: MicrosoftDemangleNodes.h:572
llvm::ms_demangle::OutputFlags
OutputFlags
Definition: MicrosoftDemangleNodes.h:75
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:235
llvm::CallingConv::Swift
@ Swift
Definition: CallingConv.h:73
synthesizeVariable
static VariableSymbolNode * synthesizeVariable(ArenaAllocator &Arena, TypeNode *Type, StringView VariableName)
Definition: MicrosoftDemangle.cpp:341
llvm::ms_demangle::SpecialIntrinsicKind::VcallThunk
@ VcallThunk
llvm::ms_demangle::EncodedStringLiteralNode
Definition: MicrosoftDemangleNodes.h:599
llvm::MSDF_NoMemberType
@ MSDF_NoMemberType
Definition: Demangle.h:40
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::ms_demangle::LocalStaticGuardIdentifierNode::ScopeIndex
uint32_t ScopeIndex
Definition: MicrosoftDemangleNodes.h:416
llvm::demangle_memory_alloc_failure
@ demangle_memory_alloc_failure
Definition: Demangle.h:27
llvm::ms_demangle::PointerAffinity::RValueReference
@ RValueReference
llvm::ms_demangle::FunctionSymbolNode
Definition: MicrosoftDemangleNodes.h:618