1 //===--- Demangler.h - String to Node-Tree Demangling -----------*- C++ -*-===// 2 // 3 // This source file is part of the Swift.org open source project 4 // 5 // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors 6 // Licensed under Apache License v2.0 with Runtime Library Exception 7 // 8 // See https://swift.org/LICENSE.txt for license information 9 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors 10 // 11 //===----------------------------------------------------------------------===// 12 // 13 // This file is the compiler-private API of the demangler. 14 // It should only be used within the swift compiler or runtime library, but not 15 // by external tools which use the demangler library (like lldb). 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef SWIFT_DEMANGLING_DEMANGLER_H 20 #define SWIFT_DEMANGLING_DEMANGLER_H 21 22 #include "swift/Demangling/Demangle.h" 23 24 //#define NODE_FACTORY_DEBUGGING 25 26 using namespace swift::Demangle; 27 using llvm::StringRef; 28 29 namespace swift { 30 namespace Demangle { 31 32 class CharVector; 33 34 /// The allocator for demangling nodes and other demangling-internal stuff. 35 /// 36 /// It implements a simple bump-pointer allocator. 37 class NodeFactory { 38 39 /// Position in the current slab. 40 char *CurPtr = nullptr; 41 42 /// The end of the current slab. 43 char *End = nullptr; 44 45 struct Slab { 46 // The previously allocated slab. 47 Slab *Previous; 48 // Tail allocated memory starts here. 49 }; 50 51 /// The head of the single-linked slab list. 52 Slab *CurrentSlab = nullptr; 53 54 /// The size of the previously allocated slab. 55 /// 56 /// The slab size can only grow, even clear() does not reset the slab size. 57 /// This initial size is good enough to fit most de-manglings. 58 size_t SlabSize = 100 * sizeof(Node); 59 align(char * Ptr,size_t Alignment)60 static char *align(char *Ptr, size_t Alignment) { 61 assert(Alignment > 0); 62 return (char*)(((uintptr_t)Ptr + Alignment - 1) 63 & ~((uintptr_t)Alignment - 1)); 64 } 65 66 static void freeSlabs(Slab *slab); 67 68 /// If not null, the NodeFactory from which this factory borrowed free memory. 69 NodeFactory *BorrowedFrom = nullptr; 70 71 /// True if some other NodeFactory borrowed free memory from this factory. 72 bool isBorrowed = false; 73 74 #ifdef NODE_FACTORY_DEBUGGING 75 size_t allocatedMemory = 0; 76 static int nestingLevel; indent()77 std::string indent() { return std::string(nestingLevel * 2, ' '); } 78 #endif 79 80 public: 81 NodeFactory()82 NodeFactory() { 83 #ifdef NODE_FACTORY_DEBUGGING 84 fprintf(stderr, "%s## New NodeFactory\n", indent().c_str()); 85 nestingLevel++; 86 #endif 87 } 88 89 /// Provide pre-allocated memory, e.g. memory on the stack. 90 /// 91 /// Only if this memory overflows, the factory begins to malloc. providePreallocatedMemory(char * Memory,size_t Size)92 void providePreallocatedMemory(char *Memory, size_t Size) { 93 #ifdef NODE_FACTORY_DEBUGGING 94 fprintf(stderr, "%s++ provide preallocated memory, size = %zu\n", indent().c_str(), Size); 95 #endif 96 assert(!CurPtr && !End && !CurrentSlab); 97 CurPtr = Memory; 98 End = CurPtr + Size; 99 } 100 101 /// Borrow free memory from another factory \p BorrowFrom. 102 /// 103 /// While this factory is alive, no allocations can be done in the 104 /// \p BorrowFrom factory. providePreallocatedMemory(NodeFactory & BorrowFrom)105 void providePreallocatedMemory(NodeFactory &BorrowFrom) { 106 assert(!CurPtr && !End && !CurrentSlab); 107 assert(!BorrowFrom.isBorrowed && !BorrowedFrom); 108 BorrowFrom.isBorrowed = true; 109 BorrowedFrom = &BorrowFrom; 110 CurPtr = BorrowFrom.CurPtr; 111 End = BorrowFrom.End; 112 #ifdef NODE_FACTORY_DEBUGGING 113 fprintf(stderr, "%s++ borrow memory, size = %zu\n", indent().c_str(), (End - CurPtr)); 114 #endif 115 } 116 ~NodeFactory()117 virtual ~NodeFactory() { 118 freeSlabs(CurrentSlab); 119 #ifdef NODE_FACTORY_DEBUGGING 120 nestingLevel--; 121 fprintf(stderr, "%s## Delete NodeFactory: allocated memory = %zu\n", indent().c_str(), allocatedMemory) 122 #endif 123 if (BorrowedFrom) { 124 BorrowedFrom->isBorrowed = false; 125 } 126 } 127 128 virtual void clear(); 129 130 /// Allocates an object of type T or an array of objects of type T. 131 template<typename T> T *Allocate(size_t NumObjects = 1) { 132 assert(!isBorrowed); 133 size_t ObjectSize = NumObjects * sizeof(T); 134 CurPtr = align(CurPtr, alignof(T)); 135 #ifdef NODE_FACTORY_DEBUGGING 136 fprintf(stderr, "%salloc %zu, CurPtr = %p\n", indent().c_str(), ObjectSize, (void *)CurPtr) 137 allocatedMemory += ObjectSize; 138 #endif 139 140 // Do we have enough space in the current slab? 141 if (CurPtr + ObjectSize > End) { 142 // No. We have to malloc a new slab. 143 // We double the slab size for each allocated slab. 144 SlabSize = std::max(SlabSize * 2, ObjectSize + alignof(T)); 145 size_t AllocSize = sizeof(Slab) + SlabSize; 146 Slab *newSlab = (Slab *)malloc(AllocSize); 147 148 // Insert the new slab in the single-linked list of slabs. 149 newSlab->Previous = CurrentSlab; 150 CurrentSlab = newSlab; 151 152 // Initialize the pointers to the new slab. 153 CurPtr = align((char *)(newSlab + 1), alignof(T)); 154 End = (char *)newSlab + AllocSize; 155 assert(CurPtr + ObjectSize <= End); 156 #ifdef NODE_FACTORY_DEBUGGING 157 fprintf(stderr, "%s** new slab %p, allocsize = %zu, CurPtr = %p, End = %p\n", 158 indent().c_str(), newSlab, AllocSize, (void *)CurPtr, (void *)End); 159 #endif 160 } 161 T *AllocatedObj = (T *)CurPtr; 162 CurPtr += ObjectSize; 163 return AllocatedObj; 164 } 165 166 /// Tries to enlarge the \p Capacity of an array of \p Objects. 167 /// 168 /// If \p Objects is allocated at the end of the current slab and the slab 169 /// has enough free space, the \p Capacity is simply enlarged and no new 170 /// allocation needs to be done. 171 /// Otherwise a new array of objects is allocated and \p Objects is set to the 172 /// new memory address. 173 /// The \p Capacity is enlarged at least by \p MinGrowth, but can also be 174 /// enlarged by a bigger value. Reallocate(T * & Objects,uint32_t & Capacity,size_t MinGrowth)175 template<typename T> void Reallocate(T *&Objects, uint32_t &Capacity, 176 size_t MinGrowth) { 177 assert(!isBorrowed); 178 size_t OldAllocSize = Capacity * sizeof(T); 179 size_t AdditionalAlloc = MinGrowth * sizeof(T); 180 181 #ifdef NODE_FACTORY_DEBUGGING 182 fprintf(stderr, "%srealloc: capacity = %d (size = %zu), growth = %zu (size = %zu)\n", 183 indent().c_str(), Capacity, OldAllocSize, MinGrowth, AdditionalAlloc); 184 #endif 185 if ((char *)Objects + OldAllocSize == CurPtr 186 && CurPtr + AdditionalAlloc <= End) { 187 // The existing array is at the end of the current slab and there is 188 // enough space. So we are fine. 189 CurPtr += AdditionalAlloc; 190 Capacity += MinGrowth; 191 #ifdef NODE_FACTORY_DEBUGGING 192 fprintf(stderr, "%s** can grow: %p\n", indent().c_str(), (void *)CurPtr); 193 allocatedMemory += AdditionalAlloc; 194 #endif 195 return; 196 } 197 // We need a new allocation. 198 size_t Growth = (MinGrowth >= 4 ? MinGrowth : 4); 199 if (Growth < Capacity * 2) 200 Growth = Capacity * 2; 201 T *NewObjects = Allocate<T>(Capacity + Growth); 202 memcpy(NewObjects, Objects, OldAllocSize); 203 Objects = NewObjects; 204 Capacity += Growth; 205 } 206 207 /// Creates a node of kind \p K. 208 NodePointer createNode(Node::Kind K); 209 210 /// Creates a node of kind \p K with an \p Index payload. 211 NodePointer createNode(Node::Kind K, Node::IndexType Index); 212 213 /// Creates a node of kind \p K with a \p Text payload. 214 /// 215 /// The \p Text string must be already allocated with the Factory and therefore 216 /// it is _not_ copied. 217 NodePointer createNodeWithAllocatedText(Node::Kind K, llvm::StringRef Text); 218 219 /// Creates a node of kind \p K with a \p Text payload. 220 /// 221 /// The \p Text string is copied. createNode(Node::Kind K,llvm::StringRef Text)222 NodePointer createNode(Node::Kind K, llvm::StringRef Text) { 223 return createNodeWithAllocatedText(K, Text.copy(*this)); 224 } 225 226 /// Creates a node of kind \p K with a \p Text payload. 227 /// 228 /// The \p Text string is already allocated with the Factory and therefore 229 /// it is _not_ copied. 230 NodePointer createNode(Node::Kind K, const CharVector &Text); 231 232 /// Creates a node of kind \p K with a \p Text payload, which must be a C 233 /// string literal. 234 /// 235 /// The \p Text string is _not_ copied. 236 NodePointer createNode(Node::Kind K, const char *Text); 237 }; 238 239 /// A vector with a storage managed by a NodeFactory. 240 /// 241 /// This Vector class only provides the minimal functionality needed by the 242 /// Demangler. 243 template<typename T> class Vector { 244 245 protected: 246 T *Elems = nullptr; 247 uint32_t NumElems = 0; 248 uint32_t Capacity = 0; 249 250 public: 251 using iterator = T *; 252 Vector()253 Vector() { } 254 255 /// Construct a vector with an initial capacity. Vector(NodeFactory & Factory,size_t InitialCapacity)256 explicit Vector(NodeFactory &Factory, size_t InitialCapacity) { 257 init(Factory, InitialCapacity); 258 } 259 260 /// Clears the content and re-allocates the buffer with an initial capacity. init(NodeFactory & Factory,size_t InitialCapacity)261 void init(NodeFactory &Factory, size_t InitialCapacity) { 262 Elems = Factory.Allocate<T>(InitialCapacity); 263 NumElems = 0; 264 Capacity = InitialCapacity; 265 } 266 free()267 void free() { 268 Capacity = 0; 269 Elems = 0; 270 } 271 clear()272 void clear() { 273 NumElems = 0; 274 } 275 begin()276 iterator begin() { return Elems; } end()277 iterator end() { return Elems + NumElems; } 278 279 T &operator[](size_t Idx) { 280 assert(Idx < NumElems); 281 return Elems[Idx]; 282 } 283 284 const T &operator[](size_t Idx) const { 285 assert(Idx < NumElems); 286 return Elems[Idx]; 287 } 288 size()289 size_t size() const { return NumElems; } 290 empty()291 bool empty() const { return NumElems == 0; } 292 back()293 T &back() { return (*this)[NumElems - 1]; } 294 resetSize(size_t toPos)295 void resetSize(size_t toPos) { 296 assert(toPos <= NumElems); 297 NumElems = toPos; 298 } 299 push_back(const T & NewElem,NodeFactory & Factory)300 void push_back(const T &NewElem, NodeFactory &Factory) { 301 if (NumElems >= Capacity) 302 Factory.Reallocate(Elems, Capacity, /*Growth*/ 1); 303 assert(NumElems < Capacity); 304 Elems[NumElems++] = NewElem; 305 } 306 pop_back_val()307 T pop_back_val() { 308 if (empty()) 309 return T(); 310 T Val = (*this)[NumElems - 1]; 311 NumElems--; 312 return Val; 313 } 314 }; 315 316 /// A vector of chars (a string) with a storage managed by a NodeFactory. 317 /// 318 /// This CharVector class only provides the minimal functionality needed by the 319 /// Demangler. 320 class CharVector : public Vector<char> { 321 public: 322 // Append another string. 323 void append(StringRef Rhs, NodeFactory &Factory); 324 325 // Append an integer as readable number. 326 void append(int Number, NodeFactory &Factory); 327 328 // Append an unsigned 64 bit integer as readable number. 329 void append(unsigned long long Number, NodeFactory &Factory); 330 str()331 StringRef str() const { 332 return StringRef(Elems, NumElems); 333 } 334 }; 335 336 /// Kinds of symbolic reference supported. 337 enum class SymbolicReferenceKind : uint8_t { 338 /// A symbolic reference to a context descriptor, representing the 339 /// (unapplied generic) context. 340 Context, 341 /// A symbolic reference to an accessor function, which can be executed in 342 /// the process to get a pointer to the referenced entity. 343 AccessorFunctionReference, 344 }; 345 346 using SymbolicReferenceResolver_t = NodePointer (SymbolicReferenceKind, 347 Directness, 348 int32_t, const void *); 349 350 /// The demangler. 351 /// 352 /// It de-mangles a string and it also owns the returned node-tree. This means 353 /// The nodes of the tree only live as long as the Demangler itself. 354 class Demangler : public NodeFactory { 355 protected: 356 StringRef Text; 357 size_t Pos = 0; 358 359 /// Mangling style where function type would have 360 /// labels attached to it, instead of having them 361 /// as part of the name. 362 bool IsOldFunctionTypeMangling = false; 363 364 Vector<NodePointer> NodeStack; 365 Vector<NodePointer> Substitutions; 366 367 static const int MaxNumWords = 26; 368 StringRef Words[MaxNumWords]; 369 int NumWords = 0; 370 371 std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver; 372 nextIf(StringRef str)373 bool nextIf(StringRef str) { 374 if (!Text.substr(Pos).startswith(str)) return false; 375 Pos += str.size(); 376 return true; 377 } 378 peekChar()379 char peekChar() { 380 if (Pos >= Text.size()) 381 return 0; 382 return Text[Pos]; 383 } 384 nextChar()385 char nextChar() { 386 if (Pos >= Text.size()) 387 return 0; 388 return Text[Pos++]; 389 } 390 nextIf(char c)391 bool nextIf(char c) { 392 if (peekChar() != c) 393 return false; 394 Pos++; 395 return true; 396 } 397 pushBack()398 void pushBack() { 399 assert(Pos > 0); 400 Pos--; 401 } 402 consumeAll()403 StringRef consumeAll() { 404 StringRef str = Text.drop_front(Pos); 405 Pos = Text.size(); 406 return str; 407 } 408 pushNode(NodePointer Nd)409 void pushNode(NodePointer Nd) { 410 NodeStack.push_back(Nd, *this); 411 } 412 popNode()413 NodePointer popNode() { 414 return NodeStack.pop_back_val(); 415 } 416 popNode(Node::Kind kind)417 NodePointer popNode(Node::Kind kind) { 418 if (NodeStack.empty()) 419 return nullptr; 420 421 Node::Kind NdKind = NodeStack.back()->getKind(); 422 if (NdKind != kind) 423 return nullptr; 424 425 return popNode(); 426 } 427 popNode(Pred pred)428 template <typename Pred> NodePointer popNode(Pred pred) { 429 if (NodeStack.empty()) 430 return nullptr; 431 432 Node::Kind NdKind = NodeStack.back()->getKind(); 433 if (!pred(NdKind)) 434 return nullptr; 435 436 return popNode(); 437 } 438 439 /// This class handles preparing the initial state for a demangle job in a reentrant way, pushing the 440 /// existing state back when a demangle job is completed. 441 class DemangleInitRAII { 442 Demangler &Dem; 443 Vector<NodePointer> NodeStack; 444 Vector<NodePointer> Substitutions; 445 int NumWords; 446 StringRef Text; 447 size_t Pos; 448 std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver; 449 450 public: 451 DemangleInitRAII(Demangler &Dem, StringRef MangledName, 452 std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver); 453 ~DemangleInitRAII(); 454 }; 455 friend DemangleInitRAII; 456 addSubstitution(NodePointer Nd)457 void addSubstitution(NodePointer Nd) { 458 if (Nd) 459 Substitutions.push_back(Nd, *this); 460 } 461 462 NodePointer addChild(NodePointer Parent, NodePointer Child); 463 NodePointer createWithChild(Node::Kind kind, NodePointer Child); 464 NodePointer createType(NodePointer Child); 465 NodePointer createWithChildren(Node::Kind kind, NodePointer Child1, 466 NodePointer Child2); 467 NodePointer createWithChildren(Node::Kind kind, NodePointer Child1, 468 NodePointer Child2, NodePointer Child3); 469 NodePointer createWithChildren(Node::Kind kind, NodePointer Child1, 470 NodePointer Child2, NodePointer Child3, 471 NodePointer Child4); createWithPoppedType(Node::Kind kind)472 NodePointer createWithPoppedType(Node::Kind kind) { 473 return createWithChild(kind, popNode(Node::Kind::Type)); 474 } 475 476 bool parseAndPushNodes(); 477 478 NodePointer changeKind(NodePointer Node, Node::Kind NewKind); 479 480 NodePointer demangleOperator(); 481 482 int demangleNatural(); 483 int demangleIndex(); 484 NodePointer demangleIndexAsNode(); 485 NodePointer demangleDependentConformanceIndex(); 486 NodePointer demangleIdentifier(); 487 NodePointer demangleOperatorIdentifier(); 488 489 std::string demangleBridgedMethodParams(); 490 491 NodePointer demangleMultiSubstitutions(); 492 NodePointer pushMultiSubstitutions(int RepeatCount, size_t SubstIdx); 493 NodePointer createSwiftType(Node::Kind typeKind, const char *name); 494 NodePointer demangleStandardSubstitution(); 495 NodePointer createStandardSubstitution(char Subst); 496 NodePointer demangleLocalIdentifier(); 497 498 NodePointer popModule(); 499 NodePointer popContext(); 500 NodePointer popTypeAndGetChild(); 501 NodePointer popTypeAndGetAnyGeneric(); 502 NodePointer demangleBuiltinType(); 503 NodePointer demangleAnyGenericType(Node::Kind kind); 504 NodePointer demangleExtensionContext(); 505 NodePointer demanglePlainFunction(); 506 NodePointer popFunctionType(Node::Kind kind); 507 NodePointer popFunctionParams(Node::Kind kind); 508 NodePointer popFunctionParamLabels(NodePointer FuncType); 509 NodePointer popTuple(); 510 NodePointer popTypeList(); 511 NodePointer popProtocol(); 512 NodePointer demangleBoundGenericType(); 513 NodePointer demangleBoundGenericArgs(NodePointer nominalType, 514 const Vector<NodePointer> &TypeLists, 515 size_t TypeListIdx); 516 NodePointer popAnyProtocolConformanceList(); 517 NodePointer demangleRetroactiveConformance(); 518 NodePointer demangleInitializer(); 519 NodePointer demangleImplParamConvention(Node::Kind ConvKind); 520 NodePointer demangleImplResultConvention(Node::Kind ConvKind); 521 NodePointer demangleImplFunctionType(); 522 NodePointer demangleMetatype(); 523 NodePointer demanglePrivateContextDescriptor(); 524 NodePointer createArchetypeRef(int depth, int i); 525 NodePointer demangleArchetype(); 526 NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx); 527 NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx); 528 529 NodePointer popAssocTypeName(); 530 NodePointer popAssocTypePath(); 531 NodePointer getDependentGenericParamType(int depth, int index); 532 NodePointer demangleGenericParamIndex(); 533 NodePointer popProtocolConformance(); 534 NodePointer demangleRetroactiveProtocolConformanceRef(); 535 NodePointer popAnyProtocolConformance(); 536 NodePointer demangleConcreteProtocolConformance(); 537 NodePointer popDependentProtocolConformance(); 538 NodePointer demangleDependentProtocolConformanceRoot(); 539 NodePointer demangleDependentProtocolConformanceInherited(); 540 NodePointer popDependentAssociatedConformance(); 541 NodePointer demangleDependentProtocolConformanceAssociated(); 542 NodePointer demangleThunkOrSpecialization(); 543 NodePointer demangleGenericSpecialization(Node::Kind SpecKind); 544 NodePointer demangleFunctionSpecialization(); 545 NodePointer demangleFuncSpecParam(Node::Kind Kind); 546 NodePointer addFuncSpecParamNumber(NodePointer Param, 547 FunctionSigSpecializationParamKind Kind); 548 549 NodePointer demangleSpecAttributes(Node::Kind SpecKind); 550 551 NodePointer demangleWitness(); 552 NodePointer demangleSpecialType(); 553 NodePointer demangleMetatypeRepresentation(); 554 NodePointer demangleAccessor(NodePointer ChildNode); 555 NodePointer demangleFunctionEntity(); 556 NodePointer demangleEntity(Node::Kind Kind); 557 NodePointer demangleVariable(); 558 NodePointer demangleSubscript(); 559 NodePointer demangleProtocolList(); 560 NodePointer demangleProtocolListType(); 561 NodePointer demangleGenericSignature(bool hasParamCounts); 562 NodePointer demangleGenericRequirement(); 563 NodePointer demangleGenericType(); 564 NodePointer demangleValueWitness(); 565 566 NodePointer demangleTypeMangling(); 567 NodePointer demangleSymbolicReference(unsigned char rawKind); 568 569 bool demangleBoundGenerics(Vector<NodePointer> &TypeListList, 570 NodePointer &RetroactiveConformances); 571 572 void dump(); 573 574 public: Demangler()575 Demangler() {} 576 577 void clear() override; 578 579 /// Demangle the given symbol and return the parse tree. 580 /// 581 /// \param MangledName The mangled symbol string, which start with the 582 /// mangling prefix $S. 583 /// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in 584 /// the string. If null, then symbolic references will cause the demangle to fail. 585 /// 586 /// \returns A parse tree for the demangled string - or a null pointer 587 /// on failure. 588 /// The lifetime of the returned node tree ends with the lifetime of the 589 /// Demangler or with a call of clear(). 590 NodePointer demangleSymbol(StringRef MangledName, 591 std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver 592 = nullptr); 593 594 /// Demangle the given type and return the parse tree. 595 /// 596 /// \param MangledName The mangled type string, which does _not_ start with 597 /// the mangling prefix $S. 598 /// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in 599 /// the string. If null, then symbolic references will cause the demangle to fail. 600 /// 601 /// \returns A parse tree for the demangled string - or a null pointer 602 /// on failure. 603 /// The lifetime of the returned node tree ends with the lifetime of the 604 /// Demangler or with a call of clear(). 605 NodePointer demangleType(StringRef MangledName, 606 std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver 607 = nullptr); 608 }; 609 610 /// A demangler which uses stack space for its initial memory. 611 /// 612 /// The \p Size paramter specifies the size of the stack space. 613 template <size_t Size> class StackAllocatedDemangler : public Demangler { 614 char StackSpace[Size]; 615 616 public: StackAllocatedDemangler()617 StackAllocatedDemangler() { 618 providePreallocatedMemory(StackSpace, Size); 619 } 620 }; 621 622 NodePointer demangleOldSymbolAsNode(StringRef MangledName, 623 NodeFactory &Factory); 624 } // end namespace Demangle 625 } // end namespace swift 626 627 #endif // SWIFT_DEMANGLING_DEMANGLER_H 628