Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 1 | #ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H |
| 2 | #define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H |
| 3 | |
| 4 | #include "llvm/Demangle/Compiler.h" |
| 5 | #include "llvm/Demangle/StringView.h" |
| 6 | #include <array> |
| 7 | |
| 8 | class OutputStream; |
| 9 | |
| 10 | namespace llvm { |
| 11 | namespace ms_demangle { |
| 12 | |
| 13 | // This memory allocator is extremely fast, but it doesn't call dtors |
| 14 | // for allocated objects. That means you can't use STL containers |
| 15 | // (such as std::vector) with this allocator. But it pays off -- |
| 16 | // the demangler is 3x faster with this allocator compared to one with |
| 17 | // STL containers. |
| 18 | constexpr size_t AllocUnit = 4096; |
| 19 | |
| 20 | class ArenaAllocator { |
| 21 | struct AllocatorNode { |
| 22 | uint8_t *Buf = nullptr; |
| 23 | size_t Used = 0; |
| 24 | size_t Capacity = 0; |
| 25 | AllocatorNode *Next = nullptr; |
| 26 | }; |
| 27 | |
| 28 | void addNode(size_t Capacity) { |
| 29 | AllocatorNode *NewHead = new AllocatorNode; |
| 30 | NewHead->Buf = new uint8_t[Capacity]; |
| 31 | NewHead->Next = Head; |
| 32 | NewHead->Capacity = Capacity; |
| 33 | Head = NewHead; |
| 34 | NewHead->Used = 0; |
| 35 | } |
| 36 | |
| 37 | public: |
| 38 | ArenaAllocator() { addNode(AllocUnit); } |
| 39 | |
| 40 | ~ArenaAllocator() { |
| 41 | while (Head) { |
| 42 | assert(Head->Buf); |
| 43 | delete[] Head->Buf; |
| 44 | AllocatorNode *Next = Head->Next; |
| 45 | delete Head; |
| 46 | Head = Next; |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | char *allocUnalignedBuffer(size_t Length) { |
| 51 | uint8_t *Buf = Head->Buf + Head->Used; |
| 52 | |
| 53 | Head->Used += Length; |
| 54 | if (Head->Used > Head->Capacity) { |
| 55 | // It's possible we need a buffer which is larger than our default unit |
| 56 | // size, so we need to be careful to add a node with capacity that is at |
| 57 | // least as large as what we need. |
| 58 | addNode(std::max(AllocUnit, Length)); |
| 59 | Head->Used = Length; |
| 60 | Buf = Head->Buf; |
| 61 | } |
| 62 | |
| 63 | return reinterpret_cast<char *>(Buf); |
| 64 | } |
| 65 | |
| 66 | template <typename T, typename... Args> |
| 67 | T *allocArray(size_t Count) { |
| 68 | |
| 69 | size_t Size = Count * sizeof(T); |
| 70 | assert(Head && Head->Buf); |
| 71 | |
| 72 | size_t P = (size_t)Head->Buf + Head->Used; |
| 73 | uintptr_t AlignedP = |
| 74 | (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); |
| 75 | uint8_t *PP = (uint8_t *)AlignedP; |
| 76 | size_t Adjustment = AlignedP - P; |
| 77 | |
| 78 | Head->Used += Size + Adjustment; |
| 79 | if (Head->Used < Head->Capacity) |
| 80 | return new (PP) T[Count](); |
| 81 | |
| 82 | addNode(AllocUnit); |
| 83 | Head->Used = Size; |
| 84 | return new (Head->Buf) T[Count](); |
| 85 | } |
| 86 | |
| 87 | template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) { |
| 88 | |
| 89 | size_t Size = sizeof(T); |
| 90 | assert(Head && Head->Buf); |
| 91 | |
| 92 | size_t P = (size_t)Head->Buf + Head->Used; |
| 93 | uintptr_t AlignedP = |
| 94 | (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); |
| 95 | uint8_t *PP = (uint8_t *)AlignedP; |
| 96 | size_t Adjustment = AlignedP - P; |
| 97 | |
| 98 | Head->Used += Size + Adjustment; |
| 99 | if (Head->Used < Head->Capacity) |
| 100 | return new (PP) T(std::forward<Args>(ConstructorArgs)...); |
| 101 | |
| 102 | addNode(AllocUnit); |
| 103 | Head->Used = Size; |
| 104 | return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...); |
| 105 | } |
| 106 | |
| 107 | private: |
| 108 | AllocatorNode *Head = nullptr; |
| 109 | }; |
| 110 | |
| 111 | // Storage classes |
| 112 | enum Qualifiers : uint8_t { |
| 113 | Q_None = 0, |
| 114 | Q_Const = 1 << 0, |
| 115 | Q_Volatile = 1 << 1, |
| 116 | Q_Far = 1 << 2, |
| 117 | Q_Huge = 1 << 3, |
| 118 | Q_Unaligned = 1 << 4, |
| 119 | Q_Restrict = 1 << 5, |
| 120 | Q_Pointer64 = 1 << 6 |
| 121 | }; |
| 122 | |
| 123 | enum class StorageClass : uint8_t { |
| 124 | None, |
| 125 | PrivateStatic, |
| 126 | ProtectedStatic, |
| 127 | PublicStatic, |
| 128 | Global, |
| 129 | FunctionLocalStatic, |
| 130 | }; |
| 131 | |
| 132 | enum class PointerAffinity { None, Pointer, Reference, RValueReference }; |
| 133 | enum class FunctionRefQualifier { None, Reference, RValueReference }; |
| 134 | |
| 135 | // Calling conventions |
| 136 | enum class CallingConv : uint8_t { |
| 137 | None, |
| 138 | Cdecl, |
| 139 | Pascal, |
| 140 | Thiscall, |
| 141 | Stdcall, |
| 142 | Fastcall, |
| 143 | Clrcall, |
| 144 | Eabi, |
| 145 | Vectorcall, |
| 146 | Regcall, |
| 147 | }; |
| 148 | |
| 149 | enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef }; |
| 150 | |
Zachary Turner | b2fef1a | 2018-08-29 04:12:44 +0000 | [diff] [blame] | 151 | enum OutputFlags { |
| 152 | OF_Default = 0, |
| 153 | OF_NoCallingConvention = 1, |
| 154 | }; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 155 | |
| 156 | // Types |
| 157 | enum class PrimitiveKind { |
| 158 | Void, |
| 159 | Bool, |
| 160 | Char, |
| 161 | Schar, |
| 162 | Uchar, |
| 163 | Char16, |
| 164 | Char32, |
| 165 | Short, |
| 166 | Ushort, |
| 167 | Int, |
| 168 | Uint, |
| 169 | Long, |
| 170 | Ulong, |
| 171 | Int64, |
| 172 | Uint64, |
| 173 | Wchar, |
| 174 | Float, |
| 175 | Double, |
| 176 | Ldouble, |
| 177 | Nullptr, |
| 178 | }; |
| 179 | |
| 180 | enum class CharKind { |
| 181 | Char, |
| 182 | Char16, |
| 183 | Char32, |
| 184 | Wchar, |
| 185 | }; |
| 186 | |
| 187 | enum class IntrinsicFunctionKind : uint8_t { |
| 188 | None, |
| 189 | New, // ?2 # operator new |
| 190 | Delete, // ?3 # operator delete |
| 191 | Assign, // ?4 # operator= |
| 192 | RightShift, // ?5 # operator>> |
| 193 | LeftShift, // ?6 # operator<< |
| 194 | LogicalNot, // ?7 # operator! |
| 195 | Equals, // ?8 # operator== |
| 196 | NotEquals, // ?9 # operator!= |
| 197 | ArraySubscript, // ?A # operator[] |
| 198 | Pointer, // ?C # operator-> |
| 199 | Dereference, // ?D # operator* |
| 200 | Increment, // ?E # operator++ |
| 201 | Decrement, // ?F # operator-- |
| 202 | Minus, // ?G # operator- |
| 203 | Plus, // ?H # operator+ |
| 204 | BitwiseAnd, // ?I # operator& |
| 205 | MemberPointer, // ?J # operator->* |
| 206 | Divide, // ?K # operator/ |
| 207 | Modulus, // ?L # operator% |
| 208 | LessThan, // ?M operator< |
| 209 | LessThanEqual, // ?N operator<= |
| 210 | GreaterThan, // ?O operator> |
| 211 | GreaterThanEqual, // ?P operator>= |
| 212 | Comma, // ?Q operator, |
| 213 | Parens, // ?R operator() |
| 214 | BitwiseNot, // ?S operator~ |
| 215 | BitwiseXor, // ?T operator^ |
| 216 | BitwiseOr, // ?U operator| |
| 217 | LogicalAnd, // ?V operator&& |
| 218 | LogicalOr, // ?W operator|| |
| 219 | TimesEqual, // ?X operator*= |
| 220 | PlusEqual, // ?Y operator+= |
| 221 | MinusEqual, // ?Z operator-= |
| 222 | DivEqual, // ?_0 operator/= |
| 223 | ModEqual, // ?_1 operator%= |
| 224 | RshEqual, // ?_2 operator>>= |
| 225 | LshEqual, // ?_3 operator<<= |
| 226 | BitwiseAndEqual, // ?_4 operator&= |
| 227 | BitwiseOrEqual, // ?_5 operator|= |
| 228 | BitwiseXorEqual, // ?_6 operator^= |
| 229 | VbaseDtor, // ?_D # vbase destructor |
| 230 | VecDelDtor, // ?_E # vector deleting destructor |
| 231 | DefaultCtorClosure, // ?_F # default constructor closure |
| 232 | ScalarDelDtor, // ?_G # scalar deleting destructor |
| 233 | VecCtorIter, // ?_H # vector constructor iterator |
| 234 | VecDtorIter, // ?_I # vector destructor iterator |
| 235 | VecVbaseCtorIter, // ?_J # vector vbase constructor iterator |
| 236 | VdispMap, // ?_K # virtual displacement map |
| 237 | EHVecCtorIter, // ?_L # eh vector constructor iterator |
| 238 | EHVecDtorIter, // ?_M # eh vector destructor iterator |
| 239 | EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator |
| 240 | CopyCtorClosure, // ?_O # copy constructor closure |
| 241 | LocalVftableCtorClosure, // ?_T # local vftable constructor closure |
| 242 | ArrayNew, // ?_U operator new[] |
| 243 | ArrayDelete, // ?_V operator delete[] |
| 244 | ManVectorCtorIter, // ?__A managed vector ctor iterator |
| 245 | ManVectorDtorIter, // ?__B managed vector dtor iterator |
| 246 | EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator |
| 247 | EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator |
| 248 | VectorCopyCtorIter, // ?__G vector copy constructor iterator |
| 249 | VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator |
| 250 | ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor |
| 251 | CoAwait, // ?__L co_await |
| 252 | Spaceship, // operator<=> |
| 253 | MaxIntrinsic |
| 254 | }; |
| 255 | |
| 256 | enum class SpecialIntrinsicKind { |
| 257 | None, |
| 258 | Vftable, |
| 259 | Vbtable, |
| 260 | Typeof, |
| 261 | VcallThunk, |
| 262 | LocalStaticGuard, |
| 263 | StringLiteralSymbol, |
| 264 | UdtReturning, |
| 265 | Unknown, |
| 266 | DynamicInitializer, |
| 267 | DynamicAtexitDestructor, |
| 268 | RttiTypeDescriptor, |
| 269 | RttiBaseClassDescriptor, |
| 270 | RttiBaseClassArray, |
| 271 | RttiClassHierarchyDescriptor, |
| 272 | RttiCompleteObjLocator, |
| 273 | LocalVftable, |
| 274 | LocalStaticThreadGuard, |
| 275 | }; |
| 276 | |
| 277 | // Function classes |
| 278 | enum FuncClass : uint16_t { |
| 279 | FC_None = 0, |
| 280 | FC_Public = 1 << 0, |
| 281 | FC_Protected = 1 << 1, |
| 282 | FC_Private = 1 << 2, |
| 283 | FC_Global = 1 << 3, |
| 284 | FC_Static = 1 << 4, |
| 285 | FC_Virtual = 1 << 5, |
| 286 | FC_Far = 1 << 6, |
| 287 | FC_ExternC = 1 << 7, |
| 288 | FC_NoParameterList = 1 << 8, |
| 289 | FC_VirtualThisAdjust = 1 << 9, |
| 290 | FC_VirtualThisAdjustEx = 1 << 10, |
| 291 | FC_StaticThisAdjust = 1 << 11, |
| 292 | }; |
| 293 | |
| 294 | enum class TagKind { Class, Struct, Union, Enum }; |
| 295 | |
| 296 | enum class NodeKind { |
| 297 | Unknown, |
| 298 | Md5Symbol, |
| 299 | PrimitiveType, |
| 300 | FunctionSignature, |
| 301 | Identifier, |
| 302 | NamedIdentifier, |
| 303 | VcallThunkIdentifier, |
| 304 | LocalStaticGuardIdentifier, |
| 305 | IntrinsicFunctionIdentifier, |
| 306 | ConversionOperatorIdentifier, |
| 307 | DynamicStructorIdentifier, |
| 308 | StructorIdentifier, |
| 309 | LiteralOperatorIdentifier, |
| 310 | ThunkSignature, |
| 311 | PointerType, |
| 312 | TagType, |
| 313 | ArrayType, |
| 314 | Custom, |
| 315 | IntrinsicType, |
| 316 | NodeArray, |
| 317 | QualifiedName, |
| 318 | TemplateParameterReference, |
| 319 | EncodedStringLiteral, |
| 320 | IntegerLiteral, |
| 321 | RttiBaseClassDescriptor, |
| 322 | LocalStaticGuardVariable, |
| 323 | FunctionSymbol, |
| 324 | VariableSymbol, |
Zachary Turner | 32a8a20 | 2018-08-29 23:56:09 +0000 | [diff] [blame] | 325 | SpecialTableSymbol |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 326 | }; |
| 327 | |
| 328 | struct Node { |
| 329 | explicit Node(NodeKind K) : Kind(K) {} |
Zachary Turner | 03b6f5a | 2018-08-27 04:04:41 +0000 | [diff] [blame] | 330 | virtual ~Node() = default; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 331 | |
| 332 | NodeKind kind() const { return Kind; } |
| 333 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 334 | virtual void output(OutputStream &OS, OutputFlags Flags) const = 0; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 335 | |
| 336 | private: |
| 337 | NodeKind Kind; |
| 338 | }; |
| 339 | |
| 340 | struct TypeNode; |
| 341 | struct PrimitiveTypeNode; |
| 342 | struct FunctionSignatureNode; |
| 343 | struct IdentifierNode; |
| 344 | struct NamedIdentifierNode; |
| 345 | struct VcallThunkIdentifierNode; |
| 346 | struct IntrinsicFunctionIdentifierNode; |
| 347 | struct LiteralOperatorIdentifierNode; |
| 348 | struct ConversionOperatorIdentifierNode; |
| 349 | struct StructorIdentifierNode; |
| 350 | struct ThunkSignatureNode; |
| 351 | struct PointerTypeNode; |
| 352 | struct ArrayTypeNode; |
| 353 | struct CustomNode; |
| 354 | struct TagTypeNode; |
| 355 | struct IntrinsicTypeNode; |
| 356 | struct NodeArrayNode; |
| 357 | struct QualifiedNameNode; |
| 358 | struct TemplateParameterReferenceNode; |
| 359 | struct EncodedStringLiteralNode; |
| 360 | struct IntegerLiteralNode; |
| 361 | struct RttiBaseClassDescriptorNode; |
| 362 | struct LocalStaticGuardVariableNode; |
| 363 | struct SymbolNode; |
| 364 | struct FunctionSymbolNode; |
| 365 | struct VariableSymbolNode; |
| 366 | struct SpecialTableSymbolNode; |
| 367 | |
| 368 | struct TypeNode : public Node { |
| 369 | explicit TypeNode(NodeKind K) : Node(K) {} |
| 370 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 371 | virtual void outputPre(OutputStream &OS, OutputFlags Flags) const = 0; |
| 372 | virtual void outputPost(OutputStream &OS, OutputFlags Flags) const = 0; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 373 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 374 | void output(OutputStream &OS, OutputFlags Flags) const override { |
| 375 | outputPre(OS, Flags); |
| 376 | outputPost(OS, Flags); |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | void outputQuals(bool SpaceBefore, bool SpaceAfter) const; |
| 380 | |
| 381 | Qualifiers Quals = Q_None; |
| 382 | }; |
| 383 | |
| 384 | struct PrimitiveTypeNode : public TypeNode { |
| 385 | explicit PrimitiveTypeNode(PrimitiveKind K) |
| 386 | : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {} |
| 387 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 388 | void outputPre(OutputStream &OS, OutputFlags Flags) const; |
| 389 | void outputPost(OutputStream &OS, OutputFlags Flags) const {} |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 390 | |
| 391 | PrimitiveKind PrimKind; |
| 392 | }; |
| 393 | |
| 394 | struct FunctionSignatureNode : public TypeNode { |
| 395 | explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {} |
| 396 | FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {} |
| 397 | |
Zachary Turner | b2fef1a | 2018-08-29 04:12:44 +0000 | [diff] [blame] | 398 | void outputPre(OutputStream &OS, OutputFlags Flags) const override; |
| 399 | void outputPost(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 400 | |
| 401 | // Valid if this FunctionTypeNode is the Pointee of a PointerType or |
| 402 | // MemberPointerType. |
| 403 | PointerAffinity Affinity = PointerAffinity::None; |
| 404 | |
| 405 | // The function's calling convention. |
| 406 | CallingConv CallConvention = CallingConv::None; |
| 407 | |
| 408 | // Function flags (gloabl, public, etc) |
| 409 | FuncClass FunctionClass = FC_Global; |
| 410 | |
| 411 | FunctionRefQualifier RefQualifier = FunctionRefQualifier::None; |
| 412 | |
| 413 | // The return type of the function. |
| 414 | TypeNode *ReturnType = nullptr; |
| 415 | |
| 416 | // True if this is a C-style ... varargs function. |
| 417 | bool IsVariadic = false; |
| 418 | |
| 419 | // Function parameters |
| 420 | NodeArrayNode *Params = nullptr; |
| 421 | }; |
| 422 | |
| 423 | struct IdentifierNode : public Node { |
| 424 | explicit IdentifierNode(NodeKind K) : Node(K) {} |
| 425 | |
| 426 | NodeArrayNode *TemplateParams = nullptr; |
| 427 | |
| 428 | protected: |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 429 | void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 430 | }; |
| 431 | |
| 432 | struct VcallThunkIdentifierNode : public IdentifierNode { |
| 433 | VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {} |
| 434 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 435 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 436 | |
| 437 | uint64_t OffsetInVTable = 0; |
| 438 | }; |
| 439 | |
| 440 | struct DynamicStructorIdentifierNode : public IdentifierNode { |
| 441 | DynamicStructorIdentifierNode() |
| 442 | : IdentifierNode(NodeKind::DynamicStructorIdentifier) {} |
| 443 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 444 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 445 | |
Zachary Turner | 32a8a20 | 2018-08-29 23:56:09 +0000 | [diff] [blame] | 446 | VariableSymbolNode *Variable = nullptr; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 447 | QualifiedNameNode *Name = nullptr; |
| 448 | bool IsDestructor = false; |
| 449 | }; |
| 450 | |
| 451 | struct NamedIdentifierNode : public IdentifierNode { |
| 452 | NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {} |
| 453 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 454 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 455 | |
| 456 | StringView Name; |
| 457 | }; |
| 458 | |
| 459 | struct IntrinsicFunctionIdentifierNode : public IdentifierNode { |
| 460 | explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator) |
| 461 | : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier), |
| 462 | Operator(Operator) {} |
| 463 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 464 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 465 | |
| 466 | IntrinsicFunctionKind Operator; |
| 467 | }; |
| 468 | |
| 469 | struct LiteralOperatorIdentifierNode : public IdentifierNode { |
| 470 | LiteralOperatorIdentifierNode() |
| 471 | : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {} |
| 472 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 473 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 474 | |
| 475 | StringView Name; |
| 476 | }; |
| 477 | |
| 478 | struct LocalStaticGuardIdentifierNode : public IdentifierNode { |
| 479 | LocalStaticGuardIdentifierNode() |
| 480 | : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {} |
| 481 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 482 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 483 | |
| 484 | uint32_t ScopeIndex = 0; |
| 485 | }; |
| 486 | |
| 487 | struct ConversionOperatorIdentifierNode : public IdentifierNode { |
| 488 | ConversionOperatorIdentifierNode() |
| 489 | : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {} |
| 490 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 491 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 492 | |
| 493 | // The type that this operator converts too. |
| 494 | TypeNode *TargetType = nullptr; |
| 495 | }; |
| 496 | |
| 497 | struct StructorIdentifierNode : public IdentifierNode { |
| 498 | StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {} |
| 499 | explicit StructorIdentifierNode(bool IsDestructor) |
| 500 | : IdentifierNode(NodeKind::StructorIdentifier), |
| 501 | IsDestructor(IsDestructor) {} |
| 502 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 503 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 504 | |
| 505 | // The name of the class that this is a structor of. |
| 506 | IdentifierNode *Class = nullptr; |
| 507 | bool IsDestructor = false; |
| 508 | }; |
| 509 | |
| 510 | struct ThunkSignatureNode : public FunctionSignatureNode { |
| 511 | ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {} |
| 512 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 513 | void outputPre(OutputStream &OS, OutputFlags Flags) const override; |
| 514 | void outputPost(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 515 | |
| 516 | struct ThisAdjustor { |
| 517 | uint32_t StaticOffset = 0; |
| 518 | int32_t VBPtrOffset = 0; |
| 519 | int32_t VBOffsetOffset = 0; |
| 520 | int32_t VtordispOffset = 0; |
| 521 | }; |
| 522 | |
| 523 | ThisAdjustor ThisAdjust; |
| 524 | }; |
| 525 | |
| 526 | struct PointerTypeNode : public TypeNode { |
| 527 | PointerTypeNode() : TypeNode(NodeKind::PointerType) {} |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 528 | void outputPre(OutputStream &OS, OutputFlags Flags) const override; |
| 529 | void outputPost(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 530 | |
| 531 | // Is this a pointer, reference, or rvalue-reference? |
| 532 | PointerAffinity Affinity = PointerAffinity::None; |
| 533 | |
| 534 | // If this is a member pointer, this is the class that the member is in. |
| 535 | QualifiedNameNode *ClassParent = nullptr; |
| 536 | |
| 537 | // Represents a type X in "a pointer to X", "a reference to X", or |
| 538 | // "rvalue-reference to X" |
| 539 | TypeNode *Pointee = nullptr; |
| 540 | }; |
| 541 | |
| 542 | struct TagTypeNode : public TypeNode { |
| 543 | explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {} |
| 544 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 545 | void outputPre(OutputStream &OS, OutputFlags Flags) const; |
| 546 | void outputPost(OutputStream &OS, OutputFlags Flags) const; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 547 | |
| 548 | QualifiedNameNode *QualifiedName = nullptr; |
| 549 | TagKind Tag; |
| 550 | }; |
| 551 | |
| 552 | struct ArrayTypeNode : public TypeNode { |
| 553 | ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {} |
| 554 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 555 | void outputPre(OutputStream &OS, OutputFlags Flags) const; |
| 556 | void outputPost(OutputStream &OS, OutputFlags Flags) const; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 557 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 558 | void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const; |
| 559 | void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 560 | |
| 561 | // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]` |
| 562 | NodeArrayNode *Dimensions = nullptr; |
| 563 | |
| 564 | // The type of array element. |
| 565 | TypeNode *ElementType = nullptr; |
| 566 | }; |
| 567 | |
| 568 | struct IntrinsicNode : public TypeNode { |
| 569 | IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {} |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 570 | void output(OutputStream &OS, OutputFlags Flags) const override {} |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 571 | }; |
| 572 | |
Zachary Turner | b2fef1a | 2018-08-29 04:12:44 +0000 | [diff] [blame] | 573 | struct CustomTypeNode : public TypeNode { |
| 574 | CustomTypeNode() : TypeNode(NodeKind::Custom) {} |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 575 | |
Zachary Turner | b2fef1a | 2018-08-29 04:12:44 +0000 | [diff] [blame] | 576 | void outputPre(OutputStream &OS, OutputFlags Flags) const override; |
| 577 | void outputPost(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 578 | |
Zachary Turner | b2fef1a | 2018-08-29 04:12:44 +0000 | [diff] [blame] | 579 | IdentifierNode *Identifier; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 580 | }; |
| 581 | |
| 582 | struct NodeArrayNode : public Node { |
| 583 | NodeArrayNode() : Node(NodeKind::NodeArray) {} |
| 584 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 585 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 586 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 587 | void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 588 | |
| 589 | Node **Nodes = 0; |
| 590 | size_t Count = 0; |
| 591 | }; |
| 592 | |
| 593 | struct QualifiedNameNode : public Node { |
| 594 | QualifiedNameNode() : Node(NodeKind::QualifiedName) {} |
| 595 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 596 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 597 | |
| 598 | NodeArrayNode *Components = nullptr; |
| 599 | |
| 600 | IdentifierNode *getUnqualifiedIdentifier() { |
| 601 | Node *LastComponent = Components->Nodes[Components->Count - 1]; |
| 602 | return static_cast<IdentifierNode *>(LastComponent); |
| 603 | } |
| 604 | }; |
| 605 | |
| 606 | struct TemplateParameterReferenceNode : public Node { |
| 607 | TemplateParameterReferenceNode() |
| 608 | : Node(NodeKind::TemplateParameterReference) {} |
| 609 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 610 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 611 | |
| 612 | SymbolNode *Symbol = nullptr; |
| 613 | |
| 614 | int ThunkOffsetCount = 0; |
| 615 | std::array<int64_t, 3> ThunkOffsets; |
| 616 | PointerAffinity Affinity = PointerAffinity::None; |
| 617 | bool IsMemberPointer = false; |
| 618 | }; |
| 619 | |
| 620 | struct IntegerLiteralNode : public Node { |
| 621 | IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) {} |
| 622 | IntegerLiteralNode(uint64_t Value, bool IsNegative) |
| 623 | : Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {} |
| 624 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 625 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 626 | |
| 627 | uint64_t Value = 0; |
| 628 | bool IsNegative = false; |
| 629 | }; |
| 630 | |
| 631 | struct RttiBaseClassDescriptorNode : public IdentifierNode { |
| 632 | RttiBaseClassDescriptorNode() |
| 633 | : IdentifierNode(NodeKind::RttiBaseClassDescriptor) {} |
| 634 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 635 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 636 | |
| 637 | uint32_t NVOffset = 0; |
| 638 | int32_t VBPtrOffset = 0; |
| 639 | uint32_t VBTableOffset = 0; |
| 640 | uint32_t Flags = 0; |
| 641 | }; |
| 642 | |
| 643 | struct SymbolNode : public Node { |
| 644 | explicit SymbolNode(NodeKind K) : Node(K) {} |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 645 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 646 | QualifiedNameNode *Name = nullptr; |
| 647 | }; |
| 648 | |
| 649 | struct SpecialTableSymbolNode : public SymbolNode { |
| 650 | explicit SpecialTableSymbolNode() |
| 651 | : SymbolNode(NodeKind::SpecialTableSymbol) {} |
| 652 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 653 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 654 | QualifiedNameNode *TargetName = nullptr; |
| 655 | Qualifiers Quals; |
| 656 | }; |
| 657 | |
| 658 | struct LocalStaticGuardVariableNode : public SymbolNode { |
| 659 | LocalStaticGuardVariableNode() |
| 660 | : SymbolNode(NodeKind::LocalStaticGuardVariable) {} |
| 661 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 662 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 663 | |
| 664 | bool IsVisible = false; |
| 665 | }; |
| 666 | |
| 667 | struct EncodedStringLiteralNode : public SymbolNode { |
| 668 | EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {} |
| 669 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 670 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 671 | |
| 672 | StringView DecodedString; |
| 673 | bool IsTruncated = false; |
| 674 | CharKind Char = CharKind::Char; |
| 675 | }; |
| 676 | |
| 677 | struct VariableSymbolNode : public SymbolNode { |
| 678 | VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {} |
| 679 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 680 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 681 | |
| 682 | StorageClass SC = StorageClass::None; |
| 683 | TypeNode *Type = nullptr; |
| 684 | }; |
| 685 | |
| 686 | struct FunctionSymbolNode : public SymbolNode { |
| 687 | FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {} |
| 688 | |
Zachary Turner | 38d2edd | 2018-08-29 03:59:17 +0000 | [diff] [blame] | 689 | void output(OutputStream &OS, OutputFlags Flags) const override; |
Zachary Turner | 0331286 | 2018-08-27 03:48:03 +0000 | [diff] [blame] | 690 | |
| 691 | FunctionSignatureNode *Signature = nullptr; |
| 692 | }; |
| 693 | |
| 694 | } // namespace ms_demangle |
| 695 | } // namespace llvm |
| 696 | |
| 697 | #endif |