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

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 27 00:23:53 PDT 2018


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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180827/9cfb2c97/attachment-0001.html>


More information about the llvm-commits mailing list