LLVM  9.0.0svn
MicrosoftDemangleNodes.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 //===----------------------------------------------------------------------===//
12 
15 #include "llvm/Demangle/Utility.h"
16 #include <cctype>
17 #include <string>
18 
19 using namespace llvm;
20 using namespace ms_demangle;
21 
22 #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
23  case Enum::Value: \
24  OS << Desc; \
25  break;
26 
27 // Writes a space if the last token does not end with a punctuation.
28 static void outputSpaceIfNecessary(OutputStream &OS) {
29  if (OS.empty())
30  return;
31 
32  char C = OS.back();
33  if (std::isalnum(C) || C == '>')
34  OS << " ";
35 }
36 
37 static bool outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
38  switch (Q) {
39  case Q_Const:
40  OS << "const";
41  return true;
42  case Q_Volatile:
43  OS << "volatile";
44  return true;
45  case Q_Restrict:
46  OS << "__restrict";
47  return true;
48  default:
49  break;
50  }
51  return false;
52 }
53 
54 static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
55  Qualifiers Mask, bool NeedSpace) {
56  if (!(Q & Mask))
57  return NeedSpace;
58 
59  if (NeedSpace)
60  OS << " ";
61 
62  outputSingleQualifier(OS, Mask);
63  return true;
64 }
65 
66 static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
67  bool SpaceAfter) {
68  if (Q == Q_None)
69  return;
70 
71  size_t Pos1 = OS.getCurrentPosition();
72  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
73  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
74  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
75  size_t Pos2 = OS.getCurrentPosition();
76  if (SpaceAfter && Pos2 > Pos1)
77  OS << " ";
78 }
79 
80 static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
82 
83  switch (CC) {
84  case CallingConv::Cdecl:
85  OS << "__cdecl";
86  break;
88  OS << "__fastcall";
89  break;
91  OS << "__pascal";
92  break;
94  OS << "__regcall";
95  break;
97  OS << "__stdcall";
98  break;
100  OS << "__thiscall";
101  break;
102  case CallingConv::Eabi:
103  OS << "__eabi";
104  break;
106  OS << "__vectorcall";
107  break;
109  OS << "__clrcall";
110  break;
111  default:
112  break;
113  }
114 }
115 
116 std::string Node::toString(OutputFlags Flags) const {
117  OutputStream OS;
118  initializeOutputStream(nullptr, nullptr, OS, 1024);
119  this->output(OS, Flags);
120  OS << '\0';
121  return {OS.getBuffer()};
122 }
123 
124 void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
125 
126 void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
127  switch (PrimKind) {
132  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
136  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
138  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
140  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
142  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
147  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
148  }
149  outputQualifiers(OS, Quals, true, false);
150 }
151 
152 void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
153  output(OS, Flags, ", ");
154 }
155 
156 void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
157  StringView Separator) const {
158  if (Count == 0)
159  return;
160  if (Nodes[0])
161  Nodes[0]->output(OS, Flags);
162  for (size_t I = 1; I < Count; ++I) {
163  OS << Separator;
164  Nodes[I]->output(OS, Flags);
165  }
166 }
167 
168 void EncodedStringLiteralNode::output(OutputStream &OS,
169  OutputFlags Flags) const {
170  switch (Char) {
171  case CharKind::Wchar:
172  OS << "L\"";
173  break;
174  case CharKind::Char:
175  OS << "\"";
176  break;
177  case CharKind::Char16:
178  OS << "u\"";
179  break;
180  case CharKind::Char32:
181  OS << "U\"";
182  break;
183  }
184  OS << DecodedString << "\"";
185  if (IsTruncated)
186  OS << "...";
187 }
188 
189 void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
190  if (IsNegative)
191  OS << '-';
192  OS << Value;
193 }
194 
196  OutputFlags Flags) const {
197  if (ThunkOffsetCount > 0)
198  OS << "{";
199  else if (Affinity == PointerAffinity::Pointer)
200  OS << "&";
201 
202  if (Symbol) {
203  Symbol->output(OS, Flags);
204  if (ThunkOffsetCount > 0)
205  OS << ", ";
206  }
207 
208  if (ThunkOffsetCount > 0)
209  OS << ThunkOffsets[0];
210  for (int I = 1; I < ThunkOffsetCount; ++I) {
211  OS << ", " << ThunkOffsets[I];
212  }
213  if (ThunkOffsetCount > 0)
214  OS << "}";
215 }
216 
218  OutputFlags Flags) const {
219  if (!TemplateParams)
220  return;
221  OS << "<";
222  TemplateParams->output(OS, Flags);
223  OS << ">";
224 }
225 
227  OutputFlags Flags) const {
228  if (IsDestructor)
229  OS << "`dynamic atexit destructor for ";
230  else
231  OS << "`dynamic initializer for ";
232 
233  if (Variable) {
234  OS << "`";
235  Variable->output(OS, Flags);
236  OS << "''";
237  } else {
238  OS << "'";
239  Name->output(OS, Flags);
240  OS << "''";
241  }
242 }
243 
244 void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
245  OS << Name;
246  outputTemplateParameters(OS, Flags);
247 }
248 
250  OutputFlags Flags) const {
251  switch (Operator) {
261  "operator[]");
270  "operator->*");
277  "operator>=");
293  "operator&=");
295  "operator|=");
297  "operator^=");
300  "`vector deleting dtor'");
302  "`default ctor closure'");
304  "`scalar deleting dtor'");
306  "`vector ctor iterator'");
308  "`vector dtor iterator'");
310  "`vector vbase ctor iterator'");
312  "`virtual displacement map'");
314  "`eh vector ctor iterator'");
316  "`eh vector dtor iterator'");
318  "`eh vector vbase ctor iterator'");
320  "`copy ctor closure'");
322  "`local vftable ctor closure'");
325  "operator delete[]");
327  "`managed vector ctor iterator'");
329  "`managed vector dtor iterator'");
331  "`EH vector copy ctor iterator'");
333  "`EH vector vbase copy ctor iterator'");
335  "`vector copy ctor iterator'");
337  "`vector vbase copy constructor iterator'");
339  "`managed vector vbase copy constructor iterator'");
344  break;
345  }
346  outputTemplateParameters(OS, Flags);
347 }
348 
350  OutputFlags Flags) const {
351  OS << "`local static guard'";
352  if (ScopeIndex > 0)
353  OS << "{" << ScopeIndex << "}";
354 }
355 
357  OutputFlags Flags) const {
358  OS << "operator";
359  outputTemplateParameters(OS, Flags);
360  OS << " ";
361  TargetType->output(OS, Flags);
362 }
363 
364 void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
365  if (IsDestructor)
366  OS << "~";
367  Class->output(OS, Flags);
368  outputTemplateParameters(OS, Flags);
369 }
370 
372  OutputFlags Flags) const {
373  OS << "operator \"\"" << Name;
374  outputTemplateParameters(OS, Flags);
375 }
376 
377 void FunctionSignatureNode::outputPre(OutputStream &OS,
378  OutputFlags Flags) const {
379  if (FunctionClass & FC_Public)
380  OS << "public: ";
381  if (FunctionClass & FC_Protected)
382  OS << "protected: ";
383  if (FunctionClass & FC_Private)
384  OS << "private: ";
385 
386  if (!(FunctionClass & FC_Global)) {
387  if (FunctionClass & FC_Static)
388  OS << "static ";
389  }
390  if (FunctionClass & FC_Virtual)
391  OS << "virtual ";
392 
393  if (FunctionClass & FC_ExternC)
394  OS << "extern \"C\" ";
395 
396  if (ReturnType) {
397  ReturnType->outputPre(OS, Flags);
398  OS << " ";
399  }
400 
401  if (!(Flags & OF_NoCallingConvention))
402  outputCallingConvention(OS, CallConvention);
403 }
404 
405 void FunctionSignatureNode::outputPost(OutputStream &OS,
406  OutputFlags Flags) const {
407  if (!(FunctionClass & FC_NoParameterList)) {
408  OS << "(";
409  if (Params)
410  Params->output(OS, Flags);
411  else
412  OS << "void";
413  OS << ")";
414  }
415 
416  if (Quals & Q_Const)
417  OS << " const";
418  if (Quals & Q_Volatile)
419  OS << " volatile";
420  if (Quals & Q_Restrict)
421  OS << " __restrict";
422  if (Quals & Q_Unaligned)
423  OS << " __unaligned";
424 
425  if (IsNoexcept)
426  OS << " noexcept";
427 
428  if (RefQualifier == FunctionRefQualifier::Reference)
429  OS << " &";
430  else if (RefQualifier == FunctionRefQualifier::RValueReference)
431  OS << " &&";
432 
433  if (ReturnType)
434  ReturnType->outputPost(OS, Flags);
435 }
436 
437 void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
438  OS << "[thunk]: ";
439 
441 }
442 
443 void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
444  if (FunctionClass & FC_StaticThisAdjust) {
445  OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
446  } else if (FunctionClass & FC_VirtualThisAdjust) {
447  if (FunctionClass & FC_VirtualThisAdjustEx) {
448  OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
449  << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
450  << ", " << ThisAdjust.StaticOffset << "}'";
451  } else {
452  OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
453  << ThisAdjust.StaticOffset << "}'";
454  }
455  }
456 
458 }
459 
460 void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
461  if (Pointee->kind() == NodeKind::FunctionSignature) {
462  // If this is a pointer to a function, don't output the calling convention.
463  // It needs to go inside the parentheses.
464  const FunctionSignatureNode *Sig =
465  static_cast<const FunctionSignatureNode *>(Pointee);
467  } else
468  Pointee->outputPre(OS, Flags);
469 
471 
472  if (Quals & Q_Unaligned)
473  OS << "__unaligned ";
474 
475  if (Pointee->kind() == NodeKind::ArrayType) {
476  OS << "(";
477  } else if (Pointee->kind() == NodeKind::FunctionSignature) {
478  OS << "(";
479  const FunctionSignatureNode *Sig =
480  static_cast<const FunctionSignatureNode *>(Pointee);
482  OS << " ";
483  }
484 
485  if (ClassParent) {
486  ClassParent->output(OS, Flags);
487  OS << "::";
488  }
489 
490  switch (Affinity) {
492  OS << "*";
493  break;
495  OS << "&";
496  break;
498  OS << "&&";
499  break;
500  default:
501  assert(false);
502  }
503  outputQualifiers(OS, Quals, false, false);
504 }
505 
506 void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
507  if (Pointee->kind() == NodeKind::ArrayType ||
508  Pointee->kind() == NodeKind::FunctionSignature)
509  OS << ")";
510 
511  Pointee->outputPost(OS, Flags);
512 }
513 
514 void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
515  if (!(Flags & OF_NoTagSpecifier)) {
516  switch (Tag) {
521  }
522  OS << " ";
523  }
524  QualifiedName->output(OS, Flags);
525  outputQualifiers(OS, Quals, true, false);
526 }
527 
528 void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
529 
530 void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
531  ElementType->outputPre(OS, Flags);
532  outputQualifiers(OS, Quals, true, false);
533 }
534 
535 void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
536  Node *N) const {
538  IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
539  if (ILN->Value != 0)
540  ILN->output(OS, Flags);
541 }
542 
544  OutputFlags Flags) const {
545  if (Dimensions->Count == 0)
546  return;
547 
548  outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
549  for (size_t I = 1; I < Dimensions->Count; ++I) {
550  OS << "][";
551  outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
552  }
553 }
554 
555 void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
556  OS << "[";
557  outputDimensionsImpl(OS, Flags);
558  OS << "]";
559 
560  ElementType->outputPost(OS, Flags);
561 }
562 
563 void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
564  Name->output(OS, Flags);
565 }
566 
567 void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
568  Signature->outputPre(OS, Flags);
570  Name->output(OS, Flags);
571  Signature->outputPost(OS, Flags);
572 }
573 
574 void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
575  switch (SC) {
577  OS << "private: static ";
578  break;
580  OS << "public: static ";
581  break;
583  OS << "protected: static ";
584  break;
585  default:
586  break;
587  }
588 
589  if (Type) {
590  Type->outputPre(OS, Flags);
592  }
593  Name->output(OS, Flags);
594  if (Type)
595  Type->outputPost(OS, Flags);
596 }
597 
598 void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
599  Identifier->output(OS, Flags);
600 }
601 void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
602 
603 void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
604  Components->output(OS, Flags, "::");
605 }
606 
608  OutputFlags Flags) const {
609  OS << "`RTTI Base Class Descriptor at (";
610  OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
611  << this->Flags;
612  OS << ")'";
613 }
614 
616  OutputFlags Flags) const {
617  Name->output(OS, Flags);
618 }
619 
620 void VcallThunkIdentifierNode::output(OutputStream &OS,
621  OutputFlags Flags) const {
622  OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
623 }
624 
625 void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
626  outputQualifiers(OS, Quals, false, true);
627  Name->output(OS, Flags);
628  if (TargetName) {
629  OS << "{for `";
630  TargetName->output(OS, Flags);
631  OS << "'}";
632  }
633  return;
634 }
uint64_t CallInst * C
void outputQuals(bool SpaceBefore, bool SpaceAfter) const
void output(OutputStream &OS, OutputFlags Flags) const override
void outputPost(OutputStream &OS, OutputFlags Flags) const
void output(OutputStream &OS, OutputFlags Flags) const override
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static void outputSpaceIfNecessary(OutputStream &OS)
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
static void outputCallingConvention(OutputStream &OS, CallingConv CC)
void outputPre(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void outputPost(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const
static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q, Qualifiers Mask, bool NeedSpace)
void outputPre(OutputStream &OS, OutputFlags Flags) const
void outputPost(OutputStream &OS, OutputFlags Flags) const override
void outputPre(OutputStream &OS, OutputFlags Flags) const override
void outputPost(OutputStream &OS, OutputFlags Flags) const
std::string toString(OutputFlags Flags=OF_Default) const
void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
void outputPre(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc)
void outputPre(OutputStream &OS, OutputFlags Flags) const
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
This is a utility class that provides an abstraction for the common functionality between Instruction...
Definition: Operator.h:30
CHAIN = SC CHAIN, Imm128 - System call.
Qualifiers
void output(OutputStream &OS, OutputFlags Flags) const override
void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const
void output(OutputStream &OS, OutputFlags Flags) const override
static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore, bool SpaceAfter)
void outputPre(OutputStream &OS, OutputFlags Flags) const override
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
void output(OutputStream &OS, OutputFlags Flags) const override
void output(OutputStream &OS, OutputFlags Flags) const override
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void output(OutputStream &OS, OutputFlags Flags) const override
LLVM Value Representation.
Definition: Value.h:72
void output(OutputStream &OS, OutputFlags Flags) const override
bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, size_t InitSize)
Definition: Utility.h:174
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:80
virtual void output(OutputStream &OS, OutputFlags Flags) const =0
void outputPost(OutputStream &OS, OutputFlags Flags) const override
static bool outputSingleQualifier(OutputStream &OS, Qualifiers Q)
void output(OutputStream &OS, OutputFlags Flags) const override
void outputPost(OutputStream &OS, OutputFlags Flags) const override
void outputPre(OutputStream &OS, OutputFlags Flags) const