blob: c57f0cfaaa5ada2459a05f80e20f571ae47b0ac3 [file] [log] [blame]
Zachary Turner03312862018-08-27 03:48:03 +00001//===- 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
Zachary Turner7ba90562018-11-01 15:07:32 +000014#include "llvm/Demangle/MicrosoftDemangleNodes.h"
Zachary Turner03312862018-08-27 03:48:03 +000015#include "llvm/Demangle/Compiler.h"
16#include "llvm/Demangle/Utility.h"
Chandler Carruthbe4a5492018-08-27 06:52:14 +000017#include <cctype>
Zachary Turner03312862018-08-27 03:48:03 +000018
19using namespace llvm;
20using 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.
28static void outputSpaceIfNecessary(OutputStream &OS) {
29 if (OS.empty())
30 return;
31
32 char C = OS.back();
Chandler Carruthbe4a5492018-08-27 06:52:14 +000033 if (std::isalnum(C) || C == '>')
Zachary Turner03312862018-08-27 03:48:03 +000034 OS << " ";
35}
36
37static 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
54static 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
66static 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
80static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
81 outputSpaceIfNecessary(OS);
82
83 switch (CC) {
84 case CallingConv::Cdecl:
85 OS << "__cdecl";
86 break;
87 case CallingConv::Fastcall:
88 OS << "__fastcall";
89 break;
90 case CallingConv::Pascal:
91 OS << "__pascal";
92 break;
93 case CallingConv::Regcall:
94 OS << "__regcall";
95 break;
96 case CallingConv::Stdcall:
97 OS << "__stdcall";
98 break;
99 case CallingConv::Thiscall:
100 OS << "__thiscall";
101 break;
102 case CallingConv::Eabi:
103 OS << "__eabi";
104 break;
105 case CallingConv::Vectorcall:
106 OS << "__vectorcall";
107 break;
108 case CallingConv::Clrcall:
109 OS << "__clrcall";
110 break;
111 default:
112 break;
113 }
114}
115
116void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
117
Zachary Turner38d2edd2018-08-29 03:59:17 +0000118void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000119 switch (PrimKind) {
120 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
121 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
122 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
123 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
124 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
125 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
126 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
127 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
128 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
129 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
130 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
131 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
132 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
133 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
134 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
135 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
136 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
137 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
138 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
139 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
140 }
141 outputQualifiers(OS, Quals, true, false);
142}
143
Zachary Turner38d2edd2018-08-29 03:59:17 +0000144void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
145 output(OS, Flags, ", ");
146}
Zachary Turner03312862018-08-27 03:48:03 +0000147
Zachary Turner38d2edd2018-08-29 03:59:17 +0000148void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
149 StringView Separator) const {
Zachary Turner03312862018-08-27 03:48:03 +0000150 if (Count == 0)
151 return;
152 if (Nodes[0])
Zachary Turner38d2edd2018-08-29 03:59:17 +0000153 Nodes[0]->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000154 for (size_t I = 1; I < Count; ++I) {
155 OS << Separator;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000156 Nodes[I]->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000157 }
158}
159
Zachary Turner38d2edd2018-08-29 03:59:17 +0000160void EncodedStringLiteralNode::output(OutputStream &OS,
161 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000162 switch (Char) {
163 case CharKind::Wchar:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000164 OS << "L\"";
Zachary Turner03312862018-08-27 03:48:03 +0000165 break;
166 case CharKind::Char:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000167 OS << "\"";
Zachary Turner03312862018-08-27 03:48:03 +0000168 break;
169 case CharKind::Char16:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000170 OS << "u\"";
Zachary Turner03312862018-08-27 03:48:03 +0000171 break;
172 case CharKind::Char32:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000173 OS << "U\"";
Zachary Turner03312862018-08-27 03:48:03 +0000174 break;
175 }
176 OS << DecodedString << "\"";
177 if (IsTruncated)
178 OS << "...";
Zachary Turner03312862018-08-27 03:48:03 +0000179}
180
Zachary Turner38d2edd2018-08-29 03:59:17 +0000181void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000182 if (IsNegative)
183 OS << '-';
184 OS << Value;
185}
186
Zachary Turner38d2edd2018-08-29 03:59:17 +0000187void TemplateParameterReferenceNode::output(OutputStream &OS,
188 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000189 if (ThunkOffsetCount > 0)
190 OS << "{";
191 else if (Affinity == PointerAffinity::Pointer)
192 OS << "&";
193
194 if (Symbol) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000195 Symbol->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000196 if (ThunkOffsetCount > 0)
197 OS << ", ";
198 }
199
200 if (ThunkOffsetCount > 0)
201 OS << ThunkOffsets[0];
202 for (int I = 1; I < ThunkOffsetCount; ++I) {
203 OS << ", " << ThunkOffsets[I];
204 }
205 if (ThunkOffsetCount > 0)
206 OS << "}";
207}
208
Zachary Turner38d2edd2018-08-29 03:59:17 +0000209void IdentifierNode::outputTemplateParameters(OutputStream &OS,
210 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000211 if (!TemplateParams)
212 return;
213 OS << "<";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000214 TemplateParams->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000215 OS << ">";
216}
217
Zachary Turner38d2edd2018-08-29 03:59:17 +0000218void DynamicStructorIdentifierNode::output(OutputStream &OS,
219 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000220 if (IsDestructor)
221 OS << "`dynamic atexit destructor for ";
222 else
223 OS << "`dynamic initializer for ";
224
Zachary Turner32a8a202018-08-29 23:56:09 +0000225 if (Variable) {
226 OS << "`";
227 Variable->output(OS, Flags);
228 OS << "''";
229 } else {
230 OS << "'";
231 Name->output(OS, Flags);
232 OS << "''";
233 }
Zachary Turner03312862018-08-27 03:48:03 +0000234}
235
Zachary Turner38d2edd2018-08-29 03:59:17 +0000236void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000237 OS << Name;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000238 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000239}
240
Zachary Turner38d2edd2018-08-29 03:59:17 +0000241void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
242 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000243 switch (Operator) {
244 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
245 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
246 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
247 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
248 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
249 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
250 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
251 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
252 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
253 "operator[]");
254 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
255 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
256 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
257 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
258 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
259 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
260 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
261 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
262 "operator->*");
263 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
264 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
265 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
266 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
267 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
268 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
269 "operator>=");
270 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
271 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
272 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
273 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
274 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
275 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
276 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
277 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
278 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
279 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
280 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
281 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
282 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
283 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
284 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
285 "operator&=");
286 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
287 "operator|=");
288 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
289 "operator^=");
290 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
291 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
292 "`vector deleting dtor'");
293 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
294 "`default ctor closure'");
295 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
296 "`scalar deleting dtor'");
297 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
298 "`vector ctor iterator'");
299 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
300 "`vector dtor iterator'");
301 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
302 "`vector vbase ctor iterator'");
303 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
304 "`virtual displacement map'");
305 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
306 "`eh vector ctor iterator'");
307 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
308 "`eh vector dtor iterator'");
309 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
310 "`eh vector vbase ctor iterator'");
311 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
312 "`copy ctor closure'");
313 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
314 "`local vftable ctor closure'");
315 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
316 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
317 "operator delete[]");
318 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
319 "`managed vector ctor iterator'");
320 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
321 "`managed vector dtor iterator'");
322 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
323 "`EH vector copy ctor iterator'");
324 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
325 "`EH vector vbase copy ctor iterator'");
326 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
327 "`vector copy ctor iterator'");
328 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
329 "`vector vbase copy constructor iterator'");
330 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
331 "`managed vector vbase copy constructor iterator'");
332 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, "co_await");
333 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator <=>");
334 case IntrinsicFunctionKind::MaxIntrinsic:
335 case IntrinsicFunctionKind::None:
336 break;
337 }
Zachary Turner38d2edd2018-08-29 03:59:17 +0000338 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000339}
340
Zachary Turner38d2edd2018-08-29 03:59:17 +0000341void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
342 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000343 OS << "`local static guard'";
344 if (ScopeIndex > 0)
345 OS << "{" << ScopeIndex << "}";
346}
347
Zachary Turner38d2edd2018-08-29 03:59:17 +0000348void ConversionOperatorIdentifierNode::output(OutputStream &OS,
349 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000350 OS << "operator";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000351 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000352 OS << " ";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000353 TargetType->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000354}
355
Zachary Turner38d2edd2018-08-29 03:59:17 +0000356void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000357 if (IsDestructor)
358 OS << "~";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000359 Class->output(OS, Flags);
360 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000361}
362
Zachary Turner38d2edd2018-08-29 03:59:17 +0000363void LiteralOperatorIdentifierNode::output(OutputStream &OS,
364 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000365 OS << "operator \"\"" << Name;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000366 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000367}
368
369void FunctionSignatureNode::outputPre(OutputStream &OS,
Zachary Turner38d2edd2018-08-29 03:59:17 +0000370 OutputFlags Flags) const {
Nico Webera92b4632018-11-13 20:18:26 +0000371 if (FunctionClass & FC_Public)
372 OS << "public: ";
373 if (FunctionClass & FC_Protected)
374 OS << "protected: ";
375 if (FunctionClass & FC_Private)
376 OS << "private: ";
377
Zachary Turner03312862018-08-27 03:48:03 +0000378 if (!(FunctionClass & FC_Global)) {
379 if (FunctionClass & FC_Static)
380 OS << "static ";
381 }
Zachary Turner03312862018-08-27 03:48:03 +0000382 if (FunctionClass & FC_Virtual)
383 OS << "virtual ";
384
Nico Webera92b4632018-11-13 20:18:26 +0000385 if (FunctionClass & FC_ExternC)
386 OS << "extern \"C\" ";
387
Zachary Turner03312862018-08-27 03:48:03 +0000388 if (ReturnType) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000389 ReturnType->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000390 OS << " ";
391 }
392
Zachary Turner38d2edd2018-08-29 03:59:17 +0000393 if (!(Flags & OF_NoCallingConvention))
Zachary Turner03312862018-08-27 03:48:03 +0000394 outputCallingConvention(OS, CallConvention);
395}
396
397void FunctionSignatureNode::outputPost(OutputStream &OS,
Zachary Turner38d2edd2018-08-29 03:59:17 +0000398 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000399 if (!(FunctionClass & FC_NoParameterList)) {
400 OS << "(";
401 if (Params)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000402 Params->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000403 else
404 OS << "void";
405 OS << ")";
406 }
407
408 if (Quals & Q_Const)
409 OS << " const";
410 if (Quals & Q_Volatile)
411 OS << " volatile";
412 if (Quals & Q_Restrict)
413 OS << " __restrict";
414 if (Quals & Q_Unaligned)
415 OS << " __unaligned";
416
417 if (RefQualifier == FunctionRefQualifier::Reference)
418 OS << " &";
419 else if (RefQualifier == FunctionRefQualifier::RValueReference)
420 OS << " &&";
421
422 if (ReturnType)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000423 ReturnType->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000424}
425
Zachary Turner38d2edd2018-08-29 03:59:17 +0000426void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000427 OS << "[thunk]: ";
428
429 FunctionSignatureNode::outputPre(OS, Flags);
430}
431
Zachary Turner38d2edd2018-08-29 03:59:17 +0000432void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000433 if (FunctionClass & FC_StaticThisAdjust) {
434 OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
435 } else if (FunctionClass & FC_VirtualThisAdjust) {
436 if (FunctionClass & FC_VirtualThisAdjustEx) {
437 OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
438 << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
439 << ", " << ThisAdjust.StaticOffset << "}'";
440 } else {
441 OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
442 << ThisAdjust.StaticOffset << "}'";
443 }
444 }
445
446 FunctionSignatureNode::outputPost(OS, Flags);
447}
448
Zachary Turner38d2edd2018-08-29 03:59:17 +0000449void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000450 if (Pointee->kind() == NodeKind::FunctionSignature) {
451 // If this is a pointer to a function, don't output the calling convention.
452 // It needs to go inside the parentheses.
453 const FunctionSignatureNode *Sig =
454 static_cast<const FunctionSignatureNode *>(Pointee);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000455 Sig->outputPre(OS, OF_NoCallingConvention);
Zachary Turner03312862018-08-27 03:48:03 +0000456 } else
Zachary Turner38d2edd2018-08-29 03:59:17 +0000457 Pointee->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000458
459 outputSpaceIfNecessary(OS);
460
461 if (Quals & Q_Unaligned)
462 OS << "__unaligned ";
463
464 if (Pointee->kind() == NodeKind::ArrayType) {
465 OS << "(";
466 } else if (Pointee->kind() == NodeKind::FunctionSignature) {
467 OS << "(";
468 const FunctionSignatureNode *Sig =
469 static_cast<const FunctionSignatureNode *>(Pointee);
470 outputCallingConvention(OS, Sig->CallConvention);
471 OS << " ";
472 }
473
474 if (ClassParent) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000475 ClassParent->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000476 OS << "::";
477 }
478
479 switch (Affinity) {
480 case PointerAffinity::Pointer:
481 OS << "*";
482 break;
483 case PointerAffinity::Reference:
484 OS << "&";
485 break;
486 case PointerAffinity::RValueReference:
487 OS << "&&";
488 break;
489 default:
490 assert(false);
491 }
492 outputQualifiers(OS, Quals, false, false);
493}
494
Zachary Turner38d2edd2018-08-29 03:59:17 +0000495void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000496 if (Pointee->kind() == NodeKind::ArrayType ||
497 Pointee->kind() == NodeKind::FunctionSignature)
498 OS << ")";
499
Zachary Turner38d2edd2018-08-29 03:59:17 +0000500 Pointee->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000501}
502
Zachary Turner38d2edd2018-08-29 03:59:17 +0000503void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000504 switch (Tag) {
505 OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
506 OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
507 OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
508 OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
509 }
510 OS << " ";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000511 QualifiedName->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000512 outputQualifiers(OS, Quals, true, false);
513}
514
Zachary Turner38d2edd2018-08-29 03:59:17 +0000515void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner03312862018-08-27 03:48:03 +0000516
Zachary Turner38d2edd2018-08-29 03:59:17 +0000517void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
518 ElementType->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000519 outputQualifiers(OS, Quals, true, false);
520}
521
Zachary Turner38d2edd2018-08-29 03:59:17 +0000522void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
523 Node *N) const {
Zachary Turner03312862018-08-27 03:48:03 +0000524 assert(N->kind() == NodeKind::IntegerLiteral);
525 IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
526 if (ILN->Value != 0)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000527 ILN->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000528}
529
Zachary Turner38d2edd2018-08-29 03:59:17 +0000530void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS,
531 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000532 if (Dimensions->Count == 0)
533 return;
534
Zachary Turner38d2edd2018-08-29 03:59:17 +0000535 outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
Zachary Turner03312862018-08-27 03:48:03 +0000536 for (size_t I = 1; I < Dimensions->Count; ++I) {
537 OS << "][";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000538 outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
Zachary Turner03312862018-08-27 03:48:03 +0000539 }
540}
541
Zachary Turner38d2edd2018-08-29 03:59:17 +0000542void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000543 OS << "[";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000544 outputDimensionsImpl(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000545 OS << "]";
546
Zachary Turner38d2edd2018-08-29 03:59:17 +0000547 ElementType->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000548}
549
Zachary Turner38d2edd2018-08-29 03:59:17 +0000550void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
551 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000552}
553
Zachary Turner38d2edd2018-08-29 03:59:17 +0000554void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000555 Signature->outputPre(OS, Flags);
556 outputSpaceIfNecessary(OS);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000557 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000558 Signature->outputPost(OS, Flags);
559}
560
Zachary Turner38d2edd2018-08-29 03:59:17 +0000561void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000562 switch (SC) {
563 case StorageClass::PrivateStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000564 OS << "private: static ";
565 break;
Zachary Turner03312862018-08-27 03:48:03 +0000566 case StorageClass::PublicStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000567 OS << "public: static ";
568 break;
Zachary Turner03312862018-08-27 03:48:03 +0000569 case StorageClass::ProtectedStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000570 OS << "protected: static ";
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000571 break;
Zachary Turner03312862018-08-27 03:48:03 +0000572 default:
573 break;
574 }
575
576 if (Type) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000577 Type->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000578 outputSpaceIfNecessary(OS);
579 }
Zachary Turner38d2edd2018-08-29 03:59:17 +0000580 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000581 if (Type)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000582 Type->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000583}
584
Zachary Turnerb2fef1a2018-08-29 04:12:44 +0000585void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
586 Identifier->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000587}
Zachary Turnerb2fef1a2018-08-29 04:12:44 +0000588void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner03312862018-08-27 03:48:03 +0000589
Zachary Turner38d2edd2018-08-29 03:59:17 +0000590void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
591 Components->output(OS, Flags, "::");
592}
593
594void RttiBaseClassDescriptorNode::output(OutputStream &OS,
595 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000596 OS << "`RTTI Base Class Descriptor at (";
597 OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
Zachary Turner38d2edd2018-08-29 03:59:17 +0000598 << this->Flags;
Zachary Turner03312862018-08-27 03:48:03 +0000599 OS << ")'";
600}
601
Zachary Turner38d2edd2018-08-29 03:59:17 +0000602void LocalStaticGuardVariableNode::output(OutputStream &OS,
603 OutputFlags Flags) const {
604 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000605}
606
Zachary Turner38d2edd2018-08-29 03:59:17 +0000607void VcallThunkIdentifierNode::output(OutputStream &OS,
608 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000609 OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
610}
611
Zachary Turner38d2edd2018-08-29 03:59:17 +0000612void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000613 outputQualifiers(OS, Quals, false, true);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000614 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000615 if (TargetName) {
616 OS << "{for `";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000617 TargetName->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000618 OS << "'}";
619 }
620 return;
621}