103312863SZachary Turner //===- MicrosoftDemangle.cpp ----------------------------------------------===// 203312863SZachary Turner // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 603312863SZachary Turner // 703312863SZachary Turner //===----------------------------------------------------------------------===// 803312863SZachary Turner // 903312863SZachary Turner // This file defines a demangler for MSVC-style mangled symbols. 1003312863SZachary Turner // 1103312863SZachary Turner //===----------------------------------------------------------------------===// 1203312863SZachary Turner 137ba90563SZachary Turner #include "llvm/Demangle/MicrosoftDemangleNodes.h" 1403312863SZachary Turner #include "llvm/Demangle/Utility.h" 15be4a5494SChandler Carruth #include <cctype> 161b9a938bSZachary Turner #include <string> 1703312863SZachary Turner 1803312863SZachary Turner using namespace llvm; 1903312863SZachary Turner using namespace ms_demangle; 2003312863SZachary Turner 2103312863SZachary Turner #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \ 2203312863SZachary Turner case Enum::Value: \ 232e97236aSLuís Ferreira OB << Desc; \ 2403312863SZachary Turner break; 2503312863SZachary Turner 2603312863SZachary Turner // Writes a space if the last token does not end with a punctuation. 272e97236aSLuís Ferreira static void outputSpaceIfNecessary(OutputBuffer &OB) { 282e97236aSLuís Ferreira if (OB.empty()) 2903312863SZachary Turner return; 3003312863SZachary Turner 312e97236aSLuís Ferreira char C = OB.back(); 32be4a5494SChandler Carruth if (std::isalnum(C) || C == '>') 332e97236aSLuís Ferreira OB << " "; 3403312863SZachary Turner } 3503312863SZachary Turner 362e97236aSLuís Ferreira static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) { 3703312863SZachary Turner switch (Q) { 3803312863SZachary Turner case Q_Const: 392e97236aSLuís Ferreira OB << "const"; 40880d21d3SNico Weber break; 4103312863SZachary Turner case Q_Volatile: 422e97236aSLuís Ferreira OB << "volatile"; 43880d21d3SNico Weber break; 4403312863SZachary Turner case Q_Restrict: 452e97236aSLuís Ferreira OB << "__restrict"; 46880d21d3SNico Weber break; 4703312863SZachary Turner default: 4803312863SZachary Turner break; 4903312863SZachary Turner } 5003312863SZachary Turner } 5103312863SZachary Turner 522e97236aSLuís Ferreira static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q, 5303312863SZachary Turner Qualifiers Mask, bool NeedSpace) { 5403312863SZachary Turner if (!(Q & Mask)) 5503312863SZachary Turner return NeedSpace; 5603312863SZachary Turner 5703312863SZachary Turner if (NeedSpace) 582e97236aSLuís Ferreira OB << " "; 5903312863SZachary Turner 602e97236aSLuís Ferreira outputSingleQualifier(OB, Mask); 6103312863SZachary Turner return true; 6203312863SZachary Turner } 6303312863SZachary Turner 642e97236aSLuís Ferreira static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore, 6503312863SZachary Turner bool SpaceAfter) { 6603312863SZachary Turner if (Q == Q_None) 6703312863SZachary Turner return; 6803312863SZachary Turner 692e97236aSLuís Ferreira size_t Pos1 = OB.getCurrentPosition(); 702e97236aSLuís Ferreira SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore); 712e97236aSLuís Ferreira SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore); 722e97236aSLuís Ferreira SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore); 732e97236aSLuís Ferreira size_t Pos2 = OB.getCurrentPosition(); 7403312863SZachary Turner if (SpaceAfter && Pos2 > Pos1) 752e97236aSLuís Ferreira OB << " "; 7603312863SZachary Turner } 7703312863SZachary Turner 782e97236aSLuís Ferreira static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) { 792e97236aSLuís Ferreira outputSpaceIfNecessary(OB); 8003312863SZachary Turner 8103312863SZachary Turner switch (CC) { 8203312863SZachary Turner case CallingConv::Cdecl: 832e97236aSLuís Ferreira OB << "__cdecl"; 8403312863SZachary Turner break; 8503312863SZachary Turner case CallingConv::Fastcall: 862e97236aSLuís Ferreira OB << "__fastcall"; 8703312863SZachary Turner break; 8803312863SZachary Turner case CallingConv::Pascal: 892e97236aSLuís Ferreira OB << "__pascal"; 9003312863SZachary Turner break; 9103312863SZachary Turner case CallingConv::Regcall: 922e97236aSLuís Ferreira OB << "__regcall"; 9303312863SZachary Turner break; 9403312863SZachary Turner case CallingConv::Stdcall: 952e97236aSLuís Ferreira OB << "__stdcall"; 9603312863SZachary Turner break; 9703312863SZachary Turner case CallingConv::Thiscall: 982e97236aSLuís Ferreira OB << "__thiscall"; 9903312863SZachary Turner break; 10003312863SZachary Turner case CallingConv::Eabi: 1012e97236aSLuís Ferreira OB << "__eabi"; 10203312863SZachary Turner break; 10303312863SZachary Turner case CallingConv::Vectorcall: 1042e97236aSLuís Ferreira OB << "__vectorcall"; 10503312863SZachary Turner break; 10603312863SZachary Turner case CallingConv::Clrcall: 1072e97236aSLuís Ferreira OB << "__clrcall"; 10803312863SZachary Turner break; 10944f79296SVarun Gandhi case CallingConv::Swift: 1102e97236aSLuís Ferreira OB << "__attribute__((__swiftcall__)) "; 11144f79296SVarun Gandhi break; 11292dcb1d2SVarun Gandhi case CallingConv::SwiftAsync: 1132e97236aSLuís Ferreira OB << "__attribute__((__swiftasynccall__)) "; 11492dcb1d2SVarun Gandhi break; 11503312863SZachary Turner default: 11603312863SZachary Turner break; 11703312863SZachary Turner } 11803312863SZachary Turner } 11903312863SZachary Turner 120ba797b6dSZachary Turner std::string Node::toString(OutputFlags Flags) const { 1212e97236aSLuís Ferreira OutputBuffer OB; 1222e97236aSLuís Ferreira this->output(OB, Flags); 1237c59e800SNick Desaulniers std::string_view SV = OB; 1241066e397SNathan Sidwell std::string Owned(SV.begin(), SV.end()); 1252e97236aSLuís Ferreira std::free(OB.getBuffer()); 126ae209aa9SRaphael Isemann return Owned; 127b472512aSZachary Turner } 128b472512aSZachary Turner 1292e97236aSLuís Ferreira void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 13003312863SZachary Turner switch (PrimKind) { 13103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); 13203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); 13303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); 13403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); 13503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); 136a2ca6e78SNico Weber OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); 13703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); 13803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); 13903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); 14003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); 14103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); 14203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); 14303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); 14403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); 14503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); 14603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); 14703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); 14803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); 14903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); 15003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); 15103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); 152*8280651aSMax Winkler OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Auto, "auto"); 153*8280651aSMax Winkler OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, DecltypeAuto, "decltype(auto)"); 15403312863SZachary Turner } 1552e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false); 15603312863SZachary Turner } 15703312863SZachary Turner 1582e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const { 1592e97236aSLuís Ferreira output(OB, Flags, ", "); 16038d2edd6SZachary Turner } 16103312863SZachary Turner 1622e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags, 1637c59e800SNick Desaulniers std::string_view Separator) const { 16403312863SZachary Turner if (Count == 0) 16503312863SZachary Turner return; 16603312863SZachary Turner if (Nodes[0]) 1672e97236aSLuís Ferreira Nodes[0]->output(OB, Flags); 16803312863SZachary Turner for (size_t I = 1; I < Count; ++I) { 1692e97236aSLuís Ferreira OB << Separator; 1702e97236aSLuís Ferreira Nodes[I]->output(OB, Flags); 17103312863SZachary Turner } 17203312863SZachary Turner } 17303312863SZachary Turner 1742e97236aSLuís Ferreira void EncodedStringLiteralNode::output(OutputBuffer &OB, 17538d2edd6SZachary Turner OutputFlags Flags) const { 17603312863SZachary Turner switch (Char) { 17703312863SZachary Turner case CharKind::Wchar: 1782e97236aSLuís Ferreira OB << "L\""; 17903312863SZachary Turner break; 18003312863SZachary Turner case CharKind::Char: 1812e97236aSLuís Ferreira OB << "\""; 18203312863SZachary Turner break; 18303312863SZachary Turner case CharKind::Char16: 1842e97236aSLuís Ferreira OB << "u\""; 18503312863SZachary Turner break; 18603312863SZachary Turner case CharKind::Char32: 1872e97236aSLuís Ferreira OB << "U\""; 18803312863SZachary Turner break; 18903312863SZachary Turner } 1902e97236aSLuís Ferreira OB << DecodedString << "\""; 19103312863SZachary Turner if (IsTruncated) 1922e97236aSLuís Ferreira OB << "..."; 19303312863SZachary Turner } 19403312863SZachary Turner 1952e97236aSLuís Ferreira void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const { 19603312863SZachary Turner if (IsNegative) 1972e97236aSLuís Ferreira OB << '-'; 1982e97236aSLuís Ferreira OB << Value; 19903312863SZachary Turner } 20003312863SZachary Turner 2012e97236aSLuís Ferreira void TemplateParameterReferenceNode::output(OutputBuffer &OB, 20238d2edd6SZachary Turner OutputFlags Flags) const { 20303312863SZachary Turner if (ThunkOffsetCount > 0) 2042e97236aSLuís Ferreira OB << "{"; 20503312863SZachary Turner else if (Affinity == PointerAffinity::Pointer) 2062e97236aSLuís Ferreira OB << "&"; 20703312863SZachary Turner 20803312863SZachary Turner if (Symbol) { 2092e97236aSLuís Ferreira Symbol->output(OB, Flags); 21003312863SZachary Turner if (ThunkOffsetCount > 0) 2112e97236aSLuís Ferreira OB << ", "; 21203312863SZachary Turner } 21303312863SZachary Turner 21403312863SZachary Turner if (ThunkOffsetCount > 0) 2152e97236aSLuís Ferreira OB << ThunkOffsets[0]; 21603312863SZachary Turner for (int I = 1; I < ThunkOffsetCount; ++I) { 2172e97236aSLuís Ferreira OB << ", " << ThunkOffsets[I]; 21803312863SZachary Turner } 21903312863SZachary Turner if (ThunkOffsetCount > 0) 2202e97236aSLuís Ferreira OB << "}"; 22103312863SZachary Turner } 22203312863SZachary Turner 2232e97236aSLuís Ferreira void IdentifierNode::outputTemplateParameters(OutputBuffer &OB, 22438d2edd6SZachary Turner OutputFlags Flags) const { 22503312863SZachary Turner if (!TemplateParams) 22603312863SZachary Turner return; 2272e97236aSLuís Ferreira OB << "<"; 2282e97236aSLuís Ferreira TemplateParams->output(OB, Flags); 2292e97236aSLuís Ferreira OB << ">"; 23003312863SZachary Turner } 23103312863SZachary Turner 2322e97236aSLuís Ferreira void DynamicStructorIdentifierNode::output(OutputBuffer &OB, 23338d2edd6SZachary Turner OutputFlags Flags) const { 23403312863SZachary Turner if (IsDestructor) 2352e97236aSLuís Ferreira OB << "`dynamic atexit destructor for "; 23603312863SZachary Turner else 2372e97236aSLuís Ferreira OB << "`dynamic initializer for "; 23803312863SZachary Turner 23932a8a202SZachary Turner if (Variable) { 2402e97236aSLuís Ferreira OB << "`"; 2412e97236aSLuís Ferreira Variable->output(OB, Flags); 2422e97236aSLuís Ferreira OB << "''"; 24332a8a202SZachary Turner } else { 2442e97236aSLuís Ferreira OB << "'"; 2452e97236aSLuís Ferreira Name->output(OB, Flags); 2462e97236aSLuís Ferreira OB << "''"; 24703312863SZachary Turner } 24832a8a202SZachary Turner } 24903312863SZachary Turner 2502e97236aSLuís Ferreira void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { 2512e97236aSLuís Ferreira OB << Name; 2522e97236aSLuís Ferreira outputTemplateParameters(OB, Flags); 25303312863SZachary Turner } 25403312863SZachary Turner 2552e97236aSLuís Ferreira void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB, 25638d2edd6SZachary Turner OutputFlags Flags) const { 25703312863SZachary Turner switch (Operator) { 25803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); 25903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); 26003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); 26103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); 26203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); 26303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); 26403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); 26503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); 26603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, 26703312863SZachary Turner "operator[]"); 26803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); 26903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); 27003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); 27103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); 27203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); 27303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); 27403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); 27503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, 27603312863SZachary Turner "operator->*"); 27703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); 27803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); 27903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); 28003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); 28103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); 28203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, 28303312863SZachary Turner "operator>="); 28403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); 28503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); 28603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); 28703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); 28803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); 28903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); 29003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); 29103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); 29203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); 29303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); 29403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); 29503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); 29603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); 29703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); 29803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, 29903312863SZachary Turner "operator&="); 30003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, 30103312863SZachary Turner "operator|="); 30203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, 30303312863SZachary Turner "operator^="); 30403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); 30503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, 30603312863SZachary Turner "`vector deleting dtor'"); 30703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, 30803312863SZachary Turner "`default ctor closure'"); 30903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, 31003312863SZachary Turner "`scalar deleting dtor'"); 31103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, 31203312863SZachary Turner "`vector ctor iterator'"); 31303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, 31403312863SZachary Turner "`vector dtor iterator'"); 31503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, 31603312863SZachary Turner "`vector vbase ctor iterator'"); 31703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, 31803312863SZachary Turner "`virtual displacement map'"); 31903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, 32003312863SZachary Turner "`eh vector ctor iterator'"); 32103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, 32203312863SZachary Turner "`eh vector dtor iterator'"); 32303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, 32403312863SZachary Turner "`eh vector vbase ctor iterator'"); 32503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, 32603312863SZachary Turner "`copy ctor closure'"); 32703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, 32803312863SZachary Turner "`local vftable ctor closure'"); 32903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); 33003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, 33103312863SZachary Turner "operator delete[]"); 33203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, 33303312863SZachary Turner "`managed vector ctor iterator'"); 33403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, 33503312863SZachary Turner "`managed vector dtor iterator'"); 33603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, 33703312863SZachary Turner "`EH vector copy ctor iterator'"); 33803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, 33903312863SZachary Turner "`EH vector vbase copy ctor iterator'"); 34003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, 34103312863SZachary Turner "`vector copy ctor iterator'"); 34203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, 34303312863SZachary Turner "`vector vbase copy constructor iterator'"); 34403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, 34503312863SZachary Turner "`managed vector vbase copy constructor iterator'"); 346e8f21b1aSNico Weber OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, 347e8f21b1aSNico Weber "operator co_await"); 34803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); 34903312863SZachary Turner case IntrinsicFunctionKind::MaxIntrinsic: 35003312863SZachary Turner case IntrinsicFunctionKind::None: 35103312863SZachary Turner break; 35203312863SZachary Turner } 3532e97236aSLuís Ferreira outputTemplateParameters(OB, Flags); 35403312863SZachary Turner } 35503312863SZachary Turner 3562e97236aSLuís Ferreira void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB, 35738d2edd6SZachary Turner OutputFlags Flags) const { 35888ab281bSNico Weber if (IsThread) 3592e97236aSLuís Ferreira OB << "`local static thread guard'"; 36088ab281bSNico Weber else 3612e97236aSLuís Ferreira OB << "`local static guard'"; 36203312863SZachary Turner if (ScopeIndex > 0) 3632e97236aSLuís Ferreira OB << "{" << ScopeIndex << "}"; 36403312863SZachary Turner } 36503312863SZachary Turner 3662e97236aSLuís Ferreira void ConversionOperatorIdentifierNode::output(OutputBuffer &OB, 36738d2edd6SZachary Turner OutputFlags Flags) const { 3682e97236aSLuís Ferreira OB << "operator"; 3692e97236aSLuís Ferreira outputTemplateParameters(OB, Flags); 3702e97236aSLuís Ferreira OB << " "; 3712e97236aSLuís Ferreira TargetType->output(OB, Flags); 37203312863SZachary Turner } 37303312863SZachary Turner 3742e97236aSLuís Ferreira void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { 37503312863SZachary Turner if (IsDestructor) 3762e97236aSLuís Ferreira OB << "~"; 3772e97236aSLuís Ferreira Class->output(OB, Flags); 3782e97236aSLuís Ferreira outputTemplateParameters(OB, Flags); 37903312863SZachary Turner } 38003312863SZachary Turner 3812e97236aSLuís Ferreira void LiteralOperatorIdentifierNode::output(OutputBuffer &OB, 38238d2edd6SZachary Turner OutputFlags Flags) const { 3832e97236aSLuís Ferreira OB << "operator \"\"" << Name; 3842e97236aSLuís Ferreira outputTemplateParameters(OB, Flags); 38503312863SZachary Turner } 38603312863SZachary Turner 3872e97236aSLuís Ferreira void FunctionSignatureNode::outputPre(OutputBuffer &OB, 38838d2edd6SZachary Turner OutputFlags Flags) const { 389da92ed83SMartin Storsjo if (!(Flags & OF_NoAccessSpecifier)) { 390a92b4639SNico Weber if (FunctionClass & FC_Public) 3912e97236aSLuís Ferreira OB << "public: "; 392a92b4639SNico Weber if (FunctionClass & FC_Protected) 3932e97236aSLuís Ferreira OB << "protected: "; 394a92b4639SNico Weber if (FunctionClass & FC_Private) 3952e97236aSLuís Ferreira OB << "private: "; 396da92ed83SMartin Storsjo } 397a92b4639SNico Weber 398da92ed83SMartin Storsjo if (!(Flags & OF_NoMemberType)) { 39903312863SZachary Turner if (!(FunctionClass & FC_Global)) { 40003312863SZachary Turner if (FunctionClass & FC_Static) 4012e97236aSLuís Ferreira OB << "static "; 40203312863SZachary Turner } 40303312863SZachary Turner if (FunctionClass & FC_Virtual) 4042e97236aSLuís Ferreira OB << "virtual "; 40503312863SZachary Turner 406a92b4639SNico Weber if (FunctionClass & FC_ExternC) 4072e97236aSLuís Ferreira OB << "extern \"C\" "; 408da92ed83SMartin Storsjo } 409a92b4639SNico Weber 410da92ed83SMartin Storsjo if (!(Flags & OF_NoReturnType) && ReturnType) { 4112e97236aSLuís Ferreira ReturnType->outputPre(OB, Flags); 4122e97236aSLuís Ferreira OB << " "; 41303312863SZachary Turner } 41403312863SZachary Turner 41538d2edd6SZachary Turner if (!(Flags & OF_NoCallingConvention)) 4162e97236aSLuís Ferreira outputCallingConvention(OB, CallConvention); 41703312863SZachary Turner } 41803312863SZachary Turner 4192e97236aSLuís Ferreira void FunctionSignatureNode::outputPost(OutputBuffer &OB, 42038d2edd6SZachary Turner OutputFlags Flags) const { 42103312863SZachary Turner if (!(FunctionClass & FC_NoParameterList)) { 4222e97236aSLuís Ferreira OB << "("; 42303312863SZachary Turner if (Params) 4242e97236aSLuís Ferreira Params->output(OB, Flags); 42503312863SZachary Turner else 4262e97236aSLuís Ferreira OB << "void"; 4271dce8263SNico Weber 4281dce8263SNico Weber if (IsVariadic) { 4292e97236aSLuís Ferreira if (OB.back() != '(') 4302e97236aSLuís Ferreira OB << ", "; 4312e97236aSLuís Ferreira OB << "..."; 4321dce8263SNico Weber } 4332e97236aSLuís Ferreira OB << ")"; 43403312863SZachary Turner } 43503312863SZachary Turner 43603312863SZachary Turner if (Quals & Q_Const) 4372e97236aSLuís Ferreira OB << " const"; 43803312863SZachary Turner if (Quals & Q_Volatile) 4392e97236aSLuís Ferreira OB << " volatile"; 44003312863SZachary Turner if (Quals & Q_Restrict) 4412e97236aSLuís Ferreira OB << " __restrict"; 44203312863SZachary Turner if (Quals & Q_Unaligned) 4432e97236aSLuís Ferreira OB << " __unaligned"; 44403312863SZachary Turner 4452fe49005SZachary Turner if (IsNoexcept) 4462e97236aSLuís Ferreira OB << " noexcept"; 4472fe49005SZachary Turner 44803312863SZachary Turner if (RefQualifier == FunctionRefQualifier::Reference) 4492e97236aSLuís Ferreira OB << " &"; 45003312863SZachary Turner else if (RefQualifier == FunctionRefQualifier::RValueReference) 4512e97236aSLuís Ferreira OB << " &&"; 45203312863SZachary Turner 453da92ed83SMartin Storsjo if (!(Flags & OF_NoReturnType) && ReturnType) 4542e97236aSLuís Ferreira ReturnType->outputPost(OB, Flags); 45503312863SZachary Turner } 45603312863SZachary Turner 4572e97236aSLuís Ferreira void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 4582e97236aSLuís Ferreira OB << "[thunk]: "; 45903312863SZachary Turner 4602e97236aSLuís Ferreira FunctionSignatureNode::outputPre(OB, Flags); 46103312863SZachary Turner } 46203312863SZachary Turner 4632e97236aSLuís Ferreira void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 46403312863SZachary Turner if (FunctionClass & FC_StaticThisAdjust) { 4652e97236aSLuís Ferreira OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; 46603312863SZachary Turner } else if (FunctionClass & FC_VirtualThisAdjust) { 46703312863SZachary Turner if (FunctionClass & FC_VirtualThisAdjustEx) { 4682e97236aSLuís Ferreira OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " 46903312863SZachary Turner << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset 47003312863SZachary Turner << ", " << ThisAdjust.StaticOffset << "}'"; 47103312863SZachary Turner } else { 4722e97236aSLuís Ferreira OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " 47303312863SZachary Turner << ThisAdjust.StaticOffset << "}'"; 47403312863SZachary Turner } 47503312863SZachary Turner } 47603312863SZachary Turner 4772e97236aSLuís Ferreira FunctionSignatureNode::outputPost(OB, Flags); 47803312863SZachary Turner } 47903312863SZachary Turner 4802e97236aSLuís Ferreira void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 48103312863SZachary Turner if (Pointee->kind() == NodeKind::FunctionSignature) { 48203312863SZachary Turner // If this is a pointer to a function, don't output the calling convention. 48303312863SZachary Turner // It needs to go inside the parentheses. 48403312863SZachary Turner const FunctionSignatureNode *Sig = 48503312863SZachary Turner static_cast<const FunctionSignatureNode *>(Pointee); 4862e97236aSLuís Ferreira Sig->outputPre(OB, OF_NoCallingConvention); 48703312863SZachary Turner } else 4882e97236aSLuís Ferreira Pointee->outputPre(OB, Flags); 48903312863SZachary Turner 4902e97236aSLuís Ferreira outputSpaceIfNecessary(OB); 49103312863SZachary Turner 49203312863SZachary Turner if (Quals & Q_Unaligned) 4932e97236aSLuís Ferreira OB << "__unaligned "; 49403312863SZachary Turner 49503312863SZachary Turner if (Pointee->kind() == NodeKind::ArrayType) { 4962e97236aSLuís Ferreira OB << "("; 49703312863SZachary Turner } else if (Pointee->kind() == NodeKind::FunctionSignature) { 4982e97236aSLuís Ferreira OB << "("; 49903312863SZachary Turner const FunctionSignatureNode *Sig = 50003312863SZachary Turner static_cast<const FunctionSignatureNode *>(Pointee); 5012e97236aSLuís Ferreira outputCallingConvention(OB, Sig->CallConvention); 5022e97236aSLuís Ferreira OB << " "; 50303312863SZachary Turner } 50403312863SZachary Turner 50503312863SZachary Turner if (ClassParent) { 5062e97236aSLuís Ferreira ClassParent->output(OB, Flags); 5072e97236aSLuís Ferreira OB << "::"; 50803312863SZachary Turner } 50903312863SZachary Turner 51003312863SZachary Turner switch (Affinity) { 51103312863SZachary Turner case PointerAffinity::Pointer: 5122e97236aSLuís Ferreira OB << "*"; 51303312863SZachary Turner break; 51403312863SZachary Turner case PointerAffinity::Reference: 5152e97236aSLuís Ferreira OB << "&"; 51603312863SZachary Turner break; 51703312863SZachary Turner case PointerAffinity::RValueReference: 5182e97236aSLuís Ferreira OB << "&&"; 51903312863SZachary Turner break; 52003312863SZachary Turner default: 52103312863SZachary Turner assert(false); 52203312863SZachary Turner } 5232e97236aSLuís Ferreira outputQualifiers(OB, Quals, false, false); 52403312863SZachary Turner } 52503312863SZachary Turner 5262e97236aSLuís Ferreira void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 52703312863SZachary Turner if (Pointee->kind() == NodeKind::ArrayType || 52803312863SZachary Turner Pointee->kind() == NodeKind::FunctionSignature) 5292e97236aSLuís Ferreira OB << ")"; 53003312863SZachary Turner 5312e97236aSLuís Ferreira Pointee->outputPost(OB, Flags); 53203312863SZachary Turner } 53303312863SZachary Turner 5342e97236aSLuís Ferreira void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 535ba797b6dSZachary Turner if (!(Flags & OF_NoTagSpecifier)) { 53603312863SZachary Turner switch (Tag) { 53703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); 53803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); 53903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); 54003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); 54103312863SZachary Turner } 5422e97236aSLuís Ferreira OB << " "; 543ba797b6dSZachary Turner } 5442e97236aSLuís Ferreira QualifiedName->output(OB, Flags); 5452e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false); 54603312863SZachary Turner } 54703312863SZachary Turner 5482e97236aSLuís Ferreira void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} 54903312863SZachary Turner 5502e97236aSLuís Ferreira void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 5512e97236aSLuís Ferreira ElementType->outputPre(OB, Flags); 5522e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false); 55303312863SZachary Turner } 55403312863SZachary Turner 5552e97236aSLuís Ferreira void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags, 55638d2edd6SZachary Turner Node *N) const { 55703312863SZachary Turner assert(N->kind() == NodeKind::IntegerLiteral); 55803312863SZachary Turner IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); 55903312863SZachary Turner if (ILN->Value != 0) 5602e97236aSLuís Ferreira ILN->output(OB, Flags); 56103312863SZachary Turner } 56203312863SZachary Turner 5632e97236aSLuís Ferreira void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB, 56438d2edd6SZachary Turner OutputFlags Flags) const { 56503312863SZachary Turner if (Dimensions->Count == 0) 56603312863SZachary Turner return; 56703312863SZachary Turner 5682e97236aSLuís Ferreira outputOneDimension(OB, Flags, Dimensions->Nodes[0]); 56903312863SZachary Turner for (size_t I = 1; I < Dimensions->Count; ++I) { 5702e97236aSLuís Ferreira OB << "]["; 5712e97236aSLuís Ferreira outputOneDimension(OB, Flags, Dimensions->Nodes[I]); 57203312863SZachary Turner } 57303312863SZachary Turner } 57403312863SZachary Turner 5752e97236aSLuís Ferreira void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 5762e97236aSLuís Ferreira OB << "["; 5772e97236aSLuís Ferreira outputDimensionsImpl(OB, Flags); 5782e97236aSLuís Ferreira OB << "]"; 57903312863SZachary Turner 5802e97236aSLuís Ferreira ElementType->outputPost(OB, Flags); 58103312863SZachary Turner } 58203312863SZachary Turner 5832e97236aSLuís Ferreira void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 5842e97236aSLuís Ferreira Name->output(OB, Flags); 58503312863SZachary Turner } 58603312863SZachary Turner 5872e97236aSLuís Ferreira void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 5882e97236aSLuís Ferreira Signature->outputPre(OB, Flags); 5892e97236aSLuís Ferreira outputSpaceIfNecessary(OB); 5902e97236aSLuís Ferreira Name->output(OB, Flags); 5912e97236aSLuís Ferreira Signature->outputPost(OB, Flags); 59203312863SZachary Turner } 59303312863SZachary Turner 5942e97236aSLuís Ferreira void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 595da92ed83SMartin Storsjo const char *AccessSpec = nullptr; 596da92ed83SMartin Storsjo bool IsStatic = true; 59703312863SZachary Turner switch (SC) { 59803312863SZachary Turner case StorageClass::PrivateStatic: 599da92ed83SMartin Storsjo AccessSpec = "private"; 600a92b4639SNico Weber break; 60103312863SZachary Turner case StorageClass::PublicStatic: 602da92ed83SMartin Storsjo AccessSpec = "public"; 603a92b4639SNico Weber break; 60403312863SZachary Turner case StorageClass::ProtectedStatic: 605da92ed83SMartin Storsjo AccessSpec = "protected"; 6064dc0b1acSReid Kleckner break; 60703312863SZachary Turner default: 608da92ed83SMartin Storsjo IsStatic = false; 60903312863SZachary Turner break; 61003312863SZachary Turner } 611da92ed83SMartin Storsjo if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) 6122e97236aSLuís Ferreira OB << AccessSpec << ": "; 613da92ed83SMartin Storsjo if (!(Flags & OF_NoMemberType) && IsStatic) 6142e97236aSLuís Ferreira OB << "static "; 61503312863SZachary Turner 616134e1817SLasse Folger if (!(Flags & OF_NoVariableType) && Type) { 6172e97236aSLuís Ferreira Type->outputPre(OB, Flags); 6182e97236aSLuís Ferreira outputSpaceIfNecessary(OB); 61903312863SZachary Turner } 6202e97236aSLuís Ferreira Name->output(OB, Flags); 621134e1817SLasse Folger if (!(Flags & OF_NoVariableType) && Type) 6222e97236aSLuís Ferreira Type->outputPost(OB, Flags); 62303312863SZachary Turner } 62403312863SZachary Turner 6252e97236aSLuís Ferreira void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 6262e97236aSLuís Ferreira Identifier->output(OB, Flags); 62703312863SZachary Turner } 6282e97236aSLuís Ferreira void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} 62903312863SZachary Turner 6302e97236aSLuís Ferreira void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const { 6312e97236aSLuís Ferreira Components->output(OB, Flags, "::"); 63238d2edd6SZachary Turner } 63338d2edd6SZachary Turner 6342e97236aSLuís Ferreira void RttiBaseClassDescriptorNode::output(OutputBuffer &OB, 63538d2edd6SZachary Turner OutputFlags Flags) const { 6362e97236aSLuís Ferreira OB << "`RTTI Base Class Descriptor at ("; 6372e97236aSLuís Ferreira OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " 63838d2edd6SZachary Turner << this->Flags; 6392e97236aSLuís Ferreira OB << ")'"; 64003312863SZachary Turner } 64103312863SZachary Turner 6422e97236aSLuís Ferreira void LocalStaticGuardVariableNode::output(OutputBuffer &OB, 64338d2edd6SZachary Turner OutputFlags Flags) const { 6442e97236aSLuís Ferreira Name->output(OB, Flags); 64503312863SZachary Turner } 64603312863SZachary Turner 6472e97236aSLuís Ferreira void VcallThunkIdentifierNode::output(OutputBuffer &OB, 64838d2edd6SZachary Turner OutputFlags Flags) const { 6492e97236aSLuís Ferreira OB << "`vcall'{" << OffsetInVTable << ", {flat}}"; 65003312863SZachary Turner } 65103312863SZachary Turner 6522e97236aSLuís Ferreira void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 6532e97236aSLuís Ferreira outputQualifiers(OB, Quals, false, true); 6542e97236aSLuís Ferreira Name->output(OB, Flags); 65503312863SZachary Turner if (TargetName) { 6562e97236aSLuís Ferreira OB << "{for `"; 6572e97236aSLuís Ferreira TargetName->output(OB, Flags); 6582e97236aSLuís Ferreira OB << "'}"; 65903312863SZachary Turner } 66003312863SZachary Turner } 661