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