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