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

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 26 23:54:29 PDT 2018


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/20180826/4aace4eb/attachment-0001.html>


More information about the llvm-commits mailing list