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