1*0b57cec5SDimitry Andric //===- MicrosoftDemangle.cpp ----------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file defines a demangler for MSVC-style mangled symbols. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangleNodes.h" 14*0b57cec5SDimitry Andric #include "llvm/Demangle/DemangleConfig.h" 15*0b57cec5SDimitry Andric #include "llvm/Demangle/Utility.h" 16*0b57cec5SDimitry Andric #include <cctype> 17*0b57cec5SDimitry Andric #include <string> 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric using namespace ms_demangle; 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \ 23*0b57cec5SDimitry Andric case Enum::Value: \ 24*0b57cec5SDimitry Andric OS << Desc; \ 25*0b57cec5SDimitry Andric break; 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric // Writes a space if the last token does not end with a punctuation. 28*0b57cec5SDimitry Andric static void outputSpaceIfNecessary(OutputStream &OS) { 29*0b57cec5SDimitry Andric if (OS.empty()) 30*0b57cec5SDimitry Andric return; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric char C = OS.back(); 33*0b57cec5SDimitry Andric if (std::isalnum(C) || C == '>') 34*0b57cec5SDimitry Andric OS << " "; 35*0b57cec5SDimitry Andric } 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric static void outputSingleQualifier(OutputStream &OS, Qualifiers Q) { 38*0b57cec5SDimitry Andric switch (Q) { 39*0b57cec5SDimitry Andric case Q_Const: 40*0b57cec5SDimitry Andric OS << "const"; 41*0b57cec5SDimitry Andric break; 42*0b57cec5SDimitry Andric case Q_Volatile: 43*0b57cec5SDimitry Andric OS << "volatile"; 44*0b57cec5SDimitry Andric break; 45*0b57cec5SDimitry Andric case Q_Restrict: 46*0b57cec5SDimitry Andric OS << "__restrict"; 47*0b57cec5SDimitry Andric break; 48*0b57cec5SDimitry Andric default: 49*0b57cec5SDimitry Andric break; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q, 54*0b57cec5SDimitry Andric Qualifiers Mask, bool NeedSpace) { 55*0b57cec5SDimitry Andric if (!(Q & Mask)) 56*0b57cec5SDimitry Andric return NeedSpace; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric if (NeedSpace) 59*0b57cec5SDimitry Andric OS << " "; 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric outputSingleQualifier(OS, Mask); 62*0b57cec5SDimitry Andric return true; 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore, 66*0b57cec5SDimitry Andric bool SpaceAfter) { 67*0b57cec5SDimitry Andric if (Q == Q_None) 68*0b57cec5SDimitry Andric return; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric size_t Pos1 = OS.getCurrentPosition(); 71*0b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore); 72*0b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore); 73*0b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore); 74*0b57cec5SDimitry Andric size_t Pos2 = OS.getCurrentPosition(); 75*0b57cec5SDimitry Andric if (SpaceAfter && Pos2 > Pos1) 76*0b57cec5SDimitry Andric OS << " "; 77*0b57cec5SDimitry Andric } 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric static void outputCallingConvention(OutputStream &OS, CallingConv CC) { 80*0b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric switch (CC) { 83*0b57cec5SDimitry Andric case CallingConv::Cdecl: 84*0b57cec5SDimitry Andric OS << "__cdecl"; 85*0b57cec5SDimitry Andric break; 86*0b57cec5SDimitry Andric case CallingConv::Fastcall: 87*0b57cec5SDimitry Andric OS << "__fastcall"; 88*0b57cec5SDimitry Andric break; 89*0b57cec5SDimitry Andric case CallingConv::Pascal: 90*0b57cec5SDimitry Andric OS << "__pascal"; 91*0b57cec5SDimitry Andric break; 92*0b57cec5SDimitry Andric case CallingConv::Regcall: 93*0b57cec5SDimitry Andric OS << "__regcall"; 94*0b57cec5SDimitry Andric break; 95*0b57cec5SDimitry Andric case CallingConv::Stdcall: 96*0b57cec5SDimitry Andric OS << "__stdcall"; 97*0b57cec5SDimitry Andric break; 98*0b57cec5SDimitry Andric case CallingConv::Thiscall: 99*0b57cec5SDimitry Andric OS << "__thiscall"; 100*0b57cec5SDimitry Andric break; 101*0b57cec5SDimitry Andric case CallingConv::Eabi: 102*0b57cec5SDimitry Andric OS << "__eabi"; 103*0b57cec5SDimitry Andric break; 104*0b57cec5SDimitry Andric case CallingConv::Vectorcall: 105*0b57cec5SDimitry Andric OS << "__vectorcall"; 106*0b57cec5SDimitry Andric break; 107*0b57cec5SDimitry Andric case CallingConv::Clrcall: 108*0b57cec5SDimitry Andric OS << "__clrcall"; 109*0b57cec5SDimitry Andric break; 110*0b57cec5SDimitry Andric default: 111*0b57cec5SDimitry Andric break; 112*0b57cec5SDimitry Andric } 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric std::string Node::toString(OutputFlags Flags) const { 116*0b57cec5SDimitry Andric OutputStream OS; 117*0b57cec5SDimitry Andric initializeOutputStream(nullptr, nullptr, OS, 1024); 118*0b57cec5SDimitry Andric this->output(OS, Flags); 119*0b57cec5SDimitry Andric OS << '\0'; 120*0b57cec5SDimitry Andric return {OS.getBuffer()}; 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {} 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 126*0b57cec5SDimitry Andric switch (PrimKind) { 127*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); 128*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); 129*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); 130*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); 131*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); 132*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); 133*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); 134*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); 135*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); 136*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); 137*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); 138*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); 139*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); 140*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); 141*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); 142*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); 143*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); 144*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); 145*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); 146*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); 147*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const { 153*0b57cec5SDimitry Andric output(OS, Flags, ", "); 154*0b57cec5SDimitry Andric } 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags, 157*0b57cec5SDimitry Andric StringView Separator) const { 158*0b57cec5SDimitry Andric if (Count == 0) 159*0b57cec5SDimitry Andric return; 160*0b57cec5SDimitry Andric if (Nodes[0]) 161*0b57cec5SDimitry Andric Nodes[0]->output(OS, Flags); 162*0b57cec5SDimitry Andric for (size_t I = 1; I < Count; ++I) { 163*0b57cec5SDimitry Andric OS << Separator; 164*0b57cec5SDimitry Andric Nodes[I]->output(OS, Flags); 165*0b57cec5SDimitry Andric } 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric void EncodedStringLiteralNode::output(OutputStream &OS, 169*0b57cec5SDimitry Andric OutputFlags Flags) const { 170*0b57cec5SDimitry Andric switch (Char) { 171*0b57cec5SDimitry Andric case CharKind::Wchar: 172*0b57cec5SDimitry Andric OS << "L\""; 173*0b57cec5SDimitry Andric break; 174*0b57cec5SDimitry Andric case CharKind::Char: 175*0b57cec5SDimitry Andric OS << "\""; 176*0b57cec5SDimitry Andric break; 177*0b57cec5SDimitry Andric case CharKind::Char16: 178*0b57cec5SDimitry Andric OS << "u\""; 179*0b57cec5SDimitry Andric break; 180*0b57cec5SDimitry Andric case CharKind::Char32: 181*0b57cec5SDimitry Andric OS << "U\""; 182*0b57cec5SDimitry Andric break; 183*0b57cec5SDimitry Andric } 184*0b57cec5SDimitry Andric OS << DecodedString << "\""; 185*0b57cec5SDimitry Andric if (IsTruncated) 186*0b57cec5SDimitry Andric OS << "..."; 187*0b57cec5SDimitry Andric } 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const { 190*0b57cec5SDimitry Andric if (IsNegative) 191*0b57cec5SDimitry Andric OS << '-'; 192*0b57cec5SDimitry Andric OS << Value; 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric void TemplateParameterReferenceNode::output(OutputStream &OS, 196*0b57cec5SDimitry Andric OutputFlags Flags) const { 197*0b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 198*0b57cec5SDimitry Andric OS << "{"; 199*0b57cec5SDimitry Andric else if (Affinity == PointerAffinity::Pointer) 200*0b57cec5SDimitry Andric OS << "&"; 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric if (Symbol) { 203*0b57cec5SDimitry Andric Symbol->output(OS, Flags); 204*0b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 205*0b57cec5SDimitry Andric OS << ", "; 206*0b57cec5SDimitry Andric } 207*0b57cec5SDimitry Andric 208*0b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 209*0b57cec5SDimitry Andric OS << ThunkOffsets[0]; 210*0b57cec5SDimitry Andric for (int I = 1; I < ThunkOffsetCount; ++I) { 211*0b57cec5SDimitry Andric OS << ", " << ThunkOffsets[I]; 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 214*0b57cec5SDimitry Andric OS << "}"; 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric void IdentifierNode::outputTemplateParameters(OutputStream &OS, 218*0b57cec5SDimitry Andric OutputFlags Flags) const { 219*0b57cec5SDimitry Andric if (!TemplateParams) 220*0b57cec5SDimitry Andric return; 221*0b57cec5SDimitry Andric OS << "<"; 222*0b57cec5SDimitry Andric TemplateParams->output(OS, Flags); 223*0b57cec5SDimitry Andric OS << ">"; 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric void DynamicStructorIdentifierNode::output(OutputStream &OS, 227*0b57cec5SDimitry Andric OutputFlags Flags) const { 228*0b57cec5SDimitry Andric if (IsDestructor) 229*0b57cec5SDimitry Andric OS << "`dynamic atexit destructor for "; 230*0b57cec5SDimitry Andric else 231*0b57cec5SDimitry Andric OS << "`dynamic initializer for "; 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric if (Variable) { 234*0b57cec5SDimitry Andric OS << "`"; 235*0b57cec5SDimitry Andric Variable->output(OS, Flags); 236*0b57cec5SDimitry Andric OS << "''"; 237*0b57cec5SDimitry Andric } else { 238*0b57cec5SDimitry Andric OS << "'"; 239*0b57cec5SDimitry Andric Name->output(OS, Flags); 240*0b57cec5SDimitry Andric OS << "''"; 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric } 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 245*0b57cec5SDimitry Andric OS << Name; 246*0b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 247*0b57cec5SDimitry Andric } 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric void IntrinsicFunctionIdentifierNode::output(OutputStream &OS, 250*0b57cec5SDimitry Andric OutputFlags Flags) const { 251*0b57cec5SDimitry Andric switch (Operator) { 252*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); 253*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); 254*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); 255*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); 256*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); 257*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); 258*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); 259*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); 260*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, 261*0b57cec5SDimitry Andric "operator[]"); 262*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); 263*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); 264*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); 265*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); 266*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); 267*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); 268*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); 269*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, 270*0b57cec5SDimitry Andric "operator->*"); 271*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); 272*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); 273*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); 274*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); 275*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); 276*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, 277*0b57cec5SDimitry Andric "operator>="); 278*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); 279*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); 280*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); 281*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); 282*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); 283*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); 284*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); 285*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); 286*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); 287*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); 288*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); 289*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); 290*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); 291*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); 292*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, 293*0b57cec5SDimitry Andric "operator&="); 294*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, 295*0b57cec5SDimitry Andric "operator|="); 296*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, 297*0b57cec5SDimitry Andric "operator^="); 298*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); 299*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, 300*0b57cec5SDimitry Andric "`vector deleting dtor'"); 301*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, 302*0b57cec5SDimitry Andric "`default ctor closure'"); 303*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, 304*0b57cec5SDimitry Andric "`scalar deleting dtor'"); 305*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, 306*0b57cec5SDimitry Andric "`vector ctor iterator'"); 307*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, 308*0b57cec5SDimitry Andric "`vector dtor iterator'"); 309*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, 310*0b57cec5SDimitry Andric "`vector vbase ctor iterator'"); 311*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, 312*0b57cec5SDimitry Andric "`virtual displacement map'"); 313*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, 314*0b57cec5SDimitry Andric "`eh vector ctor iterator'"); 315*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, 316*0b57cec5SDimitry Andric "`eh vector dtor iterator'"); 317*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, 318*0b57cec5SDimitry Andric "`eh vector vbase ctor iterator'"); 319*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, 320*0b57cec5SDimitry Andric "`copy ctor closure'"); 321*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, 322*0b57cec5SDimitry Andric "`local vftable ctor closure'"); 323*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); 324*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, 325*0b57cec5SDimitry Andric "operator delete[]"); 326*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, 327*0b57cec5SDimitry Andric "`managed vector ctor iterator'"); 328*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, 329*0b57cec5SDimitry Andric "`managed vector dtor iterator'"); 330*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, 331*0b57cec5SDimitry Andric "`EH vector copy ctor iterator'"); 332*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, 333*0b57cec5SDimitry Andric "`EH vector vbase copy ctor iterator'"); 334*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, 335*0b57cec5SDimitry Andric "`vector copy ctor iterator'"); 336*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, 337*0b57cec5SDimitry Andric "`vector vbase copy constructor iterator'"); 338*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, 339*0b57cec5SDimitry Andric "`managed vector vbase copy constructor iterator'"); 340*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, 341*0b57cec5SDimitry Andric "operator co_await"); 342*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); 343*0b57cec5SDimitry Andric case IntrinsicFunctionKind::MaxIntrinsic: 344*0b57cec5SDimitry Andric case IntrinsicFunctionKind::None: 345*0b57cec5SDimitry Andric break; 346*0b57cec5SDimitry Andric } 347*0b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric 350*0b57cec5SDimitry Andric void LocalStaticGuardIdentifierNode::output(OutputStream &OS, 351*0b57cec5SDimitry Andric OutputFlags Flags) const { 352*0b57cec5SDimitry Andric if (IsThread) 353*0b57cec5SDimitry Andric OS << "`local static thread guard'"; 354*0b57cec5SDimitry Andric else 355*0b57cec5SDimitry Andric OS << "`local static guard'"; 356*0b57cec5SDimitry Andric if (ScopeIndex > 0) 357*0b57cec5SDimitry Andric OS << "{" << ScopeIndex << "}"; 358*0b57cec5SDimitry Andric } 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric void ConversionOperatorIdentifierNode::output(OutputStream &OS, 361*0b57cec5SDimitry Andric OutputFlags Flags) const { 362*0b57cec5SDimitry Andric OS << "operator"; 363*0b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 364*0b57cec5SDimitry Andric OS << " "; 365*0b57cec5SDimitry Andric TargetType->output(OS, Flags); 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 369*0b57cec5SDimitry Andric if (IsDestructor) 370*0b57cec5SDimitry Andric OS << "~"; 371*0b57cec5SDimitry Andric Class->output(OS, Flags); 372*0b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 373*0b57cec5SDimitry Andric } 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric void LiteralOperatorIdentifierNode::output(OutputStream &OS, 376*0b57cec5SDimitry Andric OutputFlags Flags) const { 377*0b57cec5SDimitry Andric OS << "operator \"\"" << Name; 378*0b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 379*0b57cec5SDimitry Andric } 380*0b57cec5SDimitry Andric 381*0b57cec5SDimitry Andric void FunctionSignatureNode::outputPre(OutputStream &OS, 382*0b57cec5SDimitry Andric OutputFlags Flags) const { 383*0b57cec5SDimitry Andric if (FunctionClass & FC_Public) 384*0b57cec5SDimitry Andric OS << "public: "; 385*0b57cec5SDimitry Andric if (FunctionClass & FC_Protected) 386*0b57cec5SDimitry Andric OS << "protected: "; 387*0b57cec5SDimitry Andric if (FunctionClass & FC_Private) 388*0b57cec5SDimitry Andric OS << "private: "; 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric if (!(FunctionClass & FC_Global)) { 391*0b57cec5SDimitry Andric if (FunctionClass & FC_Static) 392*0b57cec5SDimitry Andric OS << "static "; 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric if (FunctionClass & FC_Virtual) 395*0b57cec5SDimitry Andric OS << "virtual "; 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric if (FunctionClass & FC_ExternC) 398*0b57cec5SDimitry Andric OS << "extern \"C\" "; 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric if (ReturnType) { 401*0b57cec5SDimitry Andric ReturnType->outputPre(OS, Flags); 402*0b57cec5SDimitry Andric OS << " "; 403*0b57cec5SDimitry Andric } 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric if (!(Flags & OF_NoCallingConvention)) 406*0b57cec5SDimitry Andric outputCallingConvention(OS, CallConvention); 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric void FunctionSignatureNode::outputPost(OutputStream &OS, 410*0b57cec5SDimitry Andric OutputFlags Flags) const { 411*0b57cec5SDimitry Andric if (!(FunctionClass & FC_NoParameterList)) { 412*0b57cec5SDimitry Andric OS << "("; 413*0b57cec5SDimitry Andric if (Params) 414*0b57cec5SDimitry Andric Params->output(OS, Flags); 415*0b57cec5SDimitry Andric else 416*0b57cec5SDimitry Andric OS << "void"; 417*0b57cec5SDimitry Andric 418*0b57cec5SDimitry Andric if (IsVariadic) { 419*0b57cec5SDimitry Andric if (OS.back() != '(') 420*0b57cec5SDimitry Andric OS << ", "; 421*0b57cec5SDimitry Andric OS << "..."; 422*0b57cec5SDimitry Andric } 423*0b57cec5SDimitry Andric OS << ")"; 424*0b57cec5SDimitry Andric } 425*0b57cec5SDimitry Andric 426*0b57cec5SDimitry Andric if (Quals & Q_Const) 427*0b57cec5SDimitry Andric OS << " const"; 428*0b57cec5SDimitry Andric if (Quals & Q_Volatile) 429*0b57cec5SDimitry Andric OS << " volatile"; 430*0b57cec5SDimitry Andric if (Quals & Q_Restrict) 431*0b57cec5SDimitry Andric OS << " __restrict"; 432*0b57cec5SDimitry Andric if (Quals & Q_Unaligned) 433*0b57cec5SDimitry Andric OS << " __unaligned"; 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric if (IsNoexcept) 436*0b57cec5SDimitry Andric OS << " noexcept"; 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric if (RefQualifier == FunctionRefQualifier::Reference) 439*0b57cec5SDimitry Andric OS << " &"; 440*0b57cec5SDimitry Andric else if (RefQualifier == FunctionRefQualifier::RValueReference) 441*0b57cec5SDimitry Andric OS << " &&"; 442*0b57cec5SDimitry Andric 443*0b57cec5SDimitry Andric if (ReturnType) 444*0b57cec5SDimitry Andric ReturnType->outputPost(OS, Flags); 445*0b57cec5SDimitry Andric } 446*0b57cec5SDimitry Andric 447*0b57cec5SDimitry Andric void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 448*0b57cec5SDimitry Andric OS << "[thunk]: "; 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric FunctionSignatureNode::outputPre(OS, Flags); 451*0b57cec5SDimitry Andric } 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 454*0b57cec5SDimitry Andric if (FunctionClass & FC_StaticThisAdjust) { 455*0b57cec5SDimitry Andric OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; 456*0b57cec5SDimitry Andric } else if (FunctionClass & FC_VirtualThisAdjust) { 457*0b57cec5SDimitry Andric if (FunctionClass & FC_VirtualThisAdjustEx) { 458*0b57cec5SDimitry Andric OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " 459*0b57cec5SDimitry Andric << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset 460*0b57cec5SDimitry Andric << ", " << ThisAdjust.StaticOffset << "}'"; 461*0b57cec5SDimitry Andric } else { 462*0b57cec5SDimitry Andric OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " 463*0b57cec5SDimitry Andric << ThisAdjust.StaticOffset << "}'"; 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric } 466*0b57cec5SDimitry Andric 467*0b57cec5SDimitry Andric FunctionSignatureNode::outputPost(OS, Flags); 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 471*0b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::FunctionSignature) { 472*0b57cec5SDimitry Andric // If this is a pointer to a function, don't output the calling convention. 473*0b57cec5SDimitry Andric // It needs to go inside the parentheses. 474*0b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 475*0b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 476*0b57cec5SDimitry Andric Sig->outputPre(OS, OF_NoCallingConvention); 477*0b57cec5SDimitry Andric } else 478*0b57cec5SDimitry Andric Pointee->outputPre(OS, Flags); 479*0b57cec5SDimitry Andric 480*0b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 481*0b57cec5SDimitry Andric 482*0b57cec5SDimitry Andric if (Quals & Q_Unaligned) 483*0b57cec5SDimitry Andric OS << "__unaligned "; 484*0b57cec5SDimitry Andric 485*0b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType) { 486*0b57cec5SDimitry Andric OS << "("; 487*0b57cec5SDimitry Andric } else if (Pointee->kind() == NodeKind::FunctionSignature) { 488*0b57cec5SDimitry Andric OS << "("; 489*0b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 490*0b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 491*0b57cec5SDimitry Andric outputCallingConvention(OS, Sig->CallConvention); 492*0b57cec5SDimitry Andric OS << " "; 493*0b57cec5SDimitry Andric } 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric if (ClassParent) { 496*0b57cec5SDimitry Andric ClassParent->output(OS, Flags); 497*0b57cec5SDimitry Andric OS << "::"; 498*0b57cec5SDimitry Andric } 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric switch (Affinity) { 501*0b57cec5SDimitry Andric case PointerAffinity::Pointer: 502*0b57cec5SDimitry Andric OS << "*"; 503*0b57cec5SDimitry Andric break; 504*0b57cec5SDimitry Andric case PointerAffinity::Reference: 505*0b57cec5SDimitry Andric OS << "&"; 506*0b57cec5SDimitry Andric break; 507*0b57cec5SDimitry Andric case PointerAffinity::RValueReference: 508*0b57cec5SDimitry Andric OS << "&&"; 509*0b57cec5SDimitry Andric break; 510*0b57cec5SDimitry Andric default: 511*0b57cec5SDimitry Andric assert(false); 512*0b57cec5SDimitry Andric } 513*0b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, false); 514*0b57cec5SDimitry Andric } 515*0b57cec5SDimitry Andric 516*0b57cec5SDimitry Andric void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 517*0b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType || 518*0b57cec5SDimitry Andric Pointee->kind() == NodeKind::FunctionSignature) 519*0b57cec5SDimitry Andric OS << ")"; 520*0b57cec5SDimitry Andric 521*0b57cec5SDimitry Andric Pointee->outputPost(OS, Flags); 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 525*0b57cec5SDimitry Andric if (!(Flags & OF_NoTagSpecifier)) { 526*0b57cec5SDimitry Andric switch (Tag) { 527*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); 528*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); 529*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); 530*0b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); 531*0b57cec5SDimitry Andric } 532*0b57cec5SDimitry Andric OS << " "; 533*0b57cec5SDimitry Andric } 534*0b57cec5SDimitry Andric QualifiedName->output(OS, Flags); 535*0b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric 538*0b57cec5SDimitry Andric void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 541*0b57cec5SDimitry Andric ElementType->outputPre(OS, Flags); 542*0b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 543*0b57cec5SDimitry Andric } 544*0b57cec5SDimitry Andric 545*0b57cec5SDimitry Andric void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags, 546*0b57cec5SDimitry Andric Node *N) const { 547*0b57cec5SDimitry Andric assert(N->kind() == NodeKind::IntegerLiteral); 548*0b57cec5SDimitry Andric IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); 549*0b57cec5SDimitry Andric if (ILN->Value != 0) 550*0b57cec5SDimitry Andric ILN->output(OS, Flags); 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS, 554*0b57cec5SDimitry Andric OutputFlags Flags) const { 555*0b57cec5SDimitry Andric if (Dimensions->Count == 0) 556*0b57cec5SDimitry Andric return; 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[0]); 559*0b57cec5SDimitry Andric for (size_t I = 1; I < Dimensions->Count; ++I) { 560*0b57cec5SDimitry Andric OS << "]["; 561*0b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[I]); 562*0b57cec5SDimitry Andric } 563*0b57cec5SDimitry Andric } 564*0b57cec5SDimitry Andric 565*0b57cec5SDimitry Andric void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 566*0b57cec5SDimitry Andric OS << "["; 567*0b57cec5SDimitry Andric outputDimensionsImpl(OS, Flags); 568*0b57cec5SDimitry Andric OS << "]"; 569*0b57cec5SDimitry Andric 570*0b57cec5SDimitry Andric ElementType->outputPost(OS, Flags); 571*0b57cec5SDimitry Andric } 572*0b57cec5SDimitry Andric 573*0b57cec5SDimitry Andric void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 574*0b57cec5SDimitry Andric Name->output(OS, Flags); 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 578*0b57cec5SDimitry Andric Signature->outputPre(OS, Flags); 579*0b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 580*0b57cec5SDimitry Andric Name->output(OS, Flags); 581*0b57cec5SDimitry Andric Signature->outputPost(OS, Flags); 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric 584*0b57cec5SDimitry Andric void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 585*0b57cec5SDimitry Andric switch (SC) { 586*0b57cec5SDimitry Andric case StorageClass::PrivateStatic: 587*0b57cec5SDimitry Andric OS << "private: static "; 588*0b57cec5SDimitry Andric break; 589*0b57cec5SDimitry Andric case StorageClass::PublicStatic: 590*0b57cec5SDimitry Andric OS << "public: static "; 591*0b57cec5SDimitry Andric break; 592*0b57cec5SDimitry Andric case StorageClass::ProtectedStatic: 593*0b57cec5SDimitry Andric OS << "protected: static "; 594*0b57cec5SDimitry Andric break; 595*0b57cec5SDimitry Andric default: 596*0b57cec5SDimitry Andric break; 597*0b57cec5SDimitry Andric } 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric if (Type) { 600*0b57cec5SDimitry Andric Type->outputPre(OS, Flags); 601*0b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 602*0b57cec5SDimitry Andric } 603*0b57cec5SDimitry Andric Name->output(OS, Flags); 604*0b57cec5SDimitry Andric if (Type) 605*0b57cec5SDimitry Andric Type->outputPost(OS, Flags); 606*0b57cec5SDimitry Andric } 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 609*0b57cec5SDimitry Andric Identifier->output(OS, Flags); 610*0b57cec5SDimitry Andric } 611*0b57cec5SDimitry Andric void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 612*0b57cec5SDimitry Andric 613*0b57cec5SDimitry Andric void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const { 614*0b57cec5SDimitry Andric Components->output(OS, Flags, "::"); 615*0b57cec5SDimitry Andric } 616*0b57cec5SDimitry Andric 617*0b57cec5SDimitry Andric void RttiBaseClassDescriptorNode::output(OutputStream &OS, 618*0b57cec5SDimitry Andric OutputFlags Flags) const { 619*0b57cec5SDimitry Andric OS << "`RTTI Base Class Descriptor at ("; 620*0b57cec5SDimitry Andric OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " 621*0b57cec5SDimitry Andric << this->Flags; 622*0b57cec5SDimitry Andric OS << ")'"; 623*0b57cec5SDimitry Andric } 624*0b57cec5SDimitry Andric 625*0b57cec5SDimitry Andric void LocalStaticGuardVariableNode::output(OutputStream &OS, 626*0b57cec5SDimitry Andric OutputFlags Flags) const { 627*0b57cec5SDimitry Andric Name->output(OS, Flags); 628*0b57cec5SDimitry Andric } 629*0b57cec5SDimitry Andric 630*0b57cec5SDimitry Andric void VcallThunkIdentifierNode::output(OutputStream &OS, 631*0b57cec5SDimitry Andric OutputFlags Flags) const { 632*0b57cec5SDimitry Andric OS << "`vcall'{" << OffsetInVTable << ", {flat}}"; 633*0b57cec5SDimitry Andric } 634*0b57cec5SDimitry Andric 635*0b57cec5SDimitry Andric void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 636*0b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, true); 637*0b57cec5SDimitry Andric Name->output(OS, Flags); 638*0b57cec5SDimitry Andric if (TargetName) { 639*0b57cec5SDimitry Andric OS << "{for `"; 640*0b57cec5SDimitry Andric TargetName->output(OS, Flags); 641*0b57cec5SDimitry Andric OS << "'}"; 642*0b57cec5SDimitry Andric } 643*0b57cec5SDimitry Andric return; 644*0b57cec5SDimitry Andric } 645