[llvm] r340710 - [MS Demangler] Re-write the Microsoft demangler.
Chandler Carruth via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 27 02:08:44 PDT 2018
S'all good. Now just need to get the *other* (unrelated) failures fixed...
On Mon, Aug 27, 2018 at 12:24 AM Zachary Turner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> 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
>>>
>>> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180827/d3c419f0/attachment.html>
More information about the llvm-commits
mailing list