LLVM  8.0.1
MicrosoftDemangleNodes.cpp
Go to the documentation of this file.
1 //===- MicrosoftDemangle.cpp ----------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a demangler for MSVC-style mangled symbols.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/Demangle/Compiler.h"
16 #include "llvm/Demangle/Utility.h"
17 #include <cctype>
18 #include <string>
19 
20 using namespace llvm;
21 using namespace ms_demangle;
22 
23 #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
24  case Enum::Value: \
25  OS << Desc; \
26  break;
27 
28 // Writes a space if the last token does not end with a punctuation.
30  if (OS.empty())
31  return;
32 
33  char C = OS.back();
34  if (std::isalnum(C) || C == '>')
35  OS << " ";
36 }
37 
39  switch (Q) {
40  case Q_Const:
41  OS << "const";
42  return true;
43  case Q_Volatile:
44  OS << "volatile";
45  return true;
46  case Q_Restrict:
47  OS << "__restrict";
48  return true;
49  default:
50  break;
51  }
52  return false;
53 }
54 
56  Qualifiers Mask, bool NeedSpace) {
57  if (!(Q & Mask))
58  return NeedSpace;
59 
60  if (NeedSpace)
61  OS << " ";
62 
63  outputSingleQualifier(OS, Mask);
64  return true;
65 }
66 
67 static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
68  bool SpaceAfter) {
69  if (Q == Q_None)
70  return;
71 
72  size_t Pos1 = OS.getCurrentPosition();
73  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
74  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
75  SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
76  size_t Pos2 = OS.getCurrentPosition();
77  if (SpaceAfter && Pos2 > Pos1)
78  OS << " ";
79 }
80 
83 
84  switch (CC) {
85  case CallingConv::Cdecl:
86  OS << "__cdecl";
87  break;
89  OS << "__fastcall";
90  break;
92  OS << "__pascal";
93  break;
95  OS << "__regcall";
96  break;
98  OS << "__stdcall";
99  break;
101  OS << "__thiscall";
102  break;
103  case CallingConv::Eabi:
104  OS << "__eabi";
105  break;
107  OS << "__vectorcall";
108  break;
110  OS << "__clrcall";
111  break;
112  default:
113  break;
114  }
115 }
116 
117 std::string Node::toString(OutputFlags Flags) const {
118  OutputStream OS;
119  initializeOutputStream(nullptr, nullptr, OS, 1024);
120  this->output(OS, Flags);
121  OS << '\0';
122  return {OS.getBuffer()};
123 }
124 
125 void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
126 
128  switch (PrimKind) {
133  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
137  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
139  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
141  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
143  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
148  OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
149  }
150  outputQualifiers(OS, Quals, true, false);
151 }
152 
154  output(OS, Flags, ", ");
155 }
156 
158  StringView Separator) const {
159  if (Count == 0)
160  return;
161  if (Nodes[0])
162  Nodes[0]->output(OS, Flags);
163  for (size_t I = 1; I < Count; ++I) {
164  OS << Separator;
165  Nodes[I]->output(OS, Flags);
166  }
167 }
168 
170  OutputFlags Flags) const {
171  switch (Char) {
172  case CharKind::Wchar:
173  OS << "L\"";
174  break;
175  case CharKind::Char:
176  OS << "\"";
177  break;
178  case CharKind::Char16:
179  OS << "u\"";
180  break;
181  case CharKind::Char32:
182  OS << "U\"";
183  break;
184  }
185  OS << DecodedString << "\"";
186  if (IsTruncated)
187  OS << "...";
188 }
189 
191  if (IsNegative)
192  OS << '-';
193  OS << Value;
194 }
195 
197  OutputFlags Flags) const {
198  if (ThunkOffsetCount > 0)
199  OS << "{";
200  else if (Affinity == PointerAffinity::Pointer)
201  OS << "&";
202 
203  if (Symbol) {
204  Symbol->output(OS, Flags);
205  if (ThunkOffsetCount > 0)
206  OS << ", ";
207  }
208 
209  if (ThunkOffsetCount > 0)
210  OS << ThunkOffsets[0];
211  for (int I = 1; I < ThunkOffsetCount; ++I) {
212  OS << ", " << ThunkOffsets[I];
213  }
214  if (ThunkOffsetCount > 0)
215  OS << "}";
216 }
217 
219  OutputFlags Flags) const {
220  if (!TemplateParams)
221  return;
222  OS << "<";
223  TemplateParams->output(OS, Flags);
224  OS << ">";
225 }
226 
228  OutputFlags Flags) const {
229  if (IsDestructor)
230  OS << "`dynamic atexit destructor for ";
231  else
232  OS << "`dynamic initializer for ";
233 
234  if (Variable) {
235  OS << "`";
236  Variable->output(OS, Flags);
237  OS << "''";
238  } else {
239  OS << "'";
240  Name->output(OS, Flags);
241  OS << "''";
242  }
243 }
244 
246  OS << Name;
247  outputTemplateParameters(OS, Flags);
248 }
249 
251  OutputFlags Flags) const {
252  switch (Operator) {
262  "operator[]");
271  "operator->*");
278  "operator>=");
294  "operator&=");
296  "operator|=");
298  "operator^=");
301  "`vector deleting dtor'");
303  "`default ctor closure'");
305  "`scalar deleting dtor'");
307  "`vector ctor iterator'");
309  "`vector dtor iterator'");
311  "`vector vbase ctor iterator'");
313  "`virtual displacement map'");
315  "`eh vector ctor iterator'");
317  "`eh vector dtor iterator'");
319  "`eh vector vbase ctor iterator'");
321  "`copy ctor closure'");
323  "`local vftable ctor closure'");
326  "operator delete[]");
328  "`managed vector ctor iterator'");
330  "`managed vector dtor iterator'");
332  "`EH vector copy ctor iterator'");
334  "`EH vector vbase copy ctor iterator'");
336  "`vector copy ctor iterator'");
338  "`vector vbase copy constructor iterator'");
340  "`managed vector vbase copy constructor iterator'");
345  break;
346  }
347  outputTemplateParameters(OS, Flags);
348 }
349 
351  OutputFlags Flags) const {
352  OS << "`local static guard'";
353  if (ScopeIndex > 0)
354  OS << "{" << ScopeIndex << "}";
355 }
356 
358  OutputFlags Flags) const {
359  OS << "operator";
360  outputTemplateParameters(OS, Flags);
361  OS << " ";
362  TargetType->output(OS, Flags);
363 }
364 
366  if (IsDestructor)
367  OS << "~";
368  Class->output(OS, Flags);
369  outputTemplateParameters(OS, Flags);
370 }
371 
373  OutputFlags Flags) const {
374  OS << "operator \"\"" << Name;
375  outputTemplateParameters(OS, Flags);
376 }
377 
379  OutputFlags Flags) const {
380  if (FunctionClass & FC_Public)
381  OS << "public: ";
382  if (FunctionClass & FC_Protected)
383  OS << "protected: ";
384  if (FunctionClass & FC_Private)
385  OS << "private: ";
386 
387  if (!(FunctionClass & FC_Global)) {
388  if (FunctionClass & FC_Static)
389  OS << "static ";
390  }
391  if (FunctionClass & FC_Virtual)
392  OS << "virtual ";
393 
394  if (FunctionClass & FC_ExternC)
395  OS << "extern \"C\" ";
396 
397  if (ReturnType) {
398  ReturnType->outputPre(OS, Flags);
399  OS << " ";
400  }
401 
402  if (!(Flags & OF_NoCallingConvention))
403  outputCallingConvention(OS, CallConvention);
404 }
405 
407  OutputFlags Flags) const {
408  if (!(FunctionClass & FC_NoParameterList)) {
409  OS << "(";
410  if (Params)
411  Params->output(OS, Flags);
412  else
413  OS << "void";
414  OS << ")";
415  }
416 
417  if (Quals & Q_Const)
418  OS << " const";
419  if (Quals & Q_Volatile)
420  OS << " volatile";
421  if (Quals & Q_Restrict)
422  OS << " __restrict";
423  if (Quals & Q_Unaligned)
424  OS << " __unaligned";
425 
426  if (IsNoexcept)
427  OS << " noexcept";
428 
429  if (RefQualifier == FunctionRefQualifier::Reference)
430  OS << " &";
431  else if (RefQualifier == FunctionRefQualifier::RValueReference)
432  OS << " &&";
433 
434  if (ReturnType)
435  ReturnType->outputPost(OS, Flags);
436 }
437 
439  OS << "[thunk]: ";
440 
442 }
443 
445  if (FunctionClass & FC_StaticThisAdjust) {
446  OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
447  } else if (FunctionClass & FC_VirtualThisAdjust) {
448  if (FunctionClass & FC_VirtualThisAdjustEx) {
449  OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
450  << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
451  << ", " << ThisAdjust.StaticOffset << "}'";
452  } else {
453  OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
454  << ThisAdjust.StaticOffset << "}'";
455  }
456  }
457 
459 }
460 
462  if (Pointee->kind() == NodeKind::FunctionSignature) {
463  // If this is a pointer to a function, don't output the calling convention.
464  // It needs to go inside the parentheses.
465  const FunctionSignatureNode *Sig =
466  static_cast<const FunctionSignatureNode *>(Pointee);
468  } else
469  Pointee->outputPre(OS, Flags);
470 
472 
473  if (Quals & Q_Unaligned)
474  OS << "__unaligned ";
475 
476  if (Pointee->kind() == NodeKind::ArrayType) {
477  OS << "(";
478  } else if (Pointee->kind() == NodeKind::FunctionSignature) {
479  OS << "(";
480  const FunctionSignatureNode *Sig =
481  static_cast<const FunctionSignatureNode *>(Pointee);
483  OS << " ";
484  }
485 
486  if (ClassParent) {
487  ClassParent->output(OS, Flags);
488  OS << "::";
489  }
490 
491  switch (Affinity) {
493  OS << "*";
494  break;
496  OS << "&";
497  break;
499  OS << "&&";
500  break;
501  default:
502  assert(false);
503  }
504  outputQualifiers(OS, Quals, false, false);
505 }
506 
508  if (Pointee->kind() == NodeKind::ArrayType ||
509  Pointee->kind() == NodeKind::FunctionSignature)
510  OS << ")";
511 
512  Pointee->outputPost(OS, Flags);
513 }
514 
516  if (!(Flags & OF_NoTagSpecifier)) {
517  switch (Tag) {
522  }
523  OS << " ";
524  }
525  QualifiedName->output(OS, Flags);
526  outputQualifiers(OS, Quals, true, false);
527 }
528 
530 
532  ElementType->outputPre(OS, Flags);
533  outputQualifiers(OS, Quals, true, false);
534 }
535 
537  Node *N) const {
539  IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
540  if (ILN->Value != 0)
541  ILN->output(OS, Flags);
542 }
543 
545  OutputFlags Flags) const {
546  if (Dimensions->Count == 0)
547  return;
548 
549  outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
550  for (size_t I = 1; I < Dimensions->Count; ++I) {
551  OS << "][";
552  outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
553  }
554 }
555 
557  OS << "[";
558  outputDimensionsImpl(OS, Flags);
559  OS << "]";
560 
561  ElementType->outputPost(OS, Flags);
562 }
563 
565  Name->output(OS, Flags);
566 }
567 
569  Signature->outputPre(OS, Flags);
571  Name->output(OS, Flags);
572  Signature->outputPost(OS, Flags);
573 }
574 
576  switch (SC) {
578  OS << "private: static ";
579  break;
581  OS << "public: static ";
582  break;
584  OS << "protected: static ";
585  break;
586  default:
587  break;
588  }
589 
590  if (Type) {
591  Type->outputPre(OS, Flags);
593  }
594  Name->output(OS, Flags);
595  if (Type)
596  Type->outputPost(OS, Flags);
597 }
598 
600  Identifier->output(OS, Flags);
601 }
603 
605  Components->output(OS, Flags, "::");
606 }
607 
609  OutputFlags Flags) const {
610  OS << "`RTTI Base Class Descriptor at (";
611  OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
612  << this->Flags;
613  OS << ")'";
614 }
615 
617  OutputFlags Flags) const {
618  Name->output(OS, Flags);
619 }
620 
622  OutputFlags Flags) const {
623  OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
624 }
625 
627  outputQualifiers(OS, Quals, false, true);
628  Name->output(OS, Flags);
629  if (TargetName) {
630  OS << "{for `";
631  TargetName->output(OS, Flags);
632  OS << "'}";
633  }
634  return;
635 }
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:24
static void outputSpaceIfNecessary(OutputStream &OS)
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
amdgpu Simplify well known AMD library false Value Value const Twine & Name
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:46
size_t getCurrentPosition() const
Definition: Utility.h:127
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
bool empty() const
Definition: Utility.h:134
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:31
char * getBuffer()
Definition: Utility.h:136
CHAIN = SC CHAIN, Imm128 - System call.
char back() const
Definition: Utility.h:130
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:73
void output(OutputStream &OS, OutputFlags Flags) const override
bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, size_t InitSize)
Definition: Utility.h:172
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:81
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