LLVM  16.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  Error = true;
828  return nullptr;
829  }
830  MangledName.consumeFront(".?A");
831  if (MangledName.empty()) {
832  Error = true;
833  return nullptr;
834  }
835 
836  return demangleClassType(MangledName);
837 }
838 
839 // <type-encoding> ::= <storage-class> <variable-type>
840 // <storage-class> ::= 0 # private static member
841 // ::= 1 # protected static member
842 // ::= 2 # public static member
843 // ::= 3 # global
844 // ::= 4 # static local
845 
846 VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName,
847  StorageClass SC) {
849 
850  VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
851  VSN->SC = SC;
852 
853  if (Error)
854  return nullptr;
855 
856  // <variable-type> ::= <type> <cvr-qualifiers>
857  // ::= <type> <pointee-cvr-qualifiers> # pointers, references
858  switch (VSN->Type->kind()) {
859  case NodeKind::PointerType: {
860  PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type);
861 
862  Qualifiers ExtraChildQuals = Q_None;
863  PTN->Quals = Qualifiers(VSN->Type->Quals |
864  demanglePointerExtQualifiers(MangledName));
865 
866  bool IsMember = false;
867  std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
868 
869  if (PTN->ClassParent) {
870  QualifiedNameNode *BackRefName =
871  demangleFullyQualifiedTypeName(MangledName);
872  (void)BackRefName;
873  }
874  PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals);
875 
876  break;
877  }
878  default:
879  VSN->Type->Quals = demangleQualifiers(MangledName).first;
880  break;
881  }
882 
883  return VSN;
884 }
885 
886 // Sometimes numbers are encoded in mangled symbols. For example,
887 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
888 // length 20), so we need some way to embed numbers as part of symbols.
889 // This function parses it.
890 //
891 // <number> ::= [?] <non-negative integer>
892 //
893 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
894 // ::= <hex digit>+ @ # when Number == 0 or >= 10
895 //
896 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
897 std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
898  bool IsNegative = MangledName.consumeFront('?');
899 
900  if (startsWithDigit(MangledName)) {
901  uint64_t Ret = MangledName[0] - '0' + 1;
902  MangledName = MangledName.dropFront(1);
903  return {Ret, IsNegative};
904  }
905 
906  uint64_t Ret = 0;
907  for (size_t i = 0; i < MangledName.size(); ++i) {
908  char C = MangledName[i];
909  if (C == '@') {
910  MangledName = MangledName.dropFront(i + 1);
911  return {Ret, IsNegative};
912  }
913  if ('A' <= C && C <= 'P') {
914  Ret = (Ret << 4) + (C - 'A');
915  continue;
916  }
917  break;
918  }
919 
920  Error = true;
921  return {0ULL, false};
922 }
923 
924 uint64_t Demangler::demangleUnsigned(StringView &MangledName) {
925  bool IsNegative = false;
926  uint64_t Number = 0;
927  std::tie(Number, IsNegative) = demangleNumber(MangledName);
928  if (IsNegative)
929  Error = true;
930  return Number;
931 }
932 
933 int64_t Demangler::demangleSigned(StringView &MangledName) {
934  bool IsNegative = false;
935  uint64_t Number = 0;
936  std::tie(Number, IsNegative) = demangleNumber(MangledName);
937  if (Number > INT64_MAX)
938  Error = true;
939  int64_t I = static_cast<int64_t>(Number);
940  return IsNegative ? -I : I;
941 }
942 
943 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
944 // Memorize it.
945 void Demangler::memorizeString(StringView S) {
946  if (Backrefs.NamesCount >= BackrefContext::Max)
947  return;
948  for (size_t i = 0; i < Backrefs.NamesCount; ++i)
949  if (S == Backrefs.Names[i]->Name)
950  return;
952  N->Name = S;
953  Backrefs.Names[Backrefs.NamesCount++] = N;
954 }
955 
956 NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) {
957  assert(startsWithDigit(MangledName));
958 
959  size_t I = MangledName[0] - '0';
960  if (I >= Backrefs.NamesCount) {
961  Error = true;
962  return nullptr;
963  }
964 
965  MangledName = MangledName.dropFront();
966  return Backrefs.Names[I];
967 }
968 
969 void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
970  // Render this class template name into a string buffer so that we can
971  // memorize it for the purpose of back-referencing.
972  OutputBuffer OB;
973  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
974  // FIXME: Propagate out-of-memory as an error?
975  std::terminate();
976  Identifier->output(OB, OF_Default);
977  StringView Owned = copyString(OB);
978  memorizeString(Owned);
979  std::free(OB.getBuffer());
980 }
981 
983 Demangler::demangleTemplateInstantiationName(StringView &MangledName,
984  NameBackrefBehavior NBB) {
985  assert(MangledName.startsWith("?$"));
986  MangledName.consumeFront("?$");
987 
988  BackrefContext OuterContext;
989  std::swap(OuterContext, Backrefs);
990 
992  demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
993  if (!Error)
994  Identifier->TemplateParams = demangleTemplateParameterList(MangledName);
995 
996  std::swap(OuterContext, Backrefs);
997  if (Error)
998  return nullptr;
999 
1000  if (NBB & NBB_Template) {
1001  // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
1002  // Structors and conversion operators only makes sense in a leaf name, so
1003  // reject them in NBB_Template contexts.
1004  if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier ||
1005  Identifier->kind() == NodeKind::StructorIdentifier) {
1006  Error = true;
1007  return nullptr;
1008  }
1009 
1010  memorizeIdentifier(Identifier);
1011  }
1012 
1013  return Identifier;
1014 }
1015 
1016 NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName,
1017  bool Memorize) {
1018  StringView S = demangleSimpleString(MangledName, Memorize);
1019  if (Error)
1020  return nullptr;
1021 
1023  Name->Name = S;
1024  return Name;
1025 }
1026 
1027 static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); }
1028 
1029 static uint8_t rebasedHexDigitToNumber(char C) {
1031  return (C <= 'J') ? (C - 'A') : (10 + C - 'K');
1032 }
1033 
1034 uint8_t Demangler::demangleCharLiteral(StringView &MangledName) {
1035  assert(!MangledName.empty());
1036  if (!MangledName.startsWith('?'))
1037  return MangledName.popFront();
1038 
1039  MangledName = MangledName.dropFront();
1040  if (MangledName.empty())
1041  goto CharLiteralError;
1042 
1043  if (MangledName.consumeFront('$')) {
1044  // Two hex digits
1045  if (MangledName.size() < 2)
1046  goto CharLiteralError;
1047  StringView Nibbles = MangledName.substr(0, 2);
1048  if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1]))
1049  goto CharLiteralError;
1050  // Don't append the null terminator.
1051  uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]);
1052  uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]);
1053  MangledName = MangledName.dropFront(2);
1054  return (C1 << 4) | C2;
1055  }
1056 
1057  if (startsWithDigit(MangledName)) {
1058  const char *Lookup = ",/\\:. \n\t'-";
1059  char C = Lookup[MangledName[0] - '0'];
1060  MangledName = MangledName.dropFront();
1061  return C;
1062  }
1063 
1064  if (MangledName[0] >= 'a' && MangledName[0] <= 'z') {
1065  char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1066  '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1067  '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1068  '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1069  char C = Lookup[MangledName[0] - 'a'];
1070  MangledName = MangledName.dropFront();
1071  return C;
1072  }
1073 
1074  if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') {
1075  char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1076  '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1077  '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1078  '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1079  char C = Lookup[MangledName[0] - 'A'];
1080  MangledName = MangledName.dropFront();
1081  return C;
1082  }
1083 
1084 CharLiteralError:
1085  Error = true;
1086  return '\0';
1087 }
1088 
1089 wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) {
1090  uint8_t C1, C2;
1091 
1092  C1 = demangleCharLiteral(MangledName);
1093  if (Error || MangledName.empty())
1094  goto WCharLiteralError;
1095  C2 = demangleCharLiteral(MangledName);
1096  if (Error)
1097  goto WCharLiteralError;
1098 
1099  return ((wchar_t)C1 << 8) | (wchar_t)C2;
1100 
1101 WCharLiteralError:
1102  Error = true;
1103  return L'\0';
1104 }
1105 
1106 static void writeHexDigit(char *Buffer, uint8_t Digit) {
1107  assert(Digit <= 15);
1108  *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
1109 }
1110 
1111 static void outputHex(OutputBuffer &OB, unsigned C) {
1112  assert (C != 0);
1113 
1114  // It's easier to do the math if we can work from right to left, but we need
1115  // to print the numbers from left to right. So render this into a temporary
1116  // buffer first, then output the temporary buffer. Each byte is of the form
1117  // \xAB, which means that each byte needs 4 characters. Since there are at
1118  // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1119  char TempBuffer[17];
1120 
1121  ::memset(TempBuffer, 0, sizeof(TempBuffer));
1122  constexpr int MaxPos = sizeof(TempBuffer) - 1;
1123 
1124  int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0.
1125  while (C != 0) {
1126  for (int I = 0; I < 2; ++I) {
1127  writeHexDigit(&TempBuffer[Pos--], C % 16);
1128  C /= 16;
1129  }
1130  }
1131  TempBuffer[Pos--] = 'x';
1132  assert(Pos >= 0);
1133  TempBuffer[Pos--] = '\\';
1134  OB << StringView(&TempBuffer[Pos + 1]);
1135 }
1136 
1137 static void outputEscapedChar(OutputBuffer &OB, unsigned C) {
1138  switch (C) {
1139  case '\0': // nul
1140  OB << "\\0";
1141  return;
1142  case '\'': // single quote
1143  OB << "\\\'";
1144  return;
1145  case '\"': // double quote
1146  OB << "\\\"";
1147  return;
1148  case '\\': // backslash
1149  OB << "\\\\";
1150  return;
1151  case '\a': // bell
1152  OB << "\\a";
1153  return;
1154  case '\b': // backspace
1155  OB << "\\b";
1156  return;
1157  case '\f': // form feed
1158  OB << "\\f";
1159  return;
1160  case '\n': // new line
1161  OB << "\\n";
1162  return;
1163  case '\r': // carriage return
1164  OB << "\\r";
1165  return;
1166  case '\t': // tab
1167  OB << "\\t";
1168  return;
1169  case '\v': // vertical tab
1170  OB << "\\v";
1171  return;
1172  default:
1173  break;
1174  }
1175 
1176  if (C > 0x1F && C < 0x7F) {
1177  // Standard ascii char.
1178  OB << (char)C;
1179  return;
1180  }
1181 
1182  outputHex(OB, C);
1183 }
1184 
1185 static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) {
1186  const uint8_t *End = StringBytes + Length - 1;
1187  unsigned Count = 0;
1188  while (Length > 0 && *End == 0) {
1189  --Length;
1190  --End;
1191  ++Count;
1192  }
1193  return Count;
1194 }
1195 
1196 static unsigned countEmbeddedNulls(const uint8_t *StringBytes,
1197  unsigned Length) {
1198  unsigned Result = 0;
1199  for (unsigned I = 0; I < Length; ++I) {
1200  if (*StringBytes++ == 0)
1201  ++Result;
1202  }
1203  return Result;
1204 }
1205 
1206 // A mangled (non-wide) string literal stores the total length of the string it
1207 // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
1208 // (passed in StringBytes, NumChars).
1209 static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars,
1210  uint64_t NumBytes) {
1211  assert(NumBytes > 0);
1212 
1213  // If the number of bytes is odd, this is guaranteed to be a char string.
1214  if (NumBytes % 2 == 1)
1215  return 1;
1216 
1217  // All strings can encode at most 32 bytes of data. If it's less than that,
1218  // then we encoded the entire string. In this case we check for a 1-byte,
1219  // 2-byte, or 4-byte null terminator.
1220  if (NumBytes < 32) {
1221  unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars);
1222  if (TrailingNulls >= 4 && NumBytes % 4 == 0)
1223  return 4;
1224  if (TrailingNulls >= 2)
1225  return 2;
1226  return 1;
1227  }
1228 
1229  // The whole string was not able to be encoded. Try to look at embedded null
1230  // terminators to guess. The heuristic is that we count all embedded null
1231  // terminators. If more than 2/3 are null, it's a char32. If more than 1/3
1232  // are null, it's a char16. Otherwise it's a char8. This obviously isn't
1233  // perfect and is biased towards languages that have ascii alphabets, but this
1234  // was always going to be best effort since the encoding is lossy.
1235  unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars);
1236  if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
1237  return 4;
1238  if (Nulls >= NumChars / 3)
1239  return 2;
1240  return 1;
1241 }
1242 
1243 static unsigned decodeMultiByteChar(const uint8_t *StringBytes,
1244  unsigned CharIndex, unsigned CharBytes) {
1245  assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4);
1246  unsigned Offset = CharIndex * CharBytes;
1247  unsigned Result = 0;
1248  StringBytes = StringBytes + Offset;
1249  for (unsigned I = 0; I < CharBytes; ++I) {
1250  unsigned C = static_cast<unsigned>(StringBytes[I]);
1251  Result |= C << (8 * I);
1252  }
1253  return Result;
1254 }
1255 
1256 FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) {
1259  FSN->Signature = Arena.alloc<ThunkSignatureNode>();
1261 
1262  FSN->Name = demangleNameScopeChain(MangledName, VTIN);
1263  if (!Error)
1264  Error = !MangledName.consumeFront("$B");
1265  if (!Error)
1266  VTIN->OffsetInVTable = demangleUnsigned(MangledName);
1267  if (!Error)
1268  Error = !MangledName.consumeFront('A');
1269  if (!Error)
1270  FSN->Signature->CallConvention = demangleCallingConvention(MangledName);
1271  return (Error) ? nullptr : FSN;
1272 }
1273 
1275 Demangler::demangleStringLiteral(StringView &MangledName) {
1276  // This function uses goto, so declare all variables up front.
1277  OutputBuffer OB;
1278  StringView CRC;
1279  uint64_t StringByteSize;
1280  bool IsWcharT = false;
1281  bool IsNegative = false;
1282  size_t CrcEndPos = 0;
1283 
1285 
1286  // Must happen before the first `goto StringLiteralError`.
1287  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1288  // FIXME: Propagate out-of-memory as an error?
1289  std::terminate();
1290 
1291  // Prefix indicating the beginning of a string literal
1292  if (!MangledName.consumeFront("@_"))
1293  goto StringLiteralError;
1294  if (MangledName.empty())
1295  goto StringLiteralError;
1296 
1297  // Char Type (regular or wchar_t)
1298  switch (MangledName.popFront()) {
1299  case '1':
1300  IsWcharT = true;
1302  case '0':
1303  break;
1304  default:
1305  goto StringLiteralError;
1306  }
1307 
1308  // Encoded Length
1309  std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
1310  if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
1311  goto StringLiteralError;
1312 
1313  // CRC 32 (always 8 characters plus a terminator)
1314  CrcEndPos = MangledName.find('@');
1315  if (CrcEndPos == StringView::npos)
1316  goto StringLiteralError;
1317  CRC = MangledName.substr(0, CrcEndPos);
1318  MangledName = MangledName.dropFront(CrcEndPos + 1);
1319  if (MangledName.empty())
1320  goto StringLiteralError;
1321 
1322  if (IsWcharT) {
1323  Result->Char = CharKind::Wchar;
1324  if (StringByteSize > 64)
1325  Result->IsTruncated = true;
1326 
1327  while (!MangledName.consumeFront('@')) {
1328  if (MangledName.size() < 2)
1329  goto StringLiteralError;
1330  wchar_t W = demangleWcharLiteral(MangledName);
1331  if (StringByteSize != 2 || Result->IsTruncated)
1333  StringByteSize -= 2;
1334  if (Error)
1335  goto StringLiteralError;
1336  }
1337  } else {
1338  // The max byte length is actually 32, but some compilers mangled strings
1339  // incorrectly, so we have to assume it can go higher.
1340  constexpr unsigned MaxStringByteLength = 32 * 4;
1341  uint8_t StringBytes[MaxStringByteLength];
1342 
1343  unsigned BytesDecoded = 0;
1344  while (!MangledName.consumeFront('@')) {
1345  if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
1346  goto StringLiteralError;
1347  StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
1348  }
1349 
1350  if (StringByteSize > BytesDecoded)
1351  Result->IsTruncated = true;
1352 
1353  unsigned CharBytes =
1354  guessCharByteSize(StringBytes, BytesDecoded, StringByteSize);
1355  assert(StringByteSize % CharBytes == 0);
1356  switch (CharBytes) {
1357  case 1:
1358  Result->Char = CharKind::Char;
1359  break;
1360  case 2:
1361  Result->Char = CharKind::Char16;
1362  break;
1363  case 4:
1364  Result->Char = CharKind::Char32;
1365  break;
1366  default:
1368  }
1369  const unsigned NumChars = BytesDecoded / CharBytes;
1370  for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
1371  unsigned NextChar =
1372  decodeMultiByteChar(StringBytes, CharIndex, CharBytes);
1373  if (CharIndex + 1 < NumChars || Result->IsTruncated)
1374  outputEscapedChar(OB, NextChar);
1375  }
1376  }
1377 
1378  Result->DecodedString = copyString(OB);
1379  std::free(OB.getBuffer());
1380  return Result;
1381 
1382 StringLiteralError:
1383  Error = true;
1384  std::free(OB.getBuffer());
1385  return nullptr;
1386 }
1387 
1388 // Returns MangledName's prefix before the first '@', or an error if
1389 // MangledName contains no '@' or the prefix has length 0.
1390 StringView Demangler::demangleSimpleString(StringView &MangledName,
1391  bool Memorize) {
1392  StringView S;
1393  for (size_t i = 0; i < MangledName.size(); ++i) {
1394  if (MangledName[i] != '@')
1395  continue;
1396  if (i == 0)
1397  break;
1398  S = MangledName.substr(0, i);
1399  MangledName = MangledName.dropFront(i + 1);
1400 
1401  if (Memorize)
1402  memorizeString(S);
1403  return S;
1404  }
1405 
1406  Error = true;
1407  return {};
1408 }
1409 
1411 Demangler::demangleAnonymousNamespaceName(StringView &MangledName) {
1412  assert(MangledName.startsWith("?A"));
1413  MangledName.consumeFront("?A");
1414 
1416  Node->Name = "`anonymous namespace'";
1417  size_t EndPos = MangledName.find('@');
1418  if (EndPos == StringView::npos) {
1419  Error = true;
1420  return nullptr;
1421  }
1422  StringView NamespaceKey = MangledName.substr(0, EndPos);
1423  memorizeString(NamespaceKey);
1424  MangledName = MangledName.substr(EndPos + 1);
1425  return Node;
1426 }
1427 
1429 Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
1430  assert(startsWithLocalScopePattern(MangledName));
1431 
1433  MangledName.consumeFront('?');
1434  uint64_t Number = 0;
1435  bool IsNegative = false;
1436  std::tie(Number, IsNegative) = demangleNumber(MangledName);
1437  assert(!IsNegative);
1438 
1439  // One ? to terminate the number
1440  MangledName.consumeFront('?');
1441 
1442  assert(!Error);
1443  Node *Scope = parse(MangledName);
1444  if (Error)
1445  return nullptr;
1446 
1447  // Render the parent symbol's name into a buffer.
1448  OutputBuffer OB;
1449  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1450  // FIXME: Propagate out-of-memory as an error?
1451  std::terminate();
1452  OB << '`';
1453  Scope->output(OB, OF_Default);
1454  OB << '\'';
1455  OB << "::`" << Number << "'";
1456 
1457  Identifier->Name = copyString(OB);
1458  std::free(OB.getBuffer());
1459  return Identifier;
1460 }
1461 
1462 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
1464 Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
1466  demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
1467  if (Error)
1468  return nullptr;
1469  assert(Identifier);
1470 
1471  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1472  if (Error)
1473  return nullptr;
1474  assert(QN);
1475  return QN;
1476 }
1477 
1478 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1479 // Symbol names have slightly different rules regarding what can appear
1480 // so we separate out the implementations for flexibility.
1482 Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
1483  // This is the final component of a symbol name (i.e. the leftmost component
1484  // of a mangled name. Since the only possible template instantiation that
1485  // can appear in this context is a function template, and since those are
1486  // not saved for the purposes of name backreferences, only backref simple
1487  // names.
1489  demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
1490  if (Error)
1491  return nullptr;
1492 
1493  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
1494  if (Error)
1495  return nullptr;
1496 
1497  if (Identifier->kind() == NodeKind::StructorIdentifier) {
1498  if (QN->Components->Count < 2) {
1499  Error = true;
1500  return nullptr;
1501  }
1502  StructorIdentifierNode *SIN =
1503  static_cast<StructorIdentifierNode *>(Identifier);
1504  Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2];
1505  SIN->Class = static_cast<IdentifierNode *>(ClassNode);
1506  }
1507  assert(QN);
1508  return QN;
1509 }
1510 
1511 IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
1512  bool Memorize) {
1513  // An inner-most name can be a back-reference, because a fully-qualified name
1514  // (e.g. Scope + Inner) can contain other fully qualified names inside of
1515  // them (for example template parameters), and these nested parameters can
1516  // refer to previously mangled types.
1517  if (startsWithDigit(MangledName))
1518  return demangleBackRefName(MangledName);
1519 
1520  if (MangledName.startsWith("?$"))
1521  return demangleTemplateInstantiationName(MangledName, NBB_Template);
1522 
1523  return demangleSimpleName(MangledName, Memorize);
1524 }
1525 
1527 Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
1528  NameBackrefBehavior NBB) {
1529  if (startsWithDigit(MangledName))
1530  return demangleBackRefName(MangledName);
1531  if (MangledName.startsWith("?$"))
1532  return demangleTemplateInstantiationName(MangledName, NBB);
1533  if (MangledName.startsWith('?'))
1534  return demangleFunctionIdentifierCode(MangledName);
1535  return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0);
1536 }
1537 
1538 IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) {
1539  if (startsWithDigit(MangledName))
1540  return demangleBackRefName(MangledName);
1541 
1542  if (MangledName.startsWith("?$"))
1543  return demangleTemplateInstantiationName(MangledName, NBB_Template);
1544 
1545  if (MangledName.startsWith("?A"))
1546  return demangleAnonymousNamespaceName(MangledName);
1547 
1548  if (startsWithLocalScopePattern(MangledName))
1549  return demangleLocallyScopedNamePiece(MangledName);
1550 
1551  return demangleSimpleName(MangledName, /*Memorize=*/true);
1552 }
1553 
1555  size_t Count) {
1556  NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
1557  N->Count = Count;
1558  N->Nodes = Arena.allocArray<Node *>(Count);
1559  for (size_t I = 0; I < Count; ++I) {
1560  N->Nodes[I] = Head->N;
1561  Head = Head->Next;
1562  }
1563  return N;
1564 }
1565 
1567 Demangler::demangleNameScopeChain(StringView &MangledName,
1568  IdentifierNode *UnqualifiedName) {
1569  NodeList *Head = Arena.alloc<NodeList>();
1570 
1571  Head->N = UnqualifiedName;
1572 
1573  size_t Count = 1;
1574  while (!MangledName.consumeFront("@")) {
1575  ++Count;
1576  NodeList *NewHead = Arena.alloc<NodeList>();
1577  NewHead->Next = Head;
1578  Head = NewHead;
1579 
1580  if (MangledName.empty()) {
1581  Error = true;
1582  return nullptr;
1583  }
1584 
1585  assert(!Error);
1586  IdentifierNode *Elem = demangleNameScopePiece(MangledName);
1587  if (Error)
1588  return nullptr;
1589 
1590  Head->N = Elem;
1591  }
1592 
1593  QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
1594  QN->Components = nodeListToNodeArray(Arena, Head, Count);
1595  return QN;
1596 }
1597 
1598 FuncClass Demangler::demangleFunctionClass(StringView &MangledName) {
1599  switch (MangledName.popFront()) {
1600  case '9':
1602  case 'A':
1603  return FC_Private;
1604  case 'B':
1605  return FuncClass(FC_Private | FC_Far);
1606  case 'C':
1607  return FuncClass(FC_Private | FC_Static);
1608  case 'D':
1609  return FuncClass(FC_Private | FC_Static | FC_Far);
1610  case 'E':
1611  return FuncClass(FC_Private | FC_Virtual);
1612  case 'F':
1613  return FuncClass(FC_Private | FC_Virtual | FC_Far);
1614  case 'G':
1616  case 'H':
1618  case 'I':
1619  return FuncClass(FC_Protected);
1620  case 'J':
1621  return FuncClass(FC_Protected | FC_Far);
1622  case 'K':
1623  return FuncClass(FC_Protected | FC_Static);
1624  case 'L':
1625  return FuncClass(FC_Protected | FC_Static | FC_Far);
1626  case 'M':
1627  return FuncClass(FC_Protected | FC_Virtual);
1628  case 'N':
1630  case 'O':
1632  case 'P':
1634  case 'Q':
1635  return FuncClass(FC_Public);
1636  case 'R':
1637  return FuncClass(FC_Public | FC_Far);
1638  case 'S':
1639  return FuncClass(FC_Public | FC_Static);
1640  case 'T':
1641  return FuncClass(FC_Public | FC_Static | FC_Far);
1642  case 'U':
1643  return FuncClass(FC_Public | FC_Virtual);
1644  case 'V':
1645  return FuncClass(FC_Public | FC_Virtual | FC_Far);
1646  case 'W':
1648  case 'X':
1650  case 'Y':
1651  return FuncClass(FC_Global);
1652  case 'Z':
1653  return FuncClass(FC_Global | FC_Far);
1654  case '$': {
1656  if (MangledName.consumeFront('R'))
1657  VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx);
1658  if (MangledName.empty())
1659  break;
1660  switch (MangledName.popFront()) {
1661  case '0':
1662  return FuncClass(FC_Private | FC_Virtual | VFlag);
1663  case '1':
1664  return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far);
1665  case '2':
1666  return FuncClass(FC_Protected | FC_Virtual | VFlag);
1667  case '3':
1668  return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far);
1669  case '4':
1670  return FuncClass(FC_Public | FC_Virtual | VFlag);
1671  case '5':
1672  return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far);
1673  }
1674  }
1675  }
1676 
1677  Error = true;
1678  return FC_Public;
1679 }
1680 
1681 CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
1682  if (MangledName.empty()) {
1683  Error = true;
1684  return CallingConv::None;
1685  }
1686 
1687  switch (MangledName.popFront()) {
1688  case 'A':
1689  case 'B':
1690  return CallingConv::Cdecl;
1691  case 'C':
1692  case 'D':
1693  return CallingConv::Pascal;
1694  case 'E':
1695  case 'F':
1696  return CallingConv::Thiscall;
1697  case 'G':
1698  case 'H':
1699  return CallingConv::Stdcall;
1700  case 'I':
1701  case 'J':
1702  return CallingConv::Fastcall;
1703  case 'M':
1704  case 'N':
1705  return CallingConv::Clrcall;
1706  case 'O':
1707  case 'P':
1708  return CallingConv::Eabi;
1709  case 'Q':
1710  return CallingConv::Vectorcall;
1711  case 'S':
1712  return CallingConv::Swift;
1713  case 'W':
1714  return CallingConv::SwiftAsync;
1715  }
1716 
1717  return CallingConv::None;
1718 }
1719 
1720 StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) {
1721  assert(MangledName.front() >= '0' && MangledName.front() <= '4');
1722 
1723  switch (MangledName.popFront()) {
1724  case '0':
1725  return StorageClass::PrivateStatic;
1726  case '1':
1727  return StorageClass::ProtectedStatic;
1728  case '2':
1729  return StorageClass::PublicStatic;
1730  case '3':
1731  return StorageClass::Global;
1732  case '4':
1733  return StorageClass::FunctionLocalStatic;
1734  }
1736 }
1737 
1738 std::pair<Qualifiers, bool>
1739 Demangler::demangleQualifiers(StringView &MangledName) {
1740  if (MangledName.empty()) {
1741  Error = true;
1742  return std::make_pair(Q_None, false);
1743  }
1744 
1745  switch (MangledName.popFront()) {
1746  // Member qualifiers
1747  case 'Q':
1748  return std::make_pair(Q_None, true);
1749  case 'R':
1750  return std::make_pair(Q_Const, true);
1751  case 'S':
1752  return std::make_pair(Q_Volatile, true);
1753  case 'T':
1754  return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true);
1755  // Non-Member qualifiers
1756  case 'A':
1757  return std::make_pair(Q_None, false);
1758  case 'B':
1759  return std::make_pair(Q_Const, false);
1760  case 'C':
1761  return std::make_pair(Q_Volatile, false);
1762  case 'D':
1763  return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false);
1764  }
1765  Error = true;
1766  return std::make_pair(Q_None, false);
1767 }
1768 
1769 // <variable-type> ::= <type> <cvr-qualifiers>
1770 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
1771 TypeNode *Demangler::demangleType(StringView &MangledName,
1772  QualifierMangleMode QMM) {
1773  Qualifiers Quals = Q_None;
1774  bool IsMember = false;
1775  if (QMM == QualifierMangleMode::Mangle) {
1776  std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1777  } else if (QMM == QualifierMangleMode::Result) {
1778  if (MangledName.consumeFront('?'))
1779  std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1780  }
1781 
1782  if (MangledName.empty()) {
1783  Error = true;
1784  return nullptr;
1785  }
1786 
1787  TypeNode *Ty = nullptr;
1788  if (isTagType(MangledName))
1789  Ty = demangleClassType(MangledName);
1790  else if (isPointerType(MangledName)) {
1791  if (isMemberPointer(MangledName, Error))
1792  Ty = demangleMemberPointerType(MangledName);
1793  else if (!Error)
1794  Ty = demanglePointerType(MangledName);
1795  else
1796  return nullptr;
1797  } else if (isArrayType(MangledName))
1798  Ty = demangleArrayType(MangledName);
1799  else if (isFunctionType(MangledName)) {
1800  if (MangledName.consumeFront("$$A8@@"))
1801  Ty = demangleFunctionType(MangledName, true);
1802  else {
1803  assert(MangledName.startsWith("$$A6"));
1804  MangledName.consumeFront("$$A6");
1805  Ty = demangleFunctionType(MangledName, false);
1806  }
1807  } else if (isCustomType(MangledName)) {
1808  Ty = demangleCustomType(MangledName);
1809  } else {
1810  Ty = demanglePrimitiveType(MangledName);
1811  }
1812 
1813  if (!Ty || Error)
1814  return Ty;
1815  Ty->Quals = Qualifiers(Ty->Quals | Quals);
1816  return Ty;
1817 }
1818 
1819 bool Demangler::demangleThrowSpecification(StringView &MangledName) {
1820  if (MangledName.consumeFront("_E"))
1821  return true;
1822  if (MangledName.consumeFront('Z'))
1823  return false;
1824 
1825  Error = true;
1826  return false;
1827 }
1828 
1829 FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName,
1830  bool HasThisQuals) {
1832 
1833  if (HasThisQuals) {
1834  FTy->Quals = demanglePointerExtQualifiers(MangledName);
1835  FTy->RefQualifier = demangleFunctionRefQualifier(MangledName);
1836  FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
1837  }
1838 
1839  // Fields that appear on both member and non-member functions.
1840  FTy->CallConvention = demangleCallingConvention(MangledName);
1841 
1842  // <return-type> ::= <type>
1843  // ::= @ # structors (they have no declared return type)
1844  bool IsStructor = MangledName.consumeFront('@');
1845  if (!IsStructor)
1846  FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
1847 
1848  FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
1849 
1850  FTy->IsNoexcept = demangleThrowSpecification(MangledName);
1851 
1852  return FTy;
1853 }
1854 
1856 Demangler::demangleFunctionEncoding(StringView &MangledName) {
1857  FuncClass ExtraFlags = FC_None;
1858  if (MangledName.consumeFront("$$J0"))
1859  ExtraFlags = FC_ExternC;
1860 
1861  if (MangledName.empty()) {
1862  Error = true;
1863  return nullptr;
1864  }
1865 
1866  FuncClass FC = demangleFunctionClass(MangledName);
1867  FC = FuncClass(ExtraFlags | FC);
1868 
1869  FunctionSignatureNode *FSN = nullptr;
1870  ThunkSignatureNode *TTN = nullptr;
1871  if (FC & FC_StaticThisAdjust) {
1872  TTN = Arena.alloc<ThunkSignatureNode>();
1873  TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
1874  } else if (FC & FC_VirtualThisAdjust) {
1875  TTN = Arena.alloc<ThunkSignatureNode>();
1876  if (FC & FC_VirtualThisAdjustEx) {
1877  TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName);
1878  TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName);
1879  }
1880  TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName);
1881  TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
1882  }
1883 
1884  if (FC & FC_NoParameterList) {
1885  // This is an extern "C" function whose full signature hasn't been mangled.
1886  // This happens when we need to mangle a local symbol inside of an extern
1887  // "C" function.
1888  FSN = Arena.alloc<FunctionSignatureNode>();
1889  } else {
1890  bool HasThisQuals = !(FC & (FC_Global | FC_Static));
1891  FSN = demangleFunctionType(MangledName, HasThisQuals);
1892  }
1893 
1894  if (Error)
1895  return nullptr;
1896 
1897  if (TTN) {
1898  *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
1899  FSN = TTN;
1900  }
1901  FSN->FunctionClass = FC;
1902 
1904  Symbol->Signature = FSN;
1905  return Symbol;
1906 }
1907 
1908 CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) {
1909  assert(MangledName.startsWith('?'));
1910  MangledName.popFront();
1911 
1912  CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
1913  CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
1914  if (!MangledName.consumeFront('@'))
1915  Error = true;
1916  if (Error)
1917  return nullptr;
1918  return CTN;
1919 }
1920 
1921 // Reads a primitive type.
1922 PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) {
1923  if (MangledName.consumeFront("$$T"))
1924  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr);
1925 
1926  switch (MangledName.popFront()) {
1927  case 'X':
1929  case 'D':
1930  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char);
1931  case 'C':
1932  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar);
1933  case 'E':
1934  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar);
1935  case 'F':
1936  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short);
1937  case 'G':
1938  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort);
1939  case 'H':
1941  case 'I':
1942  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint);
1943  case 'J':
1945  case 'K':
1946  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong);
1947  case 'M':
1949  case 'N':
1951  case 'O':
1952  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble);
1953  case '_': {
1954  if (MangledName.empty()) {
1955  Error = true;
1956  return nullptr;
1957  }
1958  switch (MangledName.popFront()) {
1959  case 'N':
1961  case 'J':
1963  case 'K':
1964  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64);
1965  case 'W':
1966  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar);
1967  case 'Q':
1968  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8);
1969  case 'S':
1970  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16);
1971  case 'U':
1972  return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32);
1973  }
1974  break;
1975  }
1976  }
1977  Error = true;
1978  return nullptr;
1979 }
1980 
1981 TagTypeNode *Demangler::demangleClassType(StringView &MangledName) {
1982  TagTypeNode *TT = nullptr;
1983 
1984  switch (MangledName.popFront()) {
1985  case 'T':
1986  TT = Arena.alloc<TagTypeNode>(TagKind::Union);
1987  break;
1988  case 'U':
1989  TT = Arena.alloc<TagTypeNode>(TagKind::Struct);
1990  break;
1991  case 'V':
1992  TT = Arena.alloc<TagTypeNode>(TagKind::Class);
1993  break;
1994  case 'W':
1995  if (!MangledName.consumeFront('4')) {
1996  Error = true;
1997  return nullptr;
1998  }
1999  TT = Arena.alloc<TagTypeNode>(TagKind::Enum);
2000  break;
2001  default:
2002  assert(false);
2003  }
2004 
2005  TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName);
2006  return TT;
2007 }
2008 
2009 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
2010 // # the E is required for 64-bit non-static pointers
2011 PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) {
2013 
2014  std::tie(Pointer->Quals, Pointer->Affinity) =
2015  demanglePointerCVQualifiers(MangledName);
2016 
2017  if (MangledName.consumeFront("6")) {
2018  Pointer->Pointee = demangleFunctionType(MangledName, false);
2019  return Pointer;
2020  }
2021 
2022  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2023  Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2024 
2025  Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
2026  return Pointer;
2027 }
2028 
2029 PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) {
2031 
2032  std::tie(Pointer->Quals, Pointer->Affinity) =
2033  demanglePointerCVQualifiers(MangledName);
2034  assert(Pointer->Affinity == PointerAffinity::Pointer);
2035 
2036  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2037  Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2038 
2039  // isMemberPointer() only returns true if there is at least one character
2040  // after the qualifiers.
2041  if (MangledName.consumeFront("8")) {
2042  Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2043  Pointer->Pointee = demangleFunctionType(MangledName, true);
2044  } else {
2045  Qualifiers PointeeQuals = Q_None;
2046  bool IsMember = false;
2047  std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
2048  assert(IsMember || Error);
2049  Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2050 
2051  Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
2052  if (Pointer->Pointee)
2053  Pointer->Pointee->Quals = PointeeQuals;
2054  }
2055 
2056  return Pointer;
2057 }
2058 
2059 Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) {
2060  Qualifiers Quals = Q_None;
2061  if (MangledName.consumeFront('E'))
2062  Quals = Qualifiers(Quals | Q_Pointer64);
2063  if (MangledName.consumeFront('I'))
2064  Quals = Qualifiers(Quals | Q_Restrict);
2065  if (MangledName.consumeFront('F'))
2066  Quals = Qualifiers(Quals | Q_Unaligned);
2067 
2068  return Quals;
2069 }
2070 
2071 ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) {
2072  assert(MangledName.front() == 'Y');
2073  MangledName.popFront();
2074 
2075  uint64_t Rank = 0;
2076  bool IsNegative = false;
2077  std::tie(Rank, IsNegative) = demangleNumber(MangledName);
2078  if (IsNegative || Rank == 0) {
2079  Error = true;
2080  return nullptr;
2081  }
2082 
2083  ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>();
2084  NodeList *Head = Arena.alloc<NodeList>();
2085  NodeList *Tail = Head;
2086 
2087  for (uint64_t I = 0; I < Rank; ++I) {
2088  uint64_t D = 0;
2089  std::tie(D, IsNegative) = demangleNumber(MangledName);
2090  if (Error || IsNegative) {
2091  Error = true;
2092  return nullptr;
2093  }
2094  Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative);
2095  if (I + 1 < Rank) {
2096  Tail->Next = Arena.alloc<NodeList>();
2097  Tail = Tail->Next;
2098  }
2099  }
2100  ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank);
2101 
2102  if (MangledName.consumeFront("$$C")) {
2103  bool IsMember = false;
2104  std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName);
2105  if (IsMember) {
2106  Error = true;
2107  return nullptr;
2108  }
2109  }
2110 
2111  ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
2112  return ATy;
2113 }
2114 
2115 // Reads a function's parameters.
2116 NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName,
2117  bool &IsVariadic) {
2118  // Empty parameter list.
2119  if (MangledName.consumeFront('X'))
2120  return nullptr;
2121 
2122  NodeList *Head = Arena.alloc<NodeList>();
2123  NodeList **Current = &Head;
2124  size_t Count = 0;
2125  while (!Error && !MangledName.startsWith('@') &&
2126  !MangledName.startsWith('Z')) {
2127  ++Count;
2128 
2129  if (startsWithDigit(MangledName)) {
2130  size_t N = MangledName[0] - '0';
2131  if (N >= Backrefs.FunctionParamCount) {
2132  Error = true;
2133  return nullptr;
2134  }
2135  MangledName = MangledName.dropFront();
2136 
2137  *Current = Arena.alloc<NodeList>();
2138  (*Current)->N = Backrefs.FunctionParams[N];
2139  Current = &(*Current)->Next;
2140  continue;
2141  }
2142 
2143  size_t OldSize = MangledName.size();
2144 
2145  *Current = Arena.alloc<NodeList>();
2146  TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop);
2147  if (!TN || Error)
2148  return nullptr;
2149 
2150  (*Current)->N = TN;
2151 
2152  size_t CharsConsumed = OldSize - MangledName.size();
2153  assert(CharsConsumed != 0);
2154 
2155  // Single-letter types are ignored for backreferences because memorizing
2156  // them doesn't save anything.
2157  if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1)
2158  Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN;
2159 
2160  Current = &(*Current)->Next;
2161  }
2162 
2163  if (Error)
2164  return nullptr;
2165 
2166  NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count);
2167  // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
2168  // list or '@' (non variadic). Careful not to consume "@Z", as in that case
2169  // the following Z could be a throw specifier.
2170  if (MangledName.consumeFront('@'))
2171  return NA;
2172 
2173  if (MangledName.consumeFront('Z')) {
2174  IsVariadic = true;
2175  return NA;
2176  }
2177 
2179 }
2180 
2181 NodeArrayNode *
2182 Demangler::demangleTemplateParameterList(StringView &MangledName) {
2183  NodeList *Head = nullptr;
2184  NodeList **Current = &Head;
2185  size_t Count = 0;
2186 
2187  while (!MangledName.startsWith('@')) {
2188  if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
2189  MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) {
2190  // parameter pack separator
2191  continue;
2192  }
2193 
2194  ++Count;
2195 
2196  // Template parameter lists don't participate in back-referencing.
2197  *Current = Arena.alloc<NodeList>();
2198 
2199  NodeList &TP = **Current;
2200 
2201  TemplateParameterReferenceNode *TPRN = nullptr;
2202  if (MangledName.consumeFront("$$Y")) {
2203  // Template alias
2204  TP.N = demangleFullyQualifiedTypeName(MangledName);
2205  } else if (MangledName.consumeFront("$$B")) {
2206  // Array
2207  TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2208  } else if (MangledName.consumeFront("$$C")) {
2209  // Type has qualifiers.
2210  TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
2211  } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") ||
2212  MangledName.startsWith("$I") || MangledName.startsWith("$J")) {
2213  // Pointer to member
2214  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2215  TPRN->IsMemberPointer = true;
2216 
2217  MangledName = MangledName.dropFront();
2218  // 1 - single inheritance <name>
2219  // H - multiple inheritance <name> <number>
2220  // I - virtual inheritance <name> <number> <number>
2221  // J - unspecified inheritance <name> <number> <number> <number>
2222  char InheritanceSpecifier = MangledName.popFront();
2223  SymbolNode *S = nullptr;
2224  if (MangledName.startsWith('?')) {
2225  S = parse(MangledName);
2226  if (Error || !S->Name) {
2227  Error = true;
2228  return nullptr;
2229  }
2230  memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
2231  }
2232 
2233  switch (InheritanceSpecifier) {
2234  case 'J':
2235  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2236  demangleSigned(MangledName);
2238  case 'I':
2239  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2240  demangleSigned(MangledName);
2242  case 'H':
2243  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2244  demangleSigned(MangledName);
2246  case '1':
2247  break;
2248  default:
2250  }
2251  TPRN->Affinity = PointerAffinity::Pointer;
2252  TPRN->Symbol = S;
2253  } else if (MangledName.startsWith("$E?")) {
2254  MangledName.consumeFront("$E");
2255  // Reference to symbol
2256  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2257  TPRN->Symbol = parse(MangledName);
2258  TPRN->Affinity = PointerAffinity::Reference;
2259  } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) {
2260  TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
2261 
2262  // Data member pointer.
2263  MangledName = MangledName.dropFront();
2264  char InheritanceSpecifier = MangledName.popFront();
2265 
2266  switch (InheritanceSpecifier) {
2267  case 'G':
2268  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2269  demangleSigned(MangledName);
2271  case 'F':
2272  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2273  demangleSigned(MangledName);
2274  TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
2275  demangleSigned(MangledName);
2276  break;
2277  default:
2279  }
2280  TPRN->IsMemberPointer = true;
2281 
2282  } else if (MangledName.consumeFront("$0")) {
2283  // Integral non-type template parameter
2284  bool IsNegative = false;
2285  uint64_t Value = 0;
2286  std::tie(Value, IsNegative) = demangleNumber(MangledName);
2287 
2288  TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative);
2289  } else {
2290  TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2291  }
2292  if (Error)
2293  return nullptr;
2294 
2295  Current = &TP.Next;
2296  }
2297 
2298  // The loop above returns nullptr on Error.
2299  assert(!Error);
2300 
2301  // Template parameter lists cannot be variadic, so it can only be terminated
2302  // by @ (as opposed to 'Z' in the function parameter case).
2303  assert(MangledName.startsWith('@')); // The above loop exits only on '@'.
2304  MangledName.consumeFront('@');
2305  return nodeListToNodeArray(Arena, Head, Count);
2306 }
2307 
2308 void Demangler::dumpBackReferences() {
2309  std::printf("%d function parameter backreferences\n",
2310  (int)Backrefs.FunctionParamCount);
2311 
2312  // Create an output stream so we can render each type.
2313  OutputBuffer OB;
2314  if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
2315  std::terminate();
2316  for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
2317  OB.setCurrentPosition(0);
2318 
2319  TypeNode *T = Backrefs.FunctionParams[I];
2320  T->output(OB, OF_Default);
2321 
2322  StringView B = OB;
2323  std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.begin());
2324  }
2325  std::free(OB.getBuffer());
2326 
2327  if (Backrefs.FunctionParamCount > 0)
2328  std::printf("\n");
2329  std::printf("%d name backreferences\n", (int)Backrefs.NamesCount);
2330  for (size_t I = 0; I < Backrefs.NamesCount; ++I) {
2331  std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(),
2332  Backrefs.Names[I]->Name.begin());
2333  }
2334  if (Backrefs.NamesCount > 0)
2335  std::printf("\n");
2336 }
2337 
2338 char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
2339  char *Buf, size_t *N,
2340  int *Status, MSDemangleFlags Flags) {
2341  Demangler D;
2342  OutputBuffer OB;
2343 
2344  StringView Name{MangledName};
2345  SymbolNode *AST = D.parse(Name);
2346  if (!D.Error && NMangled)
2347  *NMangled = Name.begin() - MangledName;
2348 
2349  if (Flags & MSDF_DumpBackrefs)
2350  D.dumpBackReferences();
2351 
2352  OutputFlags OF = OF_Default;
2353  if (Flags & MSDF_NoCallingConvention)
2355  if (Flags & MSDF_NoAccessSpecifier)
2356  OF = OutputFlags(OF | OF_NoAccessSpecifier);
2357  if (Flags & MSDF_NoReturnType)
2358  OF = OutputFlags(OF | OF_NoReturnType);
2359  if (Flags & MSDF_NoMemberType)
2360  OF = OutputFlags(OF | OF_NoMemberType);
2361  if (Flags & MSDF_NoVariableType)
2362  OF = OutputFlags(OF | OF_NoVariableType);
2363 
2364  int InternalStatus = demangle_success;
2365  if (D.Error)
2366  InternalStatus = demangle_invalid_mangled_name;
2367  else if (!initializeOutputBuffer(Buf, N, OB, 1024))
2368  InternalStatus = demangle_memory_alloc_failure;
2369  else {
2370  AST->output(OB, OF);
2371  OB += '\0';
2372  if (N != nullptr)
2373  *N = OB.getCurrentPosition();
2374  Buf = OB.getBuffer();
2375  }
2376 
2377  if (Status)
2378  *Status = InternalStatus;
2379  return InternalStatus == demangle_success ? Buf : nullptr;
2380 }
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::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::demangle_invalid_mangled_name
@ demangle_invalid_mangled_name
Definition: Demangle.h:26
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:18
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
Int64
@ Int64
Definition: TargetLibraryInfo.cpp:52
llvm::MSDF_NoAccessSpecifier
@ MSDF_NoAccessSpecifier
Definition: Demangle.h:37
T
writeHexDigit
static void writeHexDigit(char *Buffer, uint8_t Digit)
Definition: MicrosoftDemangle.cpp:1106
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:1243
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:266
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:1029
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::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::X86II::OB
@ OB
Definition: X86BaseInfo.h:801
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::CallingConv::Swift
@ Swift
Calling convention for Swift.
Definition: CallingConv.h:69
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:1137
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
Long
@ Long
Definition: TargetLibraryInfo.cpp:50
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
Int
@ Int
Definition: TargetLibraryInfo.cpp:48
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:1554
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:1209
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
Index
uint32_t Index
Definition: ELFObjHandler.cpp:82
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:1196
llvm::ms_demangle::SpecialIntrinsicKind::Typeof
@ Typeof
llvm::MD5
Definition: MD5.h:41
Qualifiers
Qualifiers
Definition: ItaniumDemangle.h:393
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)
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:1027
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:1111
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::ms_demangle::FunctionRefQualifier
FunctionRefQualifier
Definition: MicrosoftDemangleNodes.h:55
llvm::object::Comma
@ Comma
Definition: COFFModuleDefinition.cpp:35
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
Bool
@ Bool
Definition: TargetLibraryInfo.cpp:45
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:2338
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::demangle_success
@ demangle_success
Definition: Demangle.h:28
llvm::ms_demangle::PointerAffinity::Reference
@ Reference
llvm::ms_demangle::StructorIdentifierNode
Definition: MicrosoftDemangleNodes.h:429
llvm::demangle_memory_alloc_failure
@ demangle_memory_alloc_failure
Definition: Demangle.h:27
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:149
llvm::ms_demangle::FC_ExternC
@ FC_ExternC
Definition: MicrosoftDemangleNodes.h:217
countTrailingNullBytes
static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length)
Definition: MicrosoftDemangle.cpp:1185
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
Struct
@ Struct
Definition: TargetLibraryInfo.cpp:61
llvm::ms_demangle::VariableSymbolNode
Definition: MicrosoftDemangleNodes.h:609
llvm::ms_demangle::NBB_Template
@ NBB_Template
Definition: MicrosoftDemangle.h:129
MicrosoftDemangle.h
llvm::CallingConv::Tail
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition: CallingConv.h:76
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:241
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
Void
@ Void
Definition: TargetLibraryInfo.cpp:44
llvm::ms_demangle::LocalStaticGuardIdentifierNode::ScopeIndex
uint32_t ScopeIndex
Definition: MicrosoftDemangleNodes.h:416
llvm::ms_demangle::PointerAffinity::RValueReference
@ RValueReference
llvm::ms_demangle::FunctionSymbolNode
Definition: MicrosoftDemangleNodes.h:618