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

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


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/ac3dcd7f/attachment.html>


More information about the llvm-commits mailing list