[llvm] r340710 - [MS Demangler] Re-write the Microsoft demangler.

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 27 02:08:44 PDT 2018


S'all good. Now just need to get the *other* (unrelated) failures fixed...

On Mon, Aug 27, 2018 at 12:24 AM Zachary Turner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Ugh, i fixed it and pushed but then turned it off and went away and it
> failed. Anyway you had the same fix, so thanks
> On Mon, Aug 27, 2018 at 12:22 AM Zachary Turner <zturner at google.com>
> wrote:
>
>> I believe i fixed them all. There was a -Wnon-virtual-dtor and a missing
>> include. Was there something else?
>> On Sun, Aug 26, 2018 at 11:54 PM Chandler Carruth <chandlerc at gmail.com>
>> wrote:
>>
>>> Builds were broken by this... I tried to fix the most obvious cause
>>> (broke my build) in r340721....
>>>
>>> On Sun, Aug 26, 2018 at 8:48 PM Zachary Turner via llvm-commits <
>>> llvm-commits at lists.llvm.org> wrote:
>>>
>>>> Author: zturner
>>>> Date: Sun Aug 26 20:48:03 2018
>>>> New Revision: 340710
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=340710&view=rev
>>>> Log:
>>>> [MS Demangler] Re-write the Microsoft demangler.
>>>>
>>>> This is a pretty large refactor / re-write of the Microsoft
>>>> demangler.  The previous one was a little hackish because it
>>>> evolved as I was learning about all the various edge cases,
>>>> exceptions, etc.  It didn't have a proper AST and so there was
>>>> lots of custom handling of things that should have been much
>>>> more clean.
>>>>
>>>> Taking what was learned from that experience, it's now
>>>> re-written with a completely redesigned and much more sensible
>>>> AST.  It's probably still not perfect, but at least it's
>>>> comprehensible now to someone else who wants to come along
>>>> and make some modifications or read the code.
>>>>
>>>> Incidentally, this fixed a couple of bugs, so I've enabled
>>>> the tests which now pass.
>>>>
>>>> Added:
>>>>     llvm/trunk/lib/Demangle/MicrosoftDemangleNodes.cpp
>>>>     llvm/trunk/lib/Demangle/MicrosoftDemangleNodes.h
>>>> Modified:
>>>>     llvm/trunk/lib/Demangle/CMakeLists.txt
>>>>     llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
>>>>     llvm/trunk/test/Demangle/ms-basic.test
>>>>     llvm/trunk/test/Demangle/ms-operators.test
>>>>     llvm/trunk/test/Demangle/ms-templates-memptrs-2.test
>>>>     llvm/trunk/test/Demangle/ms-templates-memptrs.test
>>>>
>>>> Modified: llvm/trunk/lib/Demangle/CMakeLists.txt
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/CMakeLists.txt?rev=340710&r1=340709&r2=340710&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Demangle/CMakeLists.txt (original)
>>>> +++ llvm/trunk/lib/Demangle/CMakeLists.txt Sun Aug 26 20:48:03 2018
>>>> @@ -1,6 +1,7 @@
>>>>  add_llvm_library(LLVMDemangle
>>>>    ItaniumDemangle.cpp
>>>>    MicrosoftDemangle.cpp
>>>> +  MicrosoftDemangleNodes.cpp
>>>>
>>>>    ADDITIONAL_HEADER_DIRS
>>>>    "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"
>>>>
>>>> Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=340710&r1=340709&r2=340710&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
>>>> +++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Sun Aug 26 20:48:03
>>>> 2018
>>>> @@ -14,6 +14,7 @@
>>>>  //
>>>>
>>>>  //===----------------------------------------------------------------------===//
>>>>
>>>> +#include "MicrosoftDemangleNodes.h"
>>>>  #include "llvm/Demangle/Demangle.h"
>>>>
>>>>  #include "llvm/Demangle/Compiler.h"
>>>> @@ -25,386 +26,21 @@
>>>>  #include <cstdio>
>>>>  #include <tuple>
>>>>
>>>> -// This memory allocator is extremely fast, but it doesn't call dtors
>>>> -// for allocated objects. That means you can't use STL containers
>>>> -// (such as std::vector) with this allocator. But it pays off --
>>>> -// the demangler is 3x faster with this allocator compared to one with
>>>> -// STL containers.
>>>> -namespace {
>>>> -  constexpr size_t AllocUnit = 4096;
>>>> -
>>>> -class ArenaAllocator {
>>>> -  struct AllocatorNode {
>>>> -    uint8_t *Buf = nullptr;
>>>> -    size_t Used = 0;
>>>> -    size_t Capacity = 0;
>>>> -    AllocatorNode *Next = nullptr;
>>>> -  };
>>>> -
>>>> -  void addNode(size_t Capacity) {
>>>> -    AllocatorNode *NewHead = new AllocatorNode;
>>>> -    NewHead->Buf = new uint8_t[Capacity];
>>>> -    NewHead->Next = Head;
>>>> -    NewHead->Capacity = Capacity;
>>>> -    Head = NewHead;
>>>> -    NewHead->Used = 0;
>>>> -  }
>>>> -
>>>> -public:
>>>> -  ArenaAllocator() { addNode(AllocUnit); }
>>>> -
>>>> -  ~ArenaAllocator() {
>>>> -    while (Head) {
>>>> -      assert(Head->Buf);
>>>> -      delete[] Head->Buf;
>>>> -      AllocatorNode *Next = Head->Next;
>>>> -      delete Head;
>>>> -      Head = Next;
>>>> -    }
>>>> -  }
>>>> -
>>>> -  char *allocUnalignedBuffer(size_t Length) {
>>>> -    uint8_t *Buf = Head->Buf + Head->Used;
>>>> -
>>>> -    Head->Used += Length;
>>>> -    if (Head->Used > Head->Capacity) {
>>>> -      // It's possible we need a buffer which is larger than our
>>>> default unit
>>>> -      // size, so we need to be careful to add a node with capacity
>>>> that is at
>>>> -      // least as large as what we need.
>>>> -      addNode(std::max(AllocUnit, Length));
>>>> -      Head->Used = Length;
>>>> -      Buf = Head->Buf;
>>>> -    }
>>>> -
>>>> -    return reinterpret_cast<char *>(Buf);
>>>> -  }
>>>> -
>>>> -  template <typename T, typename... Args> T *alloc(Args &&...
>>>> ConstructorArgs) {
>>>> -
>>>> -    size_t Size = sizeof(T);
>>>> -    assert(Head && Head->Buf);
>>>> -
>>>> -    size_t P = (size_t)Head->Buf + Head->Used;
>>>> -    uintptr_t AlignedP =
>>>> -        (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
>>>> -    uint8_t *PP = (uint8_t *)AlignedP;
>>>> -    size_t Adjustment = AlignedP - P;
>>>> -
>>>> -    Head->Used += Size + Adjustment;
>>>> -    if (Head->Used < Head->Capacity)
>>>> -      return new (PP) T(std::forward<Args>(ConstructorArgs)...);
>>>> -
>>>> -    addNode(AllocUnit);
>>>> -    Head->Used = Size;
>>>> -    return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
>>>> -  }
>>>> -
>>>> -private:
>>>> -  AllocatorNode *Head = nullptr;
>>>> -};
>>>> -} // namespace
>>>> +using namespace llvm;
>>>> +using namespace ms_demangle;
>>>>
>>>>  static bool startsWithDigit(StringView S) {
>>>>    return !S.empty() && std::isdigit(S.front());
>>>>  }
>>>>
>>>> -// Writes a space if the last token does not end with a punctuation.
>>>> -static void outputSpaceIfNecessary(OutputStream &OS) {
>>>> -  if (OS.empty())
>>>> -    return;
>>>> -
>>>> -  char C = OS.back();
>>>> -  if (isalnum(C) || C == '>')
>>>> -    OS << " ";
>>>> -}
>>>> -
>>>> -// Storage classes
>>>> -enum Qualifiers : uint8_t {
>>>> -  Q_None = 0,
>>>> -  Q_Const = 1 << 0,
>>>> -  Q_Volatile = 1 << 1,
>>>> -  Q_Far = 1 << 2,
>>>> -  Q_Huge = 1 << 3,
>>>> -  Q_Unaligned = 1 << 4,
>>>> -  Q_Restrict = 1 << 5,
>>>> -  Q_Pointer64 = 1 << 6
>>>> -};
>>>> -
>>>> -enum class StorageClass : uint8_t {
>>>> -  None,
>>>> -  PrivateStatic,
>>>> -  ProtectedStatic,
>>>> -  PublicStatic,
>>>> -  Global,
>>>> -  FunctionLocalStatic,
>>>> -};
>>>> -
>>>>  enum class QualifierMangleMode { Drop, Mangle, Result };
>>>>
>>>> -enum class PointerAffinity { Pointer, Reference, RValueReference };
>>>> -
>>>> -// Calling conventions
>>>> -enum class CallingConv : uint8_t {
>>>> -  None,
>>>> -  Cdecl,
>>>> -  Pascal,
>>>> -  Thiscall,
>>>> -  Stdcall,
>>>> -  Fastcall,
>>>> -  Clrcall,
>>>> -  Eabi,
>>>> -  Vectorcall,
>>>> -  Regcall,
>>>> -};
>>>> -
>>>> -enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
>>>> -
>>>> -// Types
>>>> -enum class PrimTy : uint8_t {
>>>> -  Unknown,
>>>> -  None,
>>>> -  Function,
>>>> -  Ptr,
>>>> -  MemberPtr,
>>>> -  Array,
>>>> -
>>>> -  Struct,
>>>> -  Union,
>>>> -  Class,
>>>> -  Enum,
>>>> -
>>>> -  Void,
>>>> -  Bool,
>>>> -  Char,
>>>> -  Schar,
>>>> -  Uchar,
>>>> -  Char16,
>>>> -  Char32,
>>>> -  Short,
>>>> -  Ushort,
>>>> -  Int,
>>>> -  Uint,
>>>> -  Long,
>>>> -  Ulong,
>>>> -  Int64,
>>>> -  Uint64,
>>>> -  Wchar,
>>>> -  Float,
>>>> -  Double,
>>>> -  Ldouble,
>>>> -  Nullptr,
>>>> -  Custom,
>>>> -  Vftable,
>>>> -  Vbtable,
>>>> -  LocalStaticGuard
>>>> +struct NodeList {
>>>> +  Node *N = nullptr;
>>>> +  NodeList *Next = nullptr;
>>>>  };
>>>>
>>>> -enum class OperatorTy : uint8_t {
>>>> -  Ctor,                    // ?0 # Foo::Foo()
>>>> -  Dtor,                    // ?1 # Foo::~Foo()
>>>> -  New,                     // ?2 # operator new
>>>> -  Delete,                  // ?3 # operator delete
>>>> -  Assign,                  // ?4 # operator=
>>>> -  RightShift,              // ?5 # operator>>
>>>> -  LeftShift,               // ?6 # operator<<
>>>> -  LogicalNot,              // ?7 # operator!
>>>> -  Equals,                  // ?8 # operator==
>>>> -  NotEquals,               // ?9 # operator!=
>>>> -  ArraySubscript,          // ?A # operator[]
>>>> -  Conversion,              // ?B # Foo::operator <type>()
>>>> -  Pointer,                 // ?C # operator->
>>>> -  Dereference,             // ?D # operator*
>>>> -  Increment,               // ?E # operator++
>>>> -  Decrement,               // ?F # operator--
>>>> -  Minus,                   // ?G # operator-
>>>> -  Plus,                    // ?H # operator+
>>>> -  BitwiseAnd,              // ?I # operator&
>>>> -  MemberPointer,           // ?J # operator->*
>>>> -  Divide,                  // ?K # operator/
>>>> -  Modulus,                 // ?L # operator%
>>>> -  LessThan,                // ?M operator<
>>>> -  LessThanEqual,           // ?N operator<=
>>>> -  GreaterThan,             // ?O operator>
>>>> -  GreaterThanEqual,        // ?P operator>=
>>>> -  Comma,                   // ?Q operator,
>>>> -  Parens,                  // ?R operator()
>>>> -  BitwiseNot,              // ?S operator~
>>>> -  BitwiseXor,              // ?T operator^
>>>> -  BitwiseOr,               // ?U operator|
>>>> -  LogicalAnd,              // ?V operator&&
>>>> -  LogicalOr,               // ?W operator||
>>>> -  TimesEqual,              // ?X operator*=
>>>> -  PlusEqual,               // ?Y operator+=
>>>> -  MinusEqual,              // ?Z operator-=
>>>> -  DivEqual,                // ?_0 operator/=
>>>> -  ModEqual,                // ?_1 operator%=
>>>> -  RshEqual,                // ?_2 operator>>=
>>>> -  LshEqual,                // ?_3 operator<<=
>>>> -  BitwiseAndEqual,         // ?_4 operator&=
>>>> -  BitwiseOrEqual,          // ?_5 operator|=
>>>> -  BitwiseXorEqual,         // ?_6 operator^=
>>>> -  Vftable,                 // ?_7 # vftable
>>>> -  Vbtable,                 // ?_8 # vbtable
>>>> -  Vcall,                   // ?_9 # vcall
>>>> -  Typeof,                  // ?_A # typeof
>>>> -  LocalStaticGuard,        // ?_B # local static guard
>>>> -  StringLiteral,           // ?_C # string literal
>>>> -  VbaseDtor,               // ?_D # vbase destructor
>>>> -  VecDelDtor,              // ?_E # vector deleting destructor
>>>> -  DefaultCtorClosure,      // ?_F # default constructor closure
>>>> -  ScalarDelDtor,           // ?_G # scalar deleting destructor
>>>> -  VecCtorIter,             // ?_H # vector constructor iterator
>>>> -  VecDtorIter,             // ?_I # vector destructor iterator
>>>> -  VecVbaseCtorIter,        // ?_J # vector vbase constructor iterator
>>>> -  VdispMap,                // ?_K # virtual displacement map
>>>> -  EHVecCtorIter,           // ?_L # eh vector constructor iterator
>>>> -  EHVecDtorIter,           // ?_M # eh vector destructor iterator
>>>> -  EHVecVbaseCtorIter,      // ?_N # eh vector vbase constructor
>>>> iterator
>>>> -  CopyCtorClosure,         // ?_O # copy constructor closure
>>>> -  UdtReturning,            // ?_P<name> # udt returning <name>
>>>> -  Unknown,                 // ?_Q # <unknown>
>>>> -  RttiTypeDescriptor,      // ?_R0 # RTTI Type Descriptor
>>>> -  RttiBaseClassDescriptor, // ?_R1 # RTTI Base Class Descriptor at
>>>> (a,b,c,d)
>>>> -  RttiBaseClassArray,      // ?_R2 # RTTI Base Class Array
>>>> -  RttiClassHierarchyDescriptor, // ?_R3 # RTTI Class Hierarchy
>>>> Descriptor
>>>> -  RttiCompleteObjLocator,       // ?_R4 # RTTI Complete Object Locator
>>>> -  LocalVftable,                 // ?_S # local vftable
>>>> -  LocalVftableCtorClosure,      // ?_T # local vftable constructor
>>>> closure
>>>> -  ArrayNew,                     // ?_U operator new[]
>>>> -  ArrayDelete,                  // ?_V operator delete[]
>>>> -  ManVectorCtorIter,            // ?__A managed vector ctor iterator
>>>> -  ManVectorDtorIter,            // ?__B managed vector dtor iterator
>>>> -  EHVectorCopyCtorIter,         // ?__C EH vector copy ctor iterator
>>>> -  EHVectorVbaseCopyCtorIter,    // ?__D EH vector vbase copy ctor
>>>> iterator
>>>> -  DynamicInitializer,           // ?__E dynamic initializer for `T'
>>>> -  DynamicAtexitDestructor,      // ?__F dynamic atexit destructor for
>>>> `T'
>>>> -  VectorCopyCtorIter,           // ?__G vector copy constructor
>>>> iterator
>>>> -  VectorVbaseCopyCtorIter,      // ?__H vector vbase copy constructor
>>>> iterator
>>>> -  ManVectorVbaseCopyCtorIter,   // ?__I managed vector vbase copy
>>>> constructor
>>>> -                                // iterator
>>>> -  LocalStaticThreadGuard,       // ?__J local static thread guard
>>>> -  LiteralOperator,              // ?__K operator ""_name
>>>> -  CoAwait,                      // ?__L co_await
>>>> -  Spaceship,                    // operator<=>
>>>> -};
>>>> -
>>>> -// A map to translate from operator prefix to operator type.
>>>> -struct OperatorMapEntry {
>>>> -  StringView Prefix;
>>>> -  StringView Name;
>>>> -  OperatorTy Operator;
>>>> -};
>>>> -
>>>> -// The entries here must be in the same order as the enumeration so
>>>> that it can
>>>> -// be indexed by enum value.
>>>> -OperatorMapEntry OperatorMap[] = {
>>>> -    {"0", " <ctor>", OperatorTy::Ctor},
>>>> -    {"1", " <dtor>", OperatorTy::Dtor},
>>>> -    {"2", "operator new", OperatorTy::New},
>>>> -    {"3", "operator delete", OperatorTy::Delete},
>>>> -    {"4", "operator=", OperatorTy::Assign},
>>>> -    {"5", "operator>>", OperatorTy::RightShift},
>>>> -    {"6", "operator<<", OperatorTy::LeftShift},
>>>> -    {"7", "operator!", OperatorTy::LogicalNot},
>>>> -    {"8", "operator==", OperatorTy::Equals},
>>>> -    {"9", "operator!=", OperatorTy::NotEquals},
>>>> -    {"A", "operator[]", OperatorTy::ArraySubscript},
>>>> -    {"B", "operator <conversion>", OperatorTy::Conversion},
>>>> -    {"C", "operator->", OperatorTy::Pointer},
>>>> -    {"D", "operator*", OperatorTy::Dereference},
>>>> -    {"E", "operator++", OperatorTy::Increment},
>>>> -    {"F", "operator--", OperatorTy::Decrement},
>>>> -    {"G", "operator-", OperatorTy::Minus},
>>>> -    {"H", "operator+", OperatorTy::Plus},
>>>> -    {"I", "operator&", OperatorTy::BitwiseAnd},
>>>> -    {"J", "operator->*", OperatorTy::MemberPointer},
>>>> -    {"K", "operator/", OperatorTy::Divide},
>>>> -    {"L", "operator%", OperatorTy::Modulus},
>>>> -    {"M", "operator<", OperatorTy::LessThan},
>>>> -    {"N", "operator<=", OperatorTy::LessThanEqual},
>>>> -    {"O", "operator>", OperatorTy::GreaterThan},
>>>> -    {"P", "operator>=", OperatorTy::GreaterThanEqual},
>>>> -    {"Q", "operator,", OperatorTy::Comma},
>>>> -    {"R", "operator()", OperatorTy::Parens},
>>>> -    {"S", "operator~", OperatorTy::BitwiseNot},
>>>> -    {"T", "operator^", OperatorTy::BitwiseXor},
>>>> -    {"U", "operator|", OperatorTy::BitwiseOr},
>>>> -    {"V", "operator&&", OperatorTy::LogicalAnd},
>>>> -    {"W", "operator||", OperatorTy::LogicalOr},
>>>> -    {"X", "operator*=", OperatorTy::TimesEqual},
>>>> -    {"Y", "operator+=", OperatorTy::PlusEqual},
>>>> -    {"Z", "operator-=", OperatorTy::MinusEqual},
>>>> -    {"_0", "operator/=", OperatorTy::DivEqual},
>>>> -    {"_1", "operator%=", OperatorTy::ModEqual},
>>>> -    {"_2", "operator>>=", OperatorTy::RshEqual},
>>>> -    {"_3", "operator<<=", OperatorTy::LshEqual},
>>>> -    {"_4", "operator&=", OperatorTy::BitwiseAndEqual},
>>>> -    {"_5", "operator|=", OperatorTy::BitwiseOrEqual},
>>>> -    {"_6", "operator^=", OperatorTy::BitwiseXorEqual},
>>>> -    {"_7", "`vftable'", OperatorTy::Vftable},
>>>> -    {"_8", "`vbtable'", OperatorTy::Vbtable},
>>>> -    {"_9", "`vcall'", OperatorTy::Vcall},
>>>> -    {"_A", "`typeof'", OperatorTy::Typeof},
>>>> -    {"_B", "`local static guard'", OperatorTy::LocalStaticGuard},
>>>> -    {"_C", "`string'", OperatorTy::StringLiteral},
>>>> -    {"_D", "`vbase dtor'", OperatorTy::VbaseDtor},
>>>> -    {"_E", "`vector deleting dtor'", OperatorTy::VecDelDtor},
>>>> -    {"_F", "`default ctor closure'", OperatorTy::DefaultCtorClosure},
>>>> -    {"_G", "`scalar deleting dtor'", OperatorTy::ScalarDelDtor},
>>>> -    {"_H", "`vector ctor iterator'", OperatorTy::VecCtorIter},
>>>> -    {"_I", "`vector dtor iterator'", OperatorTy::VecDtorIter},
>>>> -    {"_J", "`vector vbase ctor iterator'",
>>>> OperatorTy::VecVbaseCtorIter},
>>>> -    {"_K", "`virtual displacement map'", OperatorTy::VdispMap},
>>>> -    {"_L", "`eh vector ctor iterator'", OperatorTy::EHVecCtorIter},
>>>> -    {"_M", "`eh vector dtor iterator'", OperatorTy::EHVecDtorIter},
>>>> -    {"_N", "`eh vector vbase ctor iterator'",
>>>> OperatorTy::EHVecVbaseCtorIter},
>>>> -    {"_O", "`copy ctor closure'", OperatorTy::CopyCtorClosure},
>>>> -    {"_P", "`udt returning'", OperatorTy::UdtReturning},
>>>> -    {"_Q", "`unknown'", OperatorTy::Unknown},
>>>> -    {"_R0", "`RTTI Type Descriptor'", OperatorTy::RttiTypeDescriptor},
>>>> -    {"_R1", "RTTI Base Class Descriptor",
>>>> OperatorTy::RttiBaseClassDescriptor},
>>>> -    {"_R2", "`RTTI Base Class Array'", OperatorTy::RttiBaseClassArray},
>>>> -    {"_R3", "`RTTI Class Hierarchy Descriptor'",
>>>> -     OperatorTy::RttiClassHierarchyDescriptor},
>>>> -    {"_R4", "`RTTI Complete Object Locator'",
>>>> -     OperatorTy::RttiCompleteObjLocator},
>>>> -    {"_S", "`local vftable'", OperatorTy::LocalVftable},
>>>> -    {"_T", "`local vftable ctor closure'",
>>>> OperatorTy::LocalVftableCtorClosure},
>>>> -    {"_U", "operator new[]", OperatorTy::ArrayNew},
>>>> -    {"_V", "operator delete[]", OperatorTy::ArrayDelete},
>>>> -    {"__A", "managed vector ctor iterator",
>>>> OperatorTy::ManVectorCtorIter},
>>>> -    {"__B", "managed vector dtor iterator",
>>>> OperatorTy::ManVectorDtorIter},
>>>> -    {"__C", "EH vector copy ctor iterator",
>>>> OperatorTy::EHVectorCopyCtorIter},
>>>> -    {"__D", "EH vector vbase copy ctor iterator",
>>>> -     OperatorTy::EHVectorVbaseCopyCtorIter},
>>>> -    {"__E", "dynamic initializer", OperatorTy::DynamicInitializer},
>>>> -    {"__F", "dynamic atexit destructor",
>>>> OperatorTy::DynamicAtexitDestructor},
>>>> -    {"__G", "vector copy ctor iterator",
>>>> OperatorTy::VectorCopyCtorIter},
>>>> -    {"__H", "vector vbase copy constructor iterator",
>>>> -     OperatorTy::VectorVbaseCopyCtorIter},
>>>> -    {"__I", "managed vector vbase copy constructor iterator",
>>>> -     OperatorTy::ManVectorVbaseCopyCtorIter},
>>>> -    {"__J", "local static thread guard",
>>>> OperatorTy::LocalStaticThreadGuard},
>>>> -    {"__K", "operator \"\"", OperatorTy::LiteralOperator},
>>>> -    {"__L", "co_await", OperatorTy::CoAwait},
>>>> -};
>>>> -
>>>> -// Function classes
>>>> -enum FuncClass : uint16_t {
>>>> -  None = 0,
>>>> -  Public = 1 << 0,
>>>> -  Protected = 1 << 1,
>>>> -  Private = 1 << 2,
>>>> -  Global = 1 << 3,
>>>> -  Static = 1 << 4,
>>>> -  Virtual = 1 << 5,
>>>> -  Far = 1 << 6,
>>>> -  ExternC = 1 << 7,
>>>> -  NoPrototype = 1 << 8,
>>>> -  VirtualThisAdjust = 1 << 9,
>>>> -  VirtualThisAdjustEx = 1 << 10,
>>>> -  StaticThisAdjust = 1 << 11
>>>> -};
>>>> +enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
>>>>
>>>>  enum NameBackrefBehavior : uint8_t {
>>>>    NBB_None = 0,          // don't save any names as backrefs.
>>>> @@ -412,237 +48,6 @@ enum NameBackrefBehavior : uint8_t {
>>>>    NBB_Simple = 1 << 1,   // save simple names.
>>>>  };
>>>>
>>>> -enum class SymbolCategory {
>>>> -  Unknown,
>>>> -  NamedFunction,
>>>> -  NamedVariable,
>>>> -  UnnamedFunction,
>>>> -  UnnamedVariable,
>>>> -  SpecialOperator
>>>> -};
>>>> -
>>>> -namespace {
>>>> -
>>>> -struct Type;
>>>> -struct Name;
>>>> -
>>>> -struct FunctionParams {
>>>> -  bool IsVariadic = false;
>>>> -
>>>> -  Type *Current = nullptr;
>>>> -
>>>> -  FunctionParams *Next = nullptr;
>>>> -};
>>>> -
>>>> -struct TemplateParams {
>>>> -  bool IsTemplateTemplate = false;
>>>> -  bool IsAliasTemplate = false;
>>>> -  bool IsIntegerLiteral = false;
>>>> -  bool IntegerLiteralIsNegative = false;
>>>> -  bool IsEmptyParameterPack = false;
>>>> -  bool PointerToSymbol = false;
>>>> -  bool NullptrLiteral = false;
>>>> -  bool DataMemberPointer = false;
>>>> -  bool ReferenceToSymbol = false;
>>>> -
>>>> -  int ThunkOffsetCount = 0;
>>>> -  std::array<int64_t, 3> ThunkOffsets;
>>>> -
>>>> -  // If IsIntegerLiteral is true, this is a non-type template parameter
>>>> -  // whose value is contained in this field.
>>>> -  uint64_t IntegralValue = 0;
>>>> -
>>>> -  // Type can be null if this is a template template parameter.  In
>>>> that case
>>>> -  // only Name will be valid.
>>>> -  Type *ParamType = nullptr;
>>>> -
>>>> -  // Name can be valid if this is a template template parameter (see
>>>> above) or
>>>> -  // this is a function declaration (e.g. foo<&SomeFunc>).  In the
>>>> latter case
>>>> -  // Name contains the name of the function and Type contains the
>>>> signature.
>>>> -  Name *ParamName = nullptr;
>>>> -
>>>> -  TemplateParams *Next = nullptr;
>>>> -};
>>>> -
>>>> -// The type class. Mangled symbols are first parsed and converted to
>>>> -// this type and then converted to string.
>>>> -struct Type {
>>>> -  virtual ~Type() {}
>>>> -
>>>> -  virtual Type *clone(ArenaAllocator &Arena) const;
>>>> -
>>>> -  // Write the "first half" of a given type.  This is a static
>>>> functions to
>>>> -  // give the code a chance to do processing that is common to a
>>>> subset of
>>>> -  // subclasses
>>>> -  static void outputPre(OutputStream &OS, Type &Ty);
>>>> -
>>>> -  // Write the "second half" of a given type.  This is a static
>>>> functions to
>>>> -  // give the code a chance to do processing that is common to a
>>>> subset of
>>>> -  // subclasses
>>>> -  static void outputPost(OutputStream &OS, Type &Ty);
>>>> -
>>>> -  virtual void outputPre(OutputStream &OS);
>>>> -  virtual void outputPost(OutputStream &OS);
>>>> -
>>>> -  // Primitive type such as Int.
>>>> -  PrimTy Prim = PrimTy::Unknown;
>>>> -
>>>> -  Qualifiers Quals = Q_None;
>>>> -  StringView Custom;
>>>> -  StorageClass Storage = StorageClass::None; // storage class
>>>> -};
>>>> -
>>>> -// Represents an identifier which may be a template.
>>>> -struct Name {
>>>> -  virtual ~Name() = default;
>>>> -
>>>> -  bool IsTemplateInstantiation = false;
>>>> -  bool IsOperator = false;
>>>> -  bool IsBackReference = false;
>>>> -
>>>> -  // Name read from an MangledName string.
>>>> -  StringView Str;
>>>> -
>>>> -  // Template parameters. Only valid if IsTemplateInstantiation is
>>>> true.
>>>> -  TemplateParams *TParams = nullptr;
>>>> -
>>>> -  // Nested BackReferences (e.g. "A::B::C") are represented as a
>>>> linked list.
>>>> -  Name *Next = nullptr;
>>>> -};
>>>> -
>>>> -struct OperatorInfo : public Name {
>>>> -  explicit OperatorInfo(const OperatorMapEntry &Info) : Info(&Info) {
>>>> -    this->IsOperator = true;
>>>> -  }
>>>> -  explicit OperatorInfo(OperatorTy OpType)
>>>> -      : OperatorInfo(OperatorMap[(int)OpType]) {}
>>>> -
>>>> -  const OperatorMapEntry *Info = nullptr;
>>>> -  bool IsIndirectTable = false;
>>>> -};
>>>> -
>>>> -struct IndirectTable : public OperatorInfo {
>>>> -  explicit IndirectTable(const OperatorMapEntry &Info) :
>>>> OperatorInfo(Info) {
>>>> -    this->IsOperator = true;
>>>> -    this->IsIndirectTable = true;
>>>> -  }
>>>> -  explicit IndirectTable(OperatorTy OpType)
>>>> -      : IndirectTable(OperatorMap[(int)OpType]) {}
>>>> -
>>>> -  const Name *TableLocation = nullptr;
>>>> -  const Name *TableTarget = nullptr;
>>>> -};
>>>> -
>>>> -struct StringLiteral : public OperatorInfo {
>>>> -  StringLiteral() : OperatorInfo(OperatorTy::StringLiteral) {}
>>>> -
>>>> -  PrimTy CharType;
>>>> -  bool IsTruncated = false;
>>>> -};
>>>> -
>>>> -struct RttiBaseClassDescriptor : public OperatorInfo {
>>>> -  RttiBaseClassDescriptor()
>>>> -      : OperatorInfo(OperatorTy::RttiBaseClassDescriptor) {}
>>>> -
>>>> -  uint32_t NVOffset = 0;
>>>> -  int32_t VBPtrOffset = 0;
>>>> -  uint32_t VBTableOffset = 0;
>>>> -  uint32_t Flags = 0;
>>>> -};
>>>> -
>>>> -struct LocalStaticGuardVariable : public OperatorInfo {
>>>> -  LocalStaticGuardVariable() :
>>>> OperatorInfo(OperatorTy::LocalStaticGuard) {}
>>>> -
>>>> -  uint32_t ScopeIndex = 0;
>>>> -  bool IsVisible = false;
>>>> -};
>>>> -
>>>> -struct VirtualMemberPtrThunk : public OperatorInfo {
>>>> -  VirtualMemberPtrThunk() : OperatorInfo(OperatorTy::Vcall) {}
>>>> -
>>>> -  uint64_t OffsetInVTable = 0;
>>>> -  CallingConv CC = CallingConv::Cdecl;
>>>> -};
>>>> -
>>>> -struct PointerType : public Type {
>>>> -  Type *clone(ArenaAllocator &Arena) const override;
>>>> -  void outputPre(OutputStream &OS) override;
>>>> -  void outputPost(OutputStream &OS) override;
>>>> -
>>>> -  PointerAffinity Affinity;
>>>> -
>>>> -  // Represents a type X in "a pointer to X", "a reference to X",
>>>> -  // "an array of X", or "a function returning X".
>>>> -  Type *Pointee = nullptr;
>>>> -};
>>>> -
>>>> -struct MemberPointerType : public Type {
>>>> -  Type *clone(ArenaAllocator &Arena) const override;
>>>> -  void outputPre(OutputStream &OS) override;
>>>> -  void outputPost(OutputStream &OS) override;
>>>> -
>>>> -  Name *MemberName = nullptr;
>>>> -
>>>> -  // Represents a type X in "a pointer to X", "a reference to X",
>>>> -  // "an array of X", or "a function returning X".
>>>> -  Type *Pointee = nullptr;
>>>> -};
>>>> -
>>>> -struct FunctionType : public Type {
>>>> -  struct ThisAdjustor {
>>>> -    uint32_t StaticOffset = 0;
>>>> -    int32_t VBPtrOffset = 0;
>>>> -    int32_t VBOffsetOffset = 0;
>>>> -    int32_t VtordispOffset = 0;
>>>> -  };
>>>> -
>>>> -  Type *clone(ArenaAllocator &Arena) const override;
>>>> -  void outputPre(OutputStream &OS) override;
>>>> -  void outputPost(OutputStream &OS) override;
>>>> -
>>>> -  // True if this FunctionType instance is the Pointee of a
>>>> PointerType or
>>>> -  // MemberPointerType.
>>>> -  bool IsFunctionPointer = false;
>>>> -  bool IsThunk = false;
>>>> -
>>>> -  Type *ReturnType = nullptr;
>>>> -  // If this is a reference, the type of reference.
>>>> -  ReferenceKind RefKind;
>>>> -
>>>> -  CallingConv CallConvention;
>>>> -  FuncClass FunctionClass;
>>>> -
>>>> -  // Valid if IsThunk is true.
>>>> -  ThisAdjustor *ThisAdjust = nullptr;
>>>> -
>>>> -  FunctionParams Params;
>>>> -};
>>>> -
>>>> -struct UdtType : public Type {
>>>> -  Type *clone(ArenaAllocator &Arena) const override;
>>>> -  void outputPre(OutputStream &OS) override;
>>>> -
>>>> -  Name *UdtName = nullptr;
>>>> -};
>>>> -
>>>> -struct ArrayDimension {
>>>> -  uint64_t Dim = 0;
>>>> -  ArrayDimension *Next = nullptr;
>>>> -};
>>>> -
>>>> -struct ArrayType : public Type {
>>>> -  Type *clone(ArenaAllocator &Arena) const override;
>>>> -  void outputPre(OutputStream &OS) override;
>>>> -  void outputPost(OutputStream &OS) override;
>>>> -
>>>> -  // Either NextDimension or ElementType will be valid.
>>>> -  ArrayDimension *Dims = nullptr;
>>>> -
>>>> -  Type *ElementType = nullptr;
>>>> -};
>>>> -
>>>> -} // namespace
>>>> -
>>>>  static bool isMemberPointer(StringView MangledName) {
>>>>    switch (MangledName.popFront()) {
>>>>    case '$':
>>>> @@ -697,40 +102,41 @@ static bool isMemberPointer(StringView M
>>>>    return false;
>>>>  }
>>>>
>>>> -static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
>>>> -  outputSpaceIfNecessary(OS);
>>>> -
>>>> -  switch (CC) {
>>>> -  case CallingConv::Cdecl:
>>>> -    OS << "__cdecl";
>>>> -    break;
>>>> -  case CallingConv::Fastcall:
>>>> -    OS << "__fastcall";
>>>> -    break;
>>>> -  case CallingConv::Pascal:
>>>> -    OS << "__pascal";
>>>> -    break;
>>>> -  case CallingConv::Regcall:
>>>> -    OS << "__regcall";
>>>> -    break;
>>>> -  case CallingConv::Stdcall:
>>>> -    OS << "__stdcall";
>>>> -    break;
>>>> -  case CallingConv::Thiscall:
>>>> -    OS << "__thiscall";
>>>> -    break;
>>>> -  case CallingConv::Eabi:
>>>> -    OS << "__eabi";
>>>> -    break;
>>>> -  case CallingConv::Vectorcall:
>>>> -    OS << "__vectorcall";
>>>> -    break;
>>>> -  case CallingConv::Clrcall:
>>>> -    OS << "__clrcall";
>>>> -    break;
>>>> -  default:
>>>> -    break;
>>>> -  }
>>>> +static SpecialIntrinsicKind
>>>> +consumeSpecialIntrinsicKind(StringView &MangledName) {
>>>> +  if (MangledName.consumeFront("?_7"))
>>>> +    return SpecialIntrinsicKind::Vftable;
>>>> +  if (MangledName.consumeFront("?_8"))
>>>> +    return SpecialIntrinsicKind::Vbtable;
>>>> +  if (MangledName.consumeFront("?_9"))
>>>> +    return SpecialIntrinsicKind::VcallThunk;
>>>> +  if (MangledName.consumeFront("?_A"))
>>>> +    return SpecialIntrinsicKind::Typeof;
>>>> +  if (MangledName.consumeFront("?_B"))
>>>> +    return SpecialIntrinsicKind::LocalStaticGuard;
>>>> +  if (MangledName.consumeFront("?_C"))
>>>> +    return SpecialIntrinsicKind::StringLiteralSymbol;
>>>> +  if (MangledName.consumeFront("?_P"))
>>>> +    return SpecialIntrinsicKind::UdtReturning;
>>>> +  if (MangledName.consumeFront("?_R0"))
>>>> +    return SpecialIntrinsicKind::RttiTypeDescriptor;
>>>> +  if (MangledName.consumeFront("?_R1"))
>>>> +    return SpecialIntrinsicKind::RttiBaseClassDescriptor;
>>>> +  if (MangledName.consumeFront("?_R2"))
>>>> +    return SpecialIntrinsicKind::RttiBaseClassArray;
>>>> +  if (MangledName.consumeFront("?_R3"))
>>>> +    return SpecialIntrinsicKind::RttiClassHierarchyDescriptor;
>>>> +  if (MangledName.consumeFront("?_R4"))
>>>> +    return SpecialIntrinsicKind::RttiCompleteObjLocator;
>>>> +  if (MangledName.consumeFront("?_S"))
>>>> +    return SpecialIntrinsicKind::LocalVftable;
>>>> +  if (MangledName.consumeFront("?__E"))
>>>> +    return SpecialIntrinsicKind::DynamicInitializer;
>>>> +  if (MangledName.consumeFront("?__F"))
>>>> +    return SpecialIntrinsicKind::DynamicAtexitDestructor;
>>>> +  if (MangledName.consumeFront("?__J"))
>>>> +    return SpecialIntrinsicKind::LocalStaticThreadGuard;
>>>> +  return SpecialIntrinsicKind::None;
>>>>  }
>>>>
>>>>  static bool startsWithLocalScopePattern(StringView S) {
>>>> @@ -774,623 +180,81 @@ static bool startsWithLocalScopePattern(
>>>>    return true;
>>>>  }
>>>>
>>>> -// Write a function or template parameter list.
>>>> -static void outputParameterList(OutputStream &OS,
>>>> -                                const FunctionParams &Params) {
>>>> -  if (!Params.Current) {
>>>> -    OS << "void";
>>>> -    return;
>>>> -  }
>>>> -
>>>> -  const FunctionParams *Head = &Params;
>>>> -  while (Head) {
>>>> -    Type::outputPre(OS, *Head->Current);
>>>> -    Type::outputPost(OS, *Head->Current);
>>>> -
>>>> -    Head = Head->Next;
>>>> -
>>>> -    if (Head)
>>>> -      OS << ", ";
>>>> -  }
>>>> -}
>>>> -
>>>> -static void outputStringLiteral(OutputStream &OS, const StringLiteral
>>>> &Str) {
>>>> -  switch (Str.CharType) {
>>>> -  case PrimTy::Wchar:
>>>> -    OS << "const wchar_t * {L\"";
>>>> -    break;
>>>> -  case PrimTy::Char:
>>>> -    OS << "const char * {\"";
>>>> -    break;
>>>> -  case PrimTy::Char16:
>>>> -    OS << "const char16_t * {u\"";
>>>> -    break;
>>>> -  case PrimTy::Char32:
>>>> -    OS << "const char32_t * {U\"";
>>>> -    break;
>>>> -  default:
>>>> -    LLVM_BUILTIN_UNREACHABLE;
>>>> -  }
>>>> -  OS << Str.Str << "\"";
>>>> -  if (Str.IsTruncated)
>>>> -    OS << "...";
>>>> -  OS << "}";
>>>> -}
>>>> -
>>>> -static void outputName(OutputStream &OS, const Name *TheName, const
>>>> Type *Ty);
>>>> -
>>>> -static void outputParameterList(OutputStream &OS,
>>>> -                                const TemplateParams &Params) {
>>>> -  if (Params.IsEmptyParameterPack) {
>>>> -    OS << "<>";
>>>> -    return;
>>>> -  }
>>>> -
>>>> -  OS << "<";
>>>> -  const TemplateParams *Head = &Params;
>>>> -  while (Head) {
>>>> -    // Type can be null if this is a template template parameter,
>>>> -    // and Name can be null if this is a simple type.
>>>> -
>>>> -    if (Head->IsIntegerLiteral) {
>>>> -      if (Head->IntegerLiteralIsNegative)
>>>> -        OS << '-';
>>>> -      OS << Head->IntegralValue;
>>>> -    } else if (Head->PointerToSymbol || Head->ReferenceToSymbol) {
>>>> -      if (Head->NullptrLiteral)
>>>> -        OS << "nullptr";
>>>> -      else {
>>>> -        if (Head->ThunkOffsetCount > 0)
>>>> -          OS << "{";
>>>> -        else if (Head->PointerToSymbol)
>>>> -          OS << "&";
>>>> -        if (Head->ParamType)
>>>> -          Type::outputPre(OS, *Head->ParamType);
>>>> -        outputName(OS, Head->ParamName, Head->ParamType);
>>>> -        if (Head->ParamType)
>>>> -          Type::outputPost(OS, *Head->ParamType);
>>>> -        if (Head->ThunkOffsetCount > 0) {
>>>> -          for (int I = 0; I < Head->ThunkOffsetCount; ++I) {
>>>> -            OS << ", " << Head->ThunkOffsets[I];
>>>> -          }
>>>> -          OS << "}";
>>>> -        }
>>>> -      }
>>>> -    } else if (Head->DataMemberPointer) {
>>>> -      OS << "{" << Head->ThunkOffsets[0];
>>>> -      for (int I = 1; I < Head->ThunkOffsetCount; ++I)
>>>> -        OS << ", " << Head->ThunkOffsets[I];
>>>> -      OS << "}";
>>>> -    } else if (Head->ParamType) {
>>>> -      // simple type.
>>>> -      Type::outputPre(OS, *Head->ParamType);
>>>> -      Type::outputPost(OS, *Head->ParamType);
>>>> -    } else {
>>>> -      // Template alias.
>>>> -      outputName(OS, Head->ParamName, Head->ParamType);
>>>> -    }
>>>> -
>>>> -    Head = Head->Next;
>>>> -
>>>> -    if (Head)
>>>> -      OS << ", ";
>>>> -  }
>>>> -  OS << ">";
>>>> -}
>>>> -
>>>> -static void outputQualifiers(OutputStream &OS, Qualifiers Q) {
>>>> -  if (Q & Q_Const) {
>>>> -    outputSpaceIfNecessary(OS);
>>>> -    OS << "const";
>>>> -  }
>>>> -
>>>> -  if (Q & Q_Volatile) {
>>>> -    outputSpaceIfNecessary(OS);
>>>> -    OS << "volatile";
>>>> -  }
>>>> -
>>>> -  if (Q & Q_Restrict) {
>>>> -    outputSpaceIfNecessary(OS);
>>>> -    OS << "__restrict";
>>>> -  }
>>>> -}
>>>> -
>>>> -static void outputNameComponent(OutputStream &OS, const Name &N) {
>>>> -  OS << N.Str;
>>>> -
>>>> -  if (N.IsTemplateInstantiation && N.TParams)
>>>> -    outputParameterList(OS, *N.TParams);
>>>> -}
>>>> -
>>>> -static const OperatorInfo *lastComponentAsOperator(const Name
>>>> *TheName) {
>>>> -  if (!TheName)
>>>> -    return nullptr;
>>>> -  while (TheName->Next)
>>>> -    TheName = TheName->Next;
>>>> -  if (TheName->IsOperator)
>>>> -    return static_cast<const OperatorInfo *>(TheName);
>>>> -  return nullptr;
>>>> -}
>>>> -
>>>> -static void outputName(OutputStream &OS, const Name *TheName, const
>>>> Type *Ty) {
>>>> -  if (!TheName)
>>>> -    return;
>>>> -
>>>> -  outputSpaceIfNecessary(OS);
>>>> -
>>>> -  const OperatorInfo *Operator = lastComponentAsOperator(TheName);
>>>> -  const VirtualMemberPtrThunk *Thunk = nullptr;
>>>> -  bool PrintLastScopeSeparator = true;
>>>> -  if (Operator) {
>>>> -    if (Operator->IsIndirectTable) {
>>>> -      const IndirectTable *Table = static_cast<const IndirectTable
>>>> *>(Operator);
>>>> -      outputName(OS, Table->TableLocation, nullptr);
>>>> -      OS << "{for `";
>>>> -      outputName(OS, Table->TableTarget, nullptr);
>>>> -      OS << "'}";
>>>> -      return;
>>>> -    }
>>>> -    if (Operator->Info->Operator == OperatorTy::Vcall) {
>>>> -      Thunk = static_cast<const VirtualMemberPtrThunk *>(Operator);
>>>> -      OS << "[thunk]: ";
>>>> -      outputCallingConvention(OS, Thunk->CC);
>>>> -      OS << " ";
>>>> -    } else if (Operator->Info->Operator ==
>>>> OperatorTy::DynamicInitializer) {
>>>> -      OS << "`dynamic initializer for '";
>>>> -      PrintLastScopeSeparator = false;
>>>> -    } else if (Operator->Info->Operator ==
>>>> -               OperatorTy::DynamicAtexitDestructor) {
>>>> -      OS << "`dynamic atexit destructor for '";
>>>> -      PrintLastScopeSeparator = false;
>>>> -    }
>>>> -  }
>>>> -
>>>> -  const Name *Previous = nullptr;
>>>> -  // Print out namespaces or outer class BackReferences.
>>>> -  for (; TheName->Next; TheName = TheName->Next) {
>>>> -    Previous = TheName;
>>>> -    outputNameComponent(OS, *TheName);
>>>> -    if (TheName->Next != Operator || PrintLastScopeSeparator)
>>>> -      OS << "::";
>>>> -  }
>>>> -
>>>> -  // Print out a regular name.
>>>> -  if (!TheName->IsOperator) {
>>>> -    outputNameComponent(OS, *TheName);
>>>> -    return;
>>>> -  }
>>>> -
>>>> -
>>>> -  // Print out ctor or dtor.
>>>> -  switch (Operator->Info->Operator) {
>>>> -  case OperatorTy::Dtor:
>>>> -    OS << "~";
>>>> -    LLVM_FALLTHROUGH;
>>>> -  case OperatorTy::Ctor:
>>>> -    // Output the class name with template arguments a second time.
>>>> -    outputNameComponent(OS, *Previous);
>>>> -
>>>> -    // Structors don't have a name, so outputting the name here
>>>> actually is a
>>>> -    // no-op.  But for template constructors, it needs to output the
>>>> template
>>>> -    // argument list.  e.g.
>>>> -    //
>>>> -    // template<typename T>
>>>> -    // struct Foo {
>>>> -    //    template<typename U>
>>>> -    //    Foo(U);
>>>> -    // };
>>>> -    // should demangle as -- for example -- Foo<int><double>(double);
>>>> -    outputNameComponent(OS, *TheName);
>>>> -    break;
>>>> -  case OperatorTy::Conversion:
>>>> -    OS << "operator";
>>>> -    if (TheName->IsTemplateInstantiation && TheName->TParams)
>>>> -      outputParameterList(OS, *TheName->TParams);
>>>> -    OS << " ";
>>>> -    if (Ty) {
>>>> -      const FunctionType *FTy = static_cast<const FunctionType *>(Ty);
>>>> -      Type::outputPre(OS, *FTy->ReturnType);
>>>> -      Type::outputPost(OS, *FTy->ReturnType);
>>>> -    } else {
>>>> -      OS << "<conversion>";
>>>> -    }
>>>> -    break;
>>>> -  case OperatorTy::LiteralOperator:
>>>> -    OS << Operator->Info->Name;
>>>> -    outputNameComponent(OS, *TheName);
>>>> -    break;
>>>> -  case OperatorTy::RttiBaseClassDescriptor: {
>>>> -    const RttiBaseClassDescriptor &BCD =
>>>> -        static_cast<const RttiBaseClassDescriptor &>(*Operator);
>>>> -    OS << "`" << Operator->Info->Name << " at (";
>>>> -    OS << BCD.NVOffset << ", " << BCD.VBPtrOffset << ", " <<
>>>> BCD.VBTableOffset
>>>> -       << ", " << BCD.Flags;
>>>> -    OS << ")'";
>>>> -    break;
>>>> -  }
>>>> -  case OperatorTy::Vcall: {
>>>> -    OS << "`vcall'{";
>>>> -    OS << Thunk->OffsetInVTable << ", {flat}}";
>>>> -    break;
>>>> -  }
>>>> -  case OperatorTy::DynamicInitializer:
>>>> -  case OperatorTy::DynamicAtexitDestructor:
>>>> -    OS << "''";
>>>> -    break;
>>>> -
>>>> -  case OperatorTy::LocalStaticGuard: {
>>>> -    const LocalStaticGuardVariable &LSG =
>>>> -        static_cast<const LocalStaticGuardVariable &>(*Operator);
>>>> -    OS << Operator->Info->Name;
>>>> -    if (LSG.ScopeIndex > 0)
>>>> -      OS << "{" << LSG.ScopeIndex << "}";
>>>> -    break;
>>>> -  }
>>>> -  default:
>>>> -    OS << Operator->Info->Name;
>>>> -    if (Operator->IsTemplateInstantiation)
>>>> -      outputParameterList(OS, *Operator->TParams);
>>>> -    break;
>>>> -  }
>>>> -}
>>>> -
>>>> -static void outputSpecialOperator(OutputStream &OS, const Name
>>>> *OuterName) {
>>>> -  assert(OuterName);
>>>> -  // The last component should be an operator.
>>>> -  const OperatorInfo *Operator = lastComponentAsOperator(OuterName);
>>>> -
>>>> -  assert(Operator->IsOperator);
>>>> -  const OperatorInfo &Oper = static_cast<const OperatorInfo
>>>> &>(*Operator);
>>>> -  switch (Oper.Info->Operator) {
>>>> -  case OperatorTy::StringLiteral: {
>>>> -    const StringLiteral &SL = static_cast<const StringLiteral &>(Oper);
>>>> -    outputStringLiteral(OS, SL);
>>>> -    break;
>>>> -  }
>>>> -  case OperatorTy::Vcall: {
>>>> -    const VirtualMemberPtrThunk &Thunk =
>>>> -        static_cast<const VirtualMemberPtrThunk &>(Oper);
>>>> -    OS << "[thunk]: ";
>>>> -    outputCallingConvention(OS, Thunk.CC);
>>>> -    OS << " ";
>>>> -    // Print out namespaces or outer class BackReferences.
>>>> -    const Name *N = OuterName;
>>>> -    for (; N->Next; N = N->Next) {
>>>> -      outputNameComponent(OS, *N);
>>>> -      OS << "::";
>>>> -    }
>>>> -    OS << "`vcall'{";
>>>> -    OS << Thunk.OffsetInVTable << ", {flat}}";
>>>> -    break;
>>>> -  }
>>>> -  default:
>>>> -    // There are no other special operator categories.
>>>> -    LLVM_BUILTIN_UNREACHABLE;
>>>> -  }
>>>> -}
>>>> -
>>>> -namespace {
>>>> -
>>>> -Type *Type::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<Type>(*this);
>>>> -}
>>>> -
>>>> -// Write the "first half" of a given type.
>>>> -void Type::outputPre(OutputStream &OS, Type &Ty) {
>>>> -  // Function types require custom handling of const and static so we
>>>> -  // handle them separately.  All other types use the same decoration
>>>> -  // for these modifiers, so handle them here in common code.
>>>> -  if (Ty.Prim == PrimTy::Function) {
>>>> -    Ty.outputPre(OS);
>>>> -    return;
>>>> -  }
>>>> -
>>>> -  switch (Ty.Storage) {
>>>> -  case StorageClass::PrivateStatic:
>>>> -  case StorageClass::PublicStatic:
>>>> -  case StorageClass::ProtectedStatic:
>>>> -    OS << "static ";
>>>> -  default:
>>>> -    break;
>>>> -  }
>>>> -  Ty.outputPre(OS);
>>>> -
>>>> -  outputQualifiers(OS, Ty.Quals);
>>>> -}
>>>> -
>>>> -// Write the "second half" of a given type.
>>>> -void Type::outputPost(OutputStream &OS, Type &Ty) { Ty.outputPost(OS);
>>>> }
>>>> -
>>>> -void Type::outputPre(OutputStream &OS) {
>>>> -  switch (Prim) {
>>>> -  case PrimTy::Void:
>>>> -    OS << "void";
>>>> -    break;
>>>> -  case PrimTy::Bool:
>>>> -    OS << "bool";
>>>> -    break;
>>>> -  case PrimTy::Char:
>>>> -    OS << "char";
>>>> -    break;
>>>> -  case PrimTy::Schar:
>>>> -    OS << "signed char";
>>>> -    break;
>>>> -  case PrimTy::Uchar:
>>>> -    OS << "unsigned char";
>>>> -    break;
>>>> -  case PrimTy::Char16:
>>>> -    OS << "char16_t";
>>>> -    break;
>>>> -  case PrimTy::Char32:
>>>> -    OS << "char32_t";
>>>> -    break;
>>>> -  case PrimTy::Short:
>>>> -    OS << "short";
>>>> -    break;
>>>> -  case PrimTy::Ushort:
>>>> -    OS << "unsigned short";
>>>> -    break;
>>>> -  case PrimTy::Int:
>>>> -    OS << "int";
>>>> -    break;
>>>> -  case PrimTy::Uint:
>>>> -    OS << "unsigned int";
>>>> -    break;
>>>> -  case PrimTy::Long:
>>>> -    OS << "long";
>>>> -    break;
>>>> -  case PrimTy::Ulong:
>>>> -    OS << "unsigned long";
>>>> -    break;
>>>> -  case PrimTy::Int64:
>>>> -    OS << "__int64";
>>>> -    break;
>>>> -  case PrimTy::Uint64:
>>>> -    OS << "unsigned __int64";
>>>> -    break;
>>>> -  case PrimTy::Wchar:
>>>> -    OS << "wchar_t";
>>>> -    break;
>>>> -  case PrimTy::Float:
>>>> -    OS << "float";
>>>> -    break;
>>>> -  case PrimTy::Double:
>>>> -    OS << "double";
>>>> -    break;
>>>> -  case PrimTy::Ldouble:
>>>> -    OS << "long double";
>>>> -    break;
>>>> -  case PrimTy::Nullptr:
>>>> -    OS << "std::nullptr_t";
>>>> -    break;
>>>> -  case PrimTy::Custom:
>>>> -    OS << Custom;
>>>> -    break;
>>>> -  case PrimTy::Vbtable:
>>>> -  case PrimTy::Vftable:
>>>> -    break;
>>>> -  default:
>>>> -    assert(false && "Invalid primitive type!");
>>>> +static bool isTagType(StringView S) {
>>>> +  switch (S.front()) {
>>>> +  case 'T': // union
>>>> +  case 'U': // struct
>>>> +  case 'V': // class
>>>> +  case 'W': // enum
>>>> +    return true;
>>>>    }
>>>> -}
>>>> -void Type::outputPost(OutputStream &OS) {}
>>>> -
>>>> -Type *PointerType::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<PointerType>(*this);
>>>> +  return false;
>>>>  }
>>>>
>>>> -static void outputPointerIndicator(OutputStream &OS, PointerAffinity
>>>> Affinity,
>>>> -                                   const Name *MemberName,
>>>> -                                   const Type *Pointee) {
>>>> -  // "[]" and "()" (for function parameters) take precedence over "*",
>>>> -  // so "int *x(int)" means "x is a function returning int *". We need
>>>> -  // parentheses to supercede the default precedence. (e.g. we want to
>>>> -  // emit something like "int (*x)(int)".)
>>>> -  if (Pointee->Prim == PrimTy::Function || Pointee->Prim ==
>>>> PrimTy::Array) {
>>>> -    OS << "(";
>>>> -    if (Pointee->Prim == PrimTy::Function) {
>>>> -      const FunctionType *FTy = static_cast<const FunctionType
>>>> *>(Pointee);
>>>> -      assert(FTy->IsFunctionPointer);
>>>> -      outputCallingConvention(OS, FTy->CallConvention);
>>>> -      OS << " ";
>>>> -    }
>>>> -  }
>>>> +static bool isPointerType(StringView S) {
>>>> +  if (S.startsWith("$$Q")) // foo &&
>>>> +    return true;
>>>>
>>>> -  if (MemberName) {
>>>> -    outputName(OS, MemberName, Pointee);
>>>> -    OS << "::";
>>>> +  switch (S.front()) {
>>>> +  case 'A': // foo &
>>>> +  case 'P': // foo *
>>>> +  case 'Q': // foo *const
>>>> +  case 'R': // foo *volatile
>>>> +  case 'S': // foo *const volatile
>>>> +    return true;
>>>>    }
>>>> -
>>>> -  if (Affinity == PointerAffinity::Pointer)
>>>> -    OS << "*";
>>>> -  else if (Affinity == PointerAffinity::Reference)
>>>> -    OS << "&";
>>>> -  else
>>>> -    OS << "&&";
>>>> -}
>>>> -
>>>> -void PointerType::outputPre(OutputStream &OS) {
>>>> -  Type::outputPre(OS, *Pointee);
>>>> -
>>>> -  outputSpaceIfNecessary(OS);
>>>> -
>>>> -  if (Quals & Q_Unaligned)
>>>> -    OS << "__unaligned ";
>>>> -
>>>> -  outputPointerIndicator(OS, Affinity, nullptr, Pointee);
>>>> -
>>>> -  // FIXME: We should output this, but it requires updating lots of
>>>> tests.
>>>> -  // if (Ty.Quals & Q_Pointer64)
>>>> -  //  OS << " __ptr64";
>>>> -}
>>>> -
>>>> -void PointerType::outputPost(OutputStream &OS) {
>>>> -  if (Pointee->Prim == PrimTy::Function || Pointee->Prim ==
>>>> PrimTy::Array)
>>>> -    OS << ")";
>>>> -
>>>> -  Type::outputPost(OS, *Pointee);
>>>> -}
>>>> -
>>>> -Type *MemberPointerType::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<MemberPointerType>(*this);
>>>> -}
>>>> -
>>>> -void MemberPointerType::outputPre(OutputStream &OS) {
>>>> -  Type::outputPre(OS, *Pointee);
>>>> -
>>>> -  outputSpaceIfNecessary(OS);
>>>> -
>>>> -  outputPointerIndicator(OS, PointerAffinity::Pointer, MemberName,
>>>> Pointee);
>>>> -
>>>> -  // FIXME: We should output this, but it requires updating lots of
>>>> tests.
>>>> -  // if (Ty.Quals & Q_Pointer64)
>>>> -  //  OS << " __ptr64";
>>>> -}
>>>> -
>>>> -void MemberPointerType::outputPost(OutputStream &OS) {
>>>> -  if (Pointee->Prim == PrimTy::Function || Pointee->Prim ==
>>>> PrimTy::Array)
>>>> -    OS << ")";
>>>> -
>>>> -  Type::outputPost(OS, *Pointee);
>>>> -}
>>>> -
>>>> -Type *FunctionType::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<FunctionType>(*this);
>>>> +  return false;
>>>>  }
>>>>
>>>> -void FunctionType::outputPre(OutputStream &OS) {
>>>> -  if ((FunctionClass & StaticThisAdjust) || (FunctionClass &
>>>> VirtualThisAdjust))
>>>> -    OS << "[thunk]: ";
>>>> -
>>>> -  if (!(FunctionClass & Global)) {
>>>> -    if (FunctionClass & Static)
>>>> -      OS << "static ";
>>>> -  }
>>>> -  if (FunctionClass & ExternC)
>>>> -    OS << "extern \"C\" ";
>>>> -
>>>> -  if (FunctionClass & Virtual)
>>>> -    OS << "virtual ";
>>>> -
>>>> -  if (ReturnType) {
>>>> -    Type::outputPre(OS, *ReturnType);
>>>> -    OS << " ";
>>>> -  }
>>>> +static bool isArrayType(StringView S) { return S[0] == 'Y'; }
>>>>
>>>> -  // Function pointers print the calling convention as void (__cdecl
>>>> *)(params)
>>>> -  // rather than void __cdecl (*)(params).  So we need to let the
>>>> PointerType
>>>> -  // class handle this.
>>>> -  if (!IsFunctionPointer)
>>>> -    outputCallingConvention(OS, CallConvention);
>>>> +static bool isFunctionType(StringView S) {
>>>> +  return S.startsWith("$$A8@@") || S.startsWith("$$A6");
>>>>  }
>>>>
>>>> -void FunctionType::outputPost(OutputStream &OS) {
>>>> -  // extern "C" functions don't have a prototype.
>>>> -  if (FunctionClass & NoPrototype)
>>>> -    return;
>>>> -
>>>> -  if (FunctionClass & StaticThisAdjust) {
>>>> -    OS << "`adjustor{" << ThisAdjust->StaticOffset << "}'";
>>>> -  } else if (FunctionClass & VirtualThisAdjust) {
>>>> -    if (FunctionClass & VirtualThisAdjustEx) {
>>>> -      OS << "`vtordispex{" << ThisAdjust->VBPtrOffset << ", "
>>>> -         << ThisAdjust->VBOffsetOffset << ", " <<
>>>> ThisAdjust->VtordispOffset
>>>> -         << ", " << ThisAdjust->StaticOffset << "}'";
>>>> -    } else {
>>>> -      OS << "`vtordisp{" << ThisAdjust->VtordispOffset << ", "
>>>> -         << ThisAdjust->StaticOffset << "}'";
>>>> -    }
>>>> -  }
>>>> -
>>>> -  OS << "(";
>>>> -  outputParameterList(OS, Params);
>>>> -  OS << ")";
>>>> -  if (Quals & Q_Const)
>>>> -    OS << " const";
>>>> -  if (Quals & Q_Volatile)
>>>> -    OS << " volatile";
>>>> -  if (Quals & Q_Restrict)
>>>> -    OS << " __restrict";
>>>> -  if (Quals & Q_Unaligned)
>>>> -    OS << " __unaligned";
>>>> -
>>>> -  if (RefKind == ReferenceKind::LValueRef)
>>>> -    OS << " &";
>>>> -  else if (RefKind == ReferenceKind::RValueRef)
>>>> -    OS << " &&";
>>>> -
>>>> -  if (ReturnType)
>>>> -    Type::outputPost(OS, *ReturnType);
>>>> -  return;
>>>> +static FunctionRefQualifier
>>>> +demangleFunctionRefQualifier(StringView &MangledName) {
>>>> +  if (MangledName.consumeFront('G'))
>>>> +    return FunctionRefQualifier::Reference;
>>>> +  else if (MangledName.consumeFront('H'))
>>>> +    return FunctionRefQualifier::RValueReference;
>>>> +  return FunctionRefQualifier::None;
>>>>  }
>>>>
>>>> -Type *UdtType::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<UdtType>(*this);
>>>> -}
>>>> +static std::pair<Qualifiers, PointerAffinity>
>>>> +demanglePointerCVQualifiers(StringView &MangledName) {
>>>> +  if (MangledName.consumeFront("$$Q"))
>>>> +    return std::make_pair(Q_None, PointerAffinity::RValueReference);
>>>>
>>>> -void UdtType::outputPre(OutputStream &OS) {
>>>> -  switch (Prim) {
>>>> -  case PrimTy::Class:
>>>> -    OS << "class ";
>>>> -    break;
>>>> -  case PrimTy::Struct:
>>>> -    OS << "struct ";
>>>> -    break;
>>>> -  case PrimTy::Union:
>>>> -    OS << "union ";
>>>> -    break;
>>>> -  case PrimTy::Enum:
>>>> -    OS << "enum ";
>>>> -    break;
>>>> +  switch (MangledName.popFront()) {
>>>> +  case 'A':
>>>> +    return std::make_pair(Q_None, PointerAffinity::Reference);
>>>> +  case 'P':
>>>> +    return std::make_pair(Q_None, PointerAffinity::Pointer);
>>>> +  case 'Q':
>>>> +    return std::make_pair(Q_Const, PointerAffinity::Pointer);
>>>> +  case 'R':
>>>> +    return std::make_pair(Q_Volatile, PointerAffinity::Pointer);
>>>> +  case 'S':
>>>> +    return std::make_pair(Qualifiers(Q_Const | Q_Volatile),
>>>> +                          PointerAffinity::Pointer);
>>>>    default:
>>>> -    assert(false && "Not a udt type!");
>>>> -  }
>>>> -
>>>> -  outputName(OS, UdtName, this);
>>>> -}
>>>> -
>>>> -Type *ArrayType::clone(ArenaAllocator &Arena) const {
>>>> -  return Arena.alloc<ArrayType>(*this);
>>>> -}
>>>> -
>>>> -void ArrayType::outputPre(OutputStream &OS) {
>>>> -  Type::outputPre(OS, *ElementType);
>>>> -}
>>>> -
>>>> -void ArrayType::outputPost(OutputStream &OS) {
>>>> -  ArrayDimension *D = Dims;
>>>> -  while (D) {
>>>> -    OS << "[";
>>>> -    if (D->Dim > 0)
>>>> -      OS << D->Dim;
>>>> -    OS << "]";
>>>> -    D = D->Next;
>>>> +    assert(false && "Ty is not a pointer type!");
>>>>    }
>>>> -
>>>> -  Type::outputPost(OS, *ElementType);
>>>> +  return std::make_pair(Q_None, PointerAffinity::Pointer);
>>>>  }
>>>>
>>>> -struct Symbol {
>>>> -  SymbolCategory Category;
>>>> -
>>>> -  Qualifiers SymbolQuals = Q_None;
>>>> -  Name *SymbolName = nullptr;
>>>> -  Type *SymbolType = nullptr;
>>>> -};
>>>> -
>>>> -} // namespace
>>>> -
>>>>  namespace {
>>>>
>>>>  struct BackrefContext {
>>>>    static constexpr size_t Max = 10;
>>>>
>>>> -  Type *FunctionParams[Max];
>>>> +  TypeNode *FunctionParams[Max];
>>>>    size_t FunctionParamCount = 0;
>>>>
>>>>    // The first 10 BackReferences in a mangled name can be
>>>> back-referenced by
>>>>    // special name @[0-9]. This is a storage for the first 10
>>>> BackReferences.
>>>> -  StringView Names[Max];
>>>> +  NamedIdentifierNode *Names[Max];
>>>>    size_t NamesCount = 0;
>>>>  };
>>>>
>>>> @@ -1404,10 +268,7 @@ public:
>>>>
>>>>    // You are supposed to call parse() first and then check if error is
>>>> true.  If
>>>>    // it is false, call output() to write the formatted name to the
>>>> given stream.
>>>> -  Symbol *parse(StringView &MangledName);
>>>> -  Symbol *parseOperator(StringView &MangledName);
>>>> -
>>>> -  void output(const Symbol *S, OutputStream &OS);
>>>> +  SymbolNode *parse(StringView &MangledName);
>>>>
>>>>    // True if an error occurred.
>>>>    bool Error = false;
>>>> @@ -1415,28 +276,28 @@ public:
>>>>    void dumpBackReferences();
>>>>
>>>>  private:
>>>> -  std::pair<SymbolCategory, Type *>
>>>> -  demangleSymbolCategoryAndType(StringView &MangledName);
>>>> +  SymbolNode *demangleEncodedSymbol(StringView &MangledName,
>>>> +                                    QualifiedNameNode *QN);
>>>>
>>>> -  Type *demangleVariableEncoding(StringView &MangledName, StorageClass
>>>> SC);
>>>> -  Type *demangleFunctionEncoding(StringView &MangledName);
>>>> -  uint64_t demangleThunkThisAdjust(StringView &MangledName);
>>>> +  VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
>>>> +                                               StorageClass SC);
>>>> +  FunctionSymbolNode *demangleFunctionEncoding(StringView
>>>> &MangledName);
>>>>
>>>>    Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
>>>>
>>>>    // Parser functions. This is a recursive-descent parser.
>>>> -  Type *demangleType(StringView &MangledName, QualifierMangleMode QMM);
>>>> -  Type *demangleBasicType(StringView &MangledName);
>>>> -  UdtType *demangleClassType(StringView &MangledName);
>>>> -  PointerType *demanglePointerType(StringView &MangledName);
>>>> -  MemberPointerType *demangleMemberPointerType(StringView
>>>> &MangledName);
>>>> -  FunctionType *demangleFunctionType(StringView &MangledName, bool
>>>> HasThisQuals,
>>>> -                                     bool IsFunctionPointer);
>>>> +  TypeNode *demangleType(StringView &MangledName, QualifierMangleMode
>>>> QMM);
>>>> +  PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
>>>> +  TagTypeNode *demangleClassType(StringView &MangledName);
>>>> +  PointerTypeNode *demanglePointerType(StringView &MangledName);
>>>> +  PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
>>>> +  FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
>>>> +                                              bool HasThisQuals);
>>>>
>>>> -  ArrayType *demangleArrayType(StringView &MangledName);
>>>> +  ArrayTypeNode *demangleArrayType(StringView &MangledName);
>>>>
>>>> -  TemplateParams *demangleTemplateParameterList(StringView
>>>> &MangledName);
>>>> -  FunctionParams demangleFunctionParameterList(StringView
>>>> &MangledName);
>>>> +  NodeArrayNode *demangleTemplateParameterList(StringView
>>>> &MangledName);
>>>> +  NodeArrayNode *demangleFunctionParameterList(StringView
>>>> &MangledName);
>>>>
>>>>    std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
>>>>    uint64_t demangleUnsigned(StringView &MangledName);
>>>> @@ -1447,32 +308,59 @@ private:
>>>>    /// Allocate a copy of \p Borrowed into memory that we own.
>>>>    StringView copyString(StringView Borrowed);
>>>>
>>>> -  Name *demangleFullyQualifiedTypeName(StringView &MangledName);
>>>> -  Name *demangleFullyQualifiedSymbolName(StringView &MangledName);
>>>> +  QualifiedNameNode *demangleFullyQualifiedTypeName(StringView
>>>> &MangledName);
>>>> +  QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView
>>>> &MangledName);
>>>>
>>>> -  Name *demangleUnqualifiedTypeName(StringView &MangledName, bool
>>>> Memorize);
>>>> -  Name *demangleUnqualifiedSymbolName(StringView &MangledName,
>>>> -                                      NameBackrefBehavior NBB);
>>>> -
>>>> -  Name *demangleNameScopeChain(StringView &MangledName, Name
>>>> *UnqualifiedName);
>>>> -  Name *demangleNameScopePiece(StringView &MangledName);
>>>> -
>>>> -  Name *demangleBackRefName(StringView &MangledName);
>>>> -  Name *demangleTemplateInstantiationName(StringView &MangledName,
>>>> -                                          NameBackrefBehavior NBB);
>>>> -  std::pair<OperatorTy, Name *> demangleOperatorName(StringView
>>>> &MangledName,
>>>> -                                                     bool
>>>> FullyQualified);
>>>> -  Name *demangleSimpleName(StringView &MangledName, bool Memorize);
>>>> -  Name *demangleAnonymousNamespaceName(StringView &MangledName);
>>>> -  Name *demangleLocallyScopedNamePiece(StringView &MangledName);
>>>> -  StringLiteral *demangleStringLiteral(StringView &MangledName);
>>>> +  IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
>>>> +                                              bool Memorize);
>>>> +  IdentifierNode *demangleUnqualifiedSymbolName(StringView
>>>> &MangledName,
>>>> +                                                NameBackrefBehavior
>>>> NBB);
>>>> +
>>>> +  QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
>>>> +                                            IdentifierNode
>>>> *UnqualifiedName);
>>>> +  IdentifierNode *demangleNameScopePiece(StringView &MangledName);
>>>> +
>>>> +  NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
>>>> +  IdentifierNode *demangleTemplateInstantiationName(StringView
>>>> &MangledName,
>>>> +
>>>> NameBackrefBehavior NBB);
>>>> +  IdentifierNode *demangleFunctionIdentifierCode(StringView
>>>> &MangledName);
>>>> +  IdentifierNode *
>>>> +  demangleFunctionIdentifierCode(StringView &MangledName,
>>>> +                                 FunctionIdentifierCodeGroup Group);
>>>> +  StructorIdentifierNode *demangleStructorIdentifier(StringView
>>>> &MangledName,
>>>> +                                                     bool
>>>> IsDestructor);
>>>> +  ConversionOperatorIdentifierNode *
>>>> +  demangleConversionOperatorIdentifier(StringView &MangledName);
>>>> +  LiteralOperatorIdentifierNode *
>>>> +  demangleLiteralOperatorIdentifier(StringView &MangledName);
>>>> +
>>>> +  SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
>>>> +  SpecialTableSymbolNode *
>>>> +  demangleSpecialTableSymbolNode(StringView &MangledName,
>>>> +                                 SpecialIntrinsicKind SIK);
>>>> +  LocalStaticGuardVariableNode *
>>>> +  demangleLocalStaticGuard(StringView &MangledName);
>>>> +  VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
>>>> +                                              StringView &MangledName,
>>>> +                                              StringView VariableName);
>>>> +  VariableSymbolNode *
>>>> +  demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
>>>> +                                      StringView &MangledName);
>>>> +  FunctionSymbolNode *demangleDynamicStructorFunction(StringView
>>>> &MangledName,
>>>> +                                                      bool
>>>> IsDestructor);
>>>> +
>>>> +  NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
>>>> +                                          bool Memorize);
>>>> +  NamedIdentifierNode *demangleAnonymousNamespaceName(StringView
>>>> &MangledName);
>>>> +  NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView
>>>> &MangledName);
>>>> +  EncodedStringLiteralNode *demangleStringLiteral(StringView
>>>> &MangledName);
>>>> +  FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
>>>>
>>>>    StringView demangleSimpleString(StringView &MangledName, bool
>>>> Memorize);
>>>>
>>>>    FuncClass demangleFunctionClass(StringView &MangledName);
>>>>    CallingConv demangleCallingConvention(StringView &MangledName);
>>>>    StorageClass demangleVariableStorageClass(StringView &MangledName);
>>>> -  ReferenceKind demangleReferenceKind(StringView &MangledName);
>>>>    void demangleThrowSpecification(StringView &MangledName);
>>>>    wchar_t demangleWcharLiteral(StringView &MangledName);
>>>>    uint8_t demangleCharLiteral(StringView &MangledName);
>>>> @@ -1506,121 +394,455 @@ StringView Demangler::copyString(StringV
>>>>    return {Stable, Borrowed.size()};
>>>>  }
>>>>
>>>> -Symbol *Demangler::parseOperator(StringView &MangledName) {
>>>> -  Symbol *S = Arena.alloc<Symbol>();
>>>> -
>>>> -  bool IsMember = false;
>>>> -  OperatorTy OTy;
>>>> -  std::tie(OTy, S->SymbolName) = demangleOperatorName(MangledName,
>>>> true);
>>>> -  switch (OTy) {
>>>> -  case OperatorTy::StringLiteral:
>>>> -    S->Category = SymbolCategory::SpecialOperator;
>>>> +SpecialTableSymbolNode *
>>>> +Demangler::demangleSpecialTableSymbolNode(StringView &MangledName,
>>>> +                                          SpecialIntrinsicKind K) {
>>>> +  NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>();
>>>> +  switch (K) {
>>>> +  case SpecialIntrinsicKind::Vftable:
>>>> +    NI->Name = "`vftable'";
>>>>      break;
>>>> -  case OperatorTy::Vcall:
>>>> -    S->Category = SymbolCategory::UnnamedFunction;
>>>> +  case SpecialIntrinsicKind::Vbtable:
>>>> +    NI->Name = "`vbtable'";
>>>>      break;
>>>> -  case OperatorTy::LocalStaticGuard:
>>>> -    S->Category = SymbolCategory::UnnamedVariable;
>>>> +  case SpecialIntrinsicKind::LocalVftable:
>>>> +    NI->Name = "`local vftable'";
>>>>      break;
>>>> -  case OperatorTy::Vftable:                // Foo@@6B@
>>>> -  case OperatorTy::LocalVftable:           // Foo@@6B@
>>>> -  case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@
>>>> -  case OperatorTy::Vbtable:                // Foo@@7B@
>>>> -    S->Category = SymbolCategory::UnnamedVariable;
>>>> -    switch (MangledName.popFront()) {
>>>> -    case '6':
>>>> -    case '7': {
>>>> -      std::tie(S->SymbolQuals, IsMember) =
>>>> demangleQualifiers(MangledName);
>>>> -      if (!MangledName.consumeFront('@')) {
>>>> -        IndirectTable *Table = Arena.alloc<IndirectTable>(OTy);
>>>> -        Table->TableTarget =
>>>> demangleFullyQualifiedTypeName(MangledName);
>>>> -        Table->TableLocation = S->SymbolName;
>>>> -        S->SymbolName = Table;
>>>> -      }
>>>> -      break;
>>>> -    }
>>>> -    default:
>>>> -      Error = true;
>>>> -      break;
>>>> -    }
>>>> +  case SpecialIntrinsicKind::RttiCompleteObjLocator:
>>>> +    NI->Name = "`RTTI Complete Object Locator'";
>>>>      break;
>>>> -  case OperatorTy::RttiTypeDescriptor: // <type>@@8
>>>> -    S->Category = SymbolCategory::UnnamedVariable;
>>>> -    S->SymbolType = demangleType(MangledName,
>>>> QualifierMangleMode::Result);
>>>> +  default:
>>>> +    LLVM_BUILTIN_UNREACHABLE;
>>>> +  }
>>>> +  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
>>>> +  SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>();
>>>> +  STSN->Name = QN;
>>>> +  bool IsMember = false;
>>>> +  char Front = MangledName.popFront();
>>>> +  if (Front != '6' && Front != '7') {
>>>> +    Error = true;
>>>> +    return nullptr;
>>>> +  }
>>>> +
>>>> +  std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
>>>> +  if (!MangledName.consumeFront('@'))
>>>> +    STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);
>>>> +  return STSN;
>>>> +}
>>>> +
>>>> +LocalStaticGuardVariableNode *
>>>> +Demangler::demangleLocalStaticGuard(StringView &MangledName) {
>>>> +  LocalStaticGuardIdentifierNode *LSGI =
>>>> +      Arena.alloc<LocalStaticGuardIdentifierNode>();
>>>> +  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
>>>> +  LocalStaticGuardVariableNode *LSGVN =
>>>> +      Arena.alloc<LocalStaticGuardVariableNode>();
>>>> +  LSGVN->Name = QN;
>>>> +
>>>> +  if (MangledName.consumeFront("4IA"))
>>>> +    LSGVN->IsVisible = false;
>>>> +  else if (MangledName.consumeFront("5"))
>>>> +    LSGVN->IsVisible = true;
>>>> +  else {
>>>> +    Error = true;
>>>> +    return nullptr;
>>>> +  }
>>>> +
>>>> +  if (!MangledName.empty())
>>>> +    LSGI->ScopeIndex = demangleUnsigned(MangledName);
>>>> +  return LSGVN;
>>>> +}
>>>> +
>>>> +static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator
>>>> &Arena,
>>>> +                                                      StringView Name)
>>>> {
>>>> +  NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>();
>>>> +  Id->Name = Name;
>>>> +  return Id;
>>>> +}
>>>> +
>>>> +static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator
>>>> &Arena,
>>>> +                                                  IdentifierNode
>>>> *Identifier) {
>>>> +  QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
>>>> +  QN->Components = Arena.alloc<NodeArrayNode>();
>>>> +  QN->Components->Count = 1;
>>>> +  QN->Components->Nodes = Arena.allocArray<Node *>(1);
>>>> +  QN->Components->Nodes[0] = Identifier;
>>>> +  return QN;
>>>> +}
>>>> +
>>>> +static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator
>>>> &Arena,
>>>> +                                                  StringView Name) {
>>>> +  NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name);
>>>> +  return synthesizeQualifiedName(Arena, Id);
>>>> +}
>>>> +
>>>> +static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena,
>>>> +                                              TypeNode *Type,
>>>> +                                              StringView VariableName)
>>>> {
>>>> +  VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
>>>> +  VSN->Type = Type;
>>>> +  VSN->Name = synthesizeQualifiedName(Arena, VariableName);
>>>> +  return VSN;
>>>> +}
>>>> +
>>>> +VariableSymbolNode *Demangler::demangleUntypedVariable(
>>>> +    ArenaAllocator &Arena, StringView &MangledName, StringView
>>>> VariableName) {
>>>> +  NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena,
>>>> VariableName);
>>>> +  QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
>>>> +  VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
>>>> +  VSN->Name = QN;
>>>> +  if (MangledName.consumeFront("8"))
>>>> +    return VSN;
>>>> +
>>>> +  Error = true;
>>>> +  return nullptr;
>>>> +}
>>>> +
>>>> +VariableSymbolNode *
>>>> +Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
>>>> +                                               StringView
>>>> &MangledName) {
>>>> +  RttiBaseClassDescriptorNode *RBCDN =
>>>> +      Arena.alloc<RttiBaseClassDescriptorNode>();
>>>> +  RBCDN->NVOffset = demangleUnsigned(MangledName);
>>>> +  RBCDN->VBPtrOffset = demangleSigned(MangledName);
>>>> +  RBCDN->VBTableOffset = demangleUnsigned(MangledName);
>>>> +  RBCDN->Flags = demangleUnsigned(MangledName);
>>>> +  if (Error)
>>>> +    return nullptr;
>>>> +
>>>> +  VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
>>>> +  VSN->Name = demangleNameScopeChain(MangledName, RBCDN);
>>>> +  MangledName.consumeFront('8');
>>>> +  return VSN;
>>>> +}
>>>> +
>>>> +FunctionSymbolNode *
>>>> +Demangler::demangleDynamicStructorFunction(StringView &MangledName,
>>>> +                                           bool IsDestructor) {
>>>> +  DynamicStructorIdentifierNode *DSIN =
>>>> +      Arena.alloc<DynamicStructorIdentifierNode>();
>>>> +  DSIN->IsDestructor = IsDestructor;
>>>> +  DSIN->Name = demangleFullyQualifiedTypeName(MangledName);
>>>> +  QualifiedNameNode *QNN = synthesizeQualifiedName(Arena, DSIN);
>>>> +  FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
>>>> +  FSN->Name = QNN;
>>>> +  return FSN;
>>>> +}
>>>> +
>>>> +SymbolNode *Demangler::demangleSpecialIntrinsic(StringView
>>>> &MangledName) {
>>>> +  SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName);
>>>> +  if (SIK == SpecialIntrinsicKind::None)
>>>> +    return nullptr;
>>>> +
>>>> +  switch (SIK) {
>>>> +  case SpecialIntrinsicKind::StringLiteralSymbol:
>>>> +    return demangleStringLiteral(MangledName);
>>>> +  case SpecialIntrinsicKind::Vftable:
>>>> +  case SpecialIntrinsicKind::Vbtable:
>>>> +  case SpecialIntrinsicKind::LocalVftable:
>>>> +  case SpecialIntrinsicKind::RttiCompleteObjLocator:
>>>> +    return demangleSpecialTableSymbolNode(MangledName, SIK);
>>>> +  case SpecialIntrinsicKind::VcallThunk:
>>>> +    return demangleVcallThunkNode(MangledName);
>>>> +  case SpecialIntrinsicKind::LocalStaticGuard:
>>>> +    return demangleLocalStaticGuard(MangledName);
>>>> +  case SpecialIntrinsicKind::RttiTypeDescriptor: {
>>>> +    TypeNode *T = demangleType(MangledName,
>>>> QualifierMangleMode::Result);
>>>>      if (Error)
>>>>        break;
>>>>      if (!MangledName.consumeFront("@8"))
>>>> -      Error = true;
>>>> +      break;
>>>>      if (!MangledName.empty())
>>>> -      Error = true;
>>>> -    break;
>>>> +      break;
>>>> +    return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");
>>>> +  }
>>>> +  case SpecialIntrinsicKind::RttiBaseClassArray:
>>>> +    return demangleUntypedVariable(Arena, MangledName,
>>>> +                                   "`RTTI Base Class Array'");
>>>> +  case SpecialIntrinsicKind::RttiClassHierarchyDescriptor:
>>>> +    return demangleUntypedVariable(Arena, MangledName,
>>>> +                                   "`RTTI Class Hierarchy
>>>> Descriptor'");
>>>> +  case SpecialIntrinsicKind::RttiBaseClassDescriptor:
>>>> +    return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
>>>> +  case SpecialIntrinsicKind::DynamicInitializer:
>>>> +    return demangleDynamicStructorFunction(MangledName, false);
>>>> +  case SpecialIntrinsicKind::DynamicAtexitDestructor:
>>>> +    return demangleDynamicStructorFunction(MangledName, true);
>>>>    default:
>>>> -    if (!Error)
>>>> -      std::tie(S->Category, S->SymbolType) =
>>>> -          demangleSymbolCategoryAndType(MangledName);
>>>>      break;
>>>>    }
>>>> +  Error = true;
>>>> +  return nullptr;
>>>> +}
>>>> +
>>>> +IdentifierNode *
>>>> +Demangler::demangleFunctionIdentifierCode(StringView &MangledName) {
>>>> +  assert(MangledName.startsWith('?'));
>>>> +  MangledName = MangledName.dropFront();
>>>> +
>>>> +  if (MangledName.consumeFront("__"))
>>>> +    return demangleFunctionIdentifierCode(
>>>> +        MangledName, FunctionIdentifierCodeGroup::DoubleUnder);
>>>> +  else if (MangledName.consumeFront("_"))
>>>> +    return demangleFunctionIdentifierCode(MangledName,
>>>> +
>>>> FunctionIdentifierCodeGroup::Under);
>>>> +  return demangleFunctionIdentifierCode(MangledName,
>>>> +
>>>> FunctionIdentifierCodeGroup::Basic);
>>>> +}
>>>> +
>>>> +StructorIdentifierNode *
>>>> +Demangler::demangleStructorIdentifier(StringView &MangledName,
>>>> +                                      bool IsDestructor) {
>>>> +  StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>();
>>>> +  N->IsDestructor = IsDestructor;
>>>> +  return N;
>>>> +}
>>>> +
>>>> +ConversionOperatorIdentifierNode *
>>>> +Demangler::demangleConversionOperatorIdentifier(StringView
>>>> &MangledName) {
>>>> +  ConversionOperatorIdentifierNode *N =
>>>> +      Arena.alloc<ConversionOperatorIdentifierNode>();
>>>> +  return N;
>>>> +}
>>>> +
>>>> +LiteralOperatorIdentifierNode *
>>>> +Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) {
>>>> +  LiteralOperatorIdentifierNode *N =
>>>> +      Arena.alloc<LiteralOperatorIdentifierNode>();
>>>> +  N->Name = demangleSimpleString(MangledName, false);
>>>> +  return N;
>>>> +}
>>>> +
>>>> +IntrinsicFunctionKind
>>>> +translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup
>>>> Group) {
>>>> +  // Not all ? identifiers are intrinsics *functions*.  This function
>>>> only maps
>>>> +  // operator codes for the special functions, all others are handled
>>>> elsewhere,
>>>> +  // hence the IFK::None entries in the table.
>>>> +  using IFK = IntrinsicFunctionKind;
>>>> +  static IFK Basic[36] = {
>>>> +      IFK::None,             // ?0 # Foo::Foo()
>>>> +      IFK::None,             // ?1 # Foo::~Foo()
>>>> +      IFK::New,              // ?2 # operator new
>>>> +      IFK::Delete,           // ?3 # operator delete
>>>> +      IFK::Assign,           // ?4 # operator=
>>>> +      IFK::RightShift,       // ?5 # operator>>
>>>> +      IFK::LeftShift,        // ?6 # operator<<
>>>> +      IFK::LogicalNot,       // ?7 # operator!
>>>> +      IFK::Equals,           // ?8 # operator==
>>>> +      IFK::NotEquals,        // ?9 # operator!=
>>>> +      IFK::ArraySubscript,   // ?A # operator[]
>>>> +      IFK::None,             // ?B # Foo::operator <type>()
>>>> +      IFK::Pointer,          // ?C # operator->
>>>> +      IFK::Dereference,      // ?D # operator*
>>>> +      IFK::Increment,        // ?E # operator++
>>>> +      IFK::Decrement,        // ?F # operator--
>>>> +      IFK::Minus,            // ?G # operator-
>>>> +      IFK::Plus,             // ?H # operator+
>>>> +      IFK::BitwiseA
>>>
>>> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180827/d3c419f0/attachment.html>


More information about the llvm-commits mailing list