1 //===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // These classes support the generation of LLVM IR for cleanups. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 15 #define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H 16 17 #include "EHScopeStack.h" 18 19 #include "Address.h" 20 #include "llvm/ADT/SmallPtrSet.h" 21 #include "llvm/ADT/SmallVector.h" 22 23 namespace llvm { 24 class BasicBlock; 25 class Value; 26 class ConstantInt; 27 class AllocaInst; 28 } 29 30 namespace clang { 31 class FunctionDecl; 32 namespace CodeGen { 33 class CodeGenModule; 34 class CodeGenFunction; 35 36 /// The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the 37 /// type of a catch handler, so we use this wrapper. 38 struct CatchTypeInfo { 39 llvm::Constant *RTTI; 40 unsigned Flags; 41 }; 42 43 /// A protected scope for zero-cost EH handling. 44 class EHScope { 45 llvm::BasicBlock *CachedLandingPad; 46 llvm::BasicBlock *CachedEHDispatchBlock; 47 48 EHScopeStack::stable_iterator EnclosingEHScope; 49 50 class CommonBitFields { 51 friend class EHScope; 52 unsigned Kind : 3; 53 }; 54 enum { NumCommonBits = 3 }; 55 56 protected: 57 class CatchBitFields { 58 friend class EHCatchScope; 59 unsigned : NumCommonBits; 60 61 unsigned NumHandlers : 32 - NumCommonBits; 62 }; 63 64 class CleanupBitFields { 65 friend class EHCleanupScope; 66 unsigned : NumCommonBits; 67 68 /// Whether this cleanup needs to be run along normal edges. 69 unsigned IsNormalCleanup : 1; 70 71 /// Whether this cleanup needs to be run along exception edges. 72 unsigned IsEHCleanup : 1; 73 74 /// Whether this cleanup is currently active. 75 unsigned IsActive : 1; 76 77 /// Whether this cleanup is a lifetime marker 78 unsigned IsLifetimeMarker : 1; 79 80 /// Whether the normal cleanup should test the activation flag. 81 unsigned TestFlagInNormalCleanup : 1; 82 83 /// Whether the EH cleanup should test the activation flag. 84 unsigned TestFlagInEHCleanup : 1; 85 86 /// The amount of extra storage needed by the Cleanup. 87 /// Always a multiple of the scope-stack alignment. 88 unsigned CleanupSize : 12; 89 }; 90 91 class FilterBitFields { 92 friend class EHFilterScope; 93 unsigned : NumCommonBits; 94 95 unsigned NumFilters : 32 - NumCommonBits; 96 }; 97 98 union { 99 CommonBitFields CommonBits; 100 CatchBitFields CatchBits; 101 CleanupBitFields CleanupBits; 102 FilterBitFields FilterBits; 103 }; 104 105 public: 106 enum Kind { Cleanup, Catch, Terminate, Filter, PadEnd }; 107 108 EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope) 109 : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr), 110 EnclosingEHScope(enclosingEHScope) { 111 CommonBits.Kind = kind; 112 } 113 114 Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); } 115 116 llvm::BasicBlock *getCachedLandingPad() const { 117 return CachedLandingPad; 118 } 119 120 void setCachedLandingPad(llvm::BasicBlock *block) { 121 CachedLandingPad = block; 122 } 123 124 llvm::BasicBlock *getCachedEHDispatchBlock() const { 125 return CachedEHDispatchBlock; 126 } 127 128 void setCachedEHDispatchBlock(llvm::BasicBlock *block) { 129 CachedEHDispatchBlock = block; 130 } 131 132 bool hasEHBranches() const { 133 if (llvm::BasicBlock *block = getCachedEHDispatchBlock()) 134 return !block->use_empty(); 135 return false; 136 } 137 138 EHScopeStack::stable_iterator getEnclosingEHScope() const { 139 return EnclosingEHScope; 140 } 141 }; 142 143 /// A scope which attempts to handle some, possibly all, types of 144 /// exceptions. 145 /// 146 /// Objective C \@finally blocks are represented using a cleanup scope 147 /// after the catch scope. 148 class EHCatchScope : public EHScope { 149 // In effect, we have a flexible array member 150 // Handler Handlers[0]; 151 // But that's only standard in C99, not C++, so we have to do 152 // annoying pointer arithmetic instead. 153 154 public: 155 struct Handler { 156 /// A type info value, or null (C++ null, not an LLVM null pointer) 157 /// for a catch-all. 158 CatchTypeInfo Type; 159 160 /// The catch handler for this type. 161 llvm::BasicBlock *Block; 162 163 bool isCatchAll() const { return Type.RTTI == nullptr; } 164 }; 165 166 private: 167 friend class EHScopeStack; 168 169 Handler *getHandlers() { 170 return reinterpret_cast<Handler*>(this+1); 171 } 172 173 const Handler *getHandlers() const { 174 return reinterpret_cast<const Handler*>(this+1); 175 } 176 177 public: 178 static size_t getSizeForNumHandlers(unsigned N) { 179 return sizeof(EHCatchScope) + N * sizeof(Handler); 180 } 181 182 EHCatchScope(unsigned numHandlers, 183 EHScopeStack::stable_iterator enclosingEHScope) 184 : EHScope(Catch, enclosingEHScope) { 185 CatchBits.NumHandlers = numHandlers; 186 assert(CatchBits.NumHandlers == numHandlers && "NumHandlers overflow?"); 187 } 188 189 unsigned getNumHandlers() const { 190 return CatchBits.NumHandlers; 191 } 192 193 void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) { 194 setHandler(I, CatchTypeInfo{nullptr, 0}, Block); 195 } 196 197 void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) { 198 assert(I < getNumHandlers()); 199 getHandlers()[I].Type = CatchTypeInfo{Type, 0}; 200 getHandlers()[I].Block = Block; 201 } 202 203 void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block) { 204 assert(I < getNumHandlers()); 205 getHandlers()[I].Type = Type; 206 getHandlers()[I].Block = Block; 207 } 208 209 const Handler &getHandler(unsigned I) const { 210 assert(I < getNumHandlers()); 211 return getHandlers()[I]; 212 } 213 214 // Clear all handler blocks. 215 // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a 216 // 'takeHandler' or some such function which removes ownership from the 217 // EHCatchScope object if the handlers should live longer than EHCatchScope. 218 void clearHandlerBlocks() { 219 for (unsigned I = 0, N = getNumHandlers(); I != N; ++I) 220 delete getHandler(I).Block; 221 } 222 223 typedef const Handler *iterator; 224 iterator begin() const { return getHandlers(); } 225 iterator end() const { return getHandlers() + getNumHandlers(); } 226 227 static bool classof(const EHScope *Scope) { 228 return Scope->getKind() == Catch; 229 } 230 }; 231 232 /// A cleanup scope which generates the cleanup blocks lazily. 233 class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope { 234 /// The nearest normal cleanup scope enclosing this one. 235 EHScopeStack::stable_iterator EnclosingNormal; 236 237 /// The nearest EH scope enclosing this one. 238 EHScopeStack::stable_iterator EnclosingEH; 239 240 /// The dual entry/exit block along the normal edge. This is lazily 241 /// created if needed before the cleanup is popped. 242 llvm::BasicBlock *NormalBlock; 243 244 /// An optional i1 variable indicating whether this cleanup has been 245 /// activated yet. 246 llvm::AllocaInst *ActiveFlag; 247 248 /// Extra information required for cleanups that have resolved 249 /// branches through them. This has to be allocated on the side 250 /// because everything on the cleanup stack has be trivially 251 /// movable. 252 struct ExtInfo { 253 /// The destinations of normal branch-afters and branch-throughs. 254 llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches; 255 256 /// Normal branch-afters. 257 SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4> 258 BranchAfters; 259 }; 260 mutable struct ExtInfo *ExtInfo; 261 262 /// The number of fixups required by enclosing scopes (not including 263 /// this one). If this is the top cleanup scope, all the fixups 264 /// from this index onwards belong to this scope. 265 unsigned FixupDepth; 266 267 struct ExtInfo &getExtInfo() { 268 if (!ExtInfo) ExtInfo = new struct ExtInfo(); 269 return *ExtInfo; 270 } 271 272 const struct ExtInfo &getExtInfo() const { 273 if (!ExtInfo) ExtInfo = new struct ExtInfo(); 274 return *ExtInfo; 275 } 276 277 public: 278 /// Gets the size required for a lazy cleanup scope with the given 279 /// cleanup-data requirements. 280 static size_t getSizeForCleanupSize(size_t Size) { 281 return sizeof(EHCleanupScope) + Size; 282 } 283 284 size_t getAllocatedSize() const { 285 return sizeof(EHCleanupScope) + CleanupBits.CleanupSize; 286 } 287 288 EHCleanupScope(bool isNormal, bool isEH, bool isActive, 289 unsigned cleanupSize, unsigned fixupDepth, 290 EHScopeStack::stable_iterator enclosingNormal, 291 EHScopeStack::stable_iterator enclosingEH) 292 : EHScope(EHScope::Cleanup, enclosingEH), 293 EnclosingNormal(enclosingNormal), NormalBlock(nullptr), 294 ActiveFlag(nullptr), ExtInfo(nullptr), FixupDepth(fixupDepth) { 295 CleanupBits.IsNormalCleanup = isNormal; 296 CleanupBits.IsEHCleanup = isEH; 297 CleanupBits.IsActive = isActive; 298 CleanupBits.IsLifetimeMarker = false; 299 CleanupBits.TestFlagInNormalCleanup = false; 300 CleanupBits.TestFlagInEHCleanup = false; 301 CleanupBits.CleanupSize = cleanupSize; 302 303 assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow"); 304 } 305 306 void Destroy() { 307 delete ExtInfo; 308 } 309 // Objects of EHCleanupScope are not destructed. Use Destroy(). 310 ~EHCleanupScope() = delete; 311 312 bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; } 313 llvm::BasicBlock *getNormalBlock() const { return NormalBlock; } 314 void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; } 315 316 bool isEHCleanup() const { return CleanupBits.IsEHCleanup; } 317 318 bool isActive() const { return CleanupBits.IsActive; } 319 void setActive(bool A) { CleanupBits.IsActive = A; } 320 321 bool isLifetimeMarker() const { return CleanupBits.IsLifetimeMarker; } 322 void setLifetimeMarker() { CleanupBits.IsLifetimeMarker = true; } 323 324 bool hasActiveFlag() const { return ActiveFlag != nullptr; } 325 Address getActiveFlag() const { 326 return Address(ActiveFlag, CharUnits::One()); 327 } 328 void setActiveFlag(Address Var) { 329 assert(Var.getAlignment().isOne()); 330 ActiveFlag = cast<llvm::AllocaInst>(Var.getPointer()); 331 } 332 333 void setTestFlagInNormalCleanup() { 334 CleanupBits.TestFlagInNormalCleanup = true; 335 } 336 bool shouldTestFlagInNormalCleanup() const { 337 return CleanupBits.TestFlagInNormalCleanup; 338 } 339 340 void setTestFlagInEHCleanup() { 341 CleanupBits.TestFlagInEHCleanup = true; 342 } 343 bool shouldTestFlagInEHCleanup() const { 344 return CleanupBits.TestFlagInEHCleanup; 345 } 346 347 unsigned getFixupDepth() const { return FixupDepth; } 348 EHScopeStack::stable_iterator getEnclosingNormalCleanup() const { 349 return EnclosingNormal; 350 } 351 352 size_t getCleanupSize() const { return CleanupBits.CleanupSize; } 353 void *getCleanupBuffer() { return this + 1; } 354 355 EHScopeStack::Cleanup *getCleanup() { 356 return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer()); 357 } 358 359 /// True if this cleanup scope has any branch-afters or branch-throughs. 360 bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); } 361 362 /// Add a branch-after to this cleanup scope. A branch-after is a 363 /// branch from a point protected by this (normal) cleanup to a 364 /// point in the normal cleanup scope immediately containing it. 365 /// For example, 366 /// for (;;) { A a; break; } 367 /// contains a branch-after. 368 /// 369 /// Branch-afters each have their own destination out of the 370 /// cleanup, guaranteed distinct from anything else threaded through 371 /// it. Therefore branch-afters usually force a switch after the 372 /// cleanup. 373 void addBranchAfter(llvm::ConstantInt *Index, 374 llvm::BasicBlock *Block) { 375 struct ExtInfo &ExtInfo = getExtInfo(); 376 if (ExtInfo.Branches.insert(Block).second) 377 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index)); 378 } 379 380 /// Return the number of unique branch-afters on this scope. 381 unsigned getNumBranchAfters() const { 382 return ExtInfo ? ExtInfo->BranchAfters.size() : 0; 383 } 384 385 llvm::BasicBlock *getBranchAfterBlock(unsigned I) const { 386 assert(I < getNumBranchAfters()); 387 return ExtInfo->BranchAfters[I].first; 388 } 389 390 llvm::ConstantInt *getBranchAfterIndex(unsigned I) const { 391 assert(I < getNumBranchAfters()); 392 return ExtInfo->BranchAfters[I].second; 393 } 394 395 /// Add a branch-through to this cleanup scope. A branch-through is 396 /// a branch from a scope protected by this (normal) cleanup to an 397 /// enclosing scope other than the immediately-enclosing normal 398 /// cleanup scope. 399 /// 400 /// In the following example, the branch through B's scope is a 401 /// branch-through, while the branch through A's scope is a 402 /// branch-after: 403 /// for (;;) { A a; B b; break; } 404 /// 405 /// All branch-throughs have a common destination out of the 406 /// cleanup, one possibly shared with the fall-through. Therefore 407 /// branch-throughs usually don't force a switch after the cleanup. 408 /// 409 /// \return true if the branch-through was new to this scope 410 bool addBranchThrough(llvm::BasicBlock *Block) { 411 return getExtInfo().Branches.insert(Block).second; 412 } 413 414 /// Determines if this cleanup scope has any branch throughs. 415 bool hasBranchThroughs() const { 416 if (!ExtInfo) return false; 417 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size()); 418 } 419 420 static bool classof(const EHScope *Scope) { 421 return (Scope->getKind() == Cleanup); 422 } 423 }; 424 // NOTE: there's a bunch of different data classes tacked on after an 425 // EHCleanupScope. It is asserted (in EHScopeStack::pushCleanup*) that 426 // they don't require greater alignment than ScopeStackAlignment. So, 427 // EHCleanupScope ought to have alignment equal to that -- not more 428 // (would be misaligned by the stack allocator), and not less (would 429 // break the appended classes). 430 static_assert(llvm::AlignOf<EHCleanupScope>::Alignment == 431 EHScopeStack::ScopeStackAlignment, 432 "EHCleanupScope expected alignment"); 433 434 /// An exceptions scope which filters exceptions thrown through it. 435 /// Only exceptions matching the filter types will be permitted to be 436 /// thrown. 437 /// 438 /// This is used to implement C++ exception specifications. 439 class EHFilterScope : public EHScope { 440 // Essentially ends in a flexible array member: 441 // llvm::Value *FilterTypes[0]; 442 443 llvm::Value **getFilters() { 444 return reinterpret_cast<llvm::Value**>(this+1); 445 } 446 447 llvm::Value * const *getFilters() const { 448 return reinterpret_cast<llvm::Value* const *>(this+1); 449 } 450 451 public: 452 EHFilterScope(unsigned numFilters) 453 : EHScope(Filter, EHScopeStack::stable_end()) { 454 FilterBits.NumFilters = numFilters; 455 assert(FilterBits.NumFilters == numFilters && "NumFilters overflow"); 456 } 457 458 static size_t getSizeForNumFilters(unsigned numFilters) { 459 return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*); 460 } 461 462 unsigned getNumFilters() const { return FilterBits.NumFilters; } 463 464 void setFilter(unsigned i, llvm::Value *filterValue) { 465 assert(i < getNumFilters()); 466 getFilters()[i] = filterValue; 467 } 468 469 llvm::Value *getFilter(unsigned i) const { 470 assert(i < getNumFilters()); 471 return getFilters()[i]; 472 } 473 474 static bool classof(const EHScope *scope) { 475 return scope->getKind() == Filter; 476 } 477 }; 478 479 /// An exceptions scope which calls std::terminate if any exception 480 /// reaches it. 481 class EHTerminateScope : public EHScope { 482 public: 483 EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope) 484 : EHScope(Terminate, enclosingEHScope) {} 485 static size_t getSize() { return sizeof(EHTerminateScope); } 486 487 static bool classof(const EHScope *scope) { 488 return scope->getKind() == Terminate; 489 } 490 }; 491 492 class EHPadEndScope : public EHScope { 493 public: 494 EHPadEndScope(EHScopeStack::stable_iterator enclosingEHScope) 495 : EHScope(PadEnd, enclosingEHScope) {} 496 static size_t getSize() { return sizeof(EHPadEndScope); } 497 498 static bool classof(const EHScope *scope) { 499 return scope->getKind() == PadEnd; 500 } 501 }; 502 503 /// A non-stable pointer into the scope stack. 504 class EHScopeStack::iterator { 505 char *Ptr; 506 507 friend class EHScopeStack; 508 explicit iterator(char *Ptr) : Ptr(Ptr) {} 509 510 public: 511 iterator() : Ptr(nullptr) {} 512 513 EHScope *get() const { 514 return reinterpret_cast<EHScope*>(Ptr); 515 } 516 517 EHScope *operator->() const { return get(); } 518 EHScope &operator*() const { return *get(); } 519 520 iterator &operator++() { 521 size_t Size; 522 switch (get()->getKind()) { 523 case EHScope::Catch: 524 Size = EHCatchScope::getSizeForNumHandlers( 525 static_cast<const EHCatchScope *>(get())->getNumHandlers()); 526 break; 527 528 case EHScope::Filter: 529 Size = EHFilterScope::getSizeForNumFilters( 530 static_cast<const EHFilterScope *>(get())->getNumFilters()); 531 break; 532 533 case EHScope::Cleanup: 534 Size = static_cast<const EHCleanupScope *>(get())->getAllocatedSize(); 535 break; 536 537 case EHScope::Terminate: 538 Size = EHTerminateScope::getSize(); 539 break; 540 541 case EHScope::PadEnd: 542 Size = EHPadEndScope::getSize(); 543 break; 544 } 545 Ptr += llvm::alignTo(Size, ScopeStackAlignment); 546 return *this; 547 } 548 549 iterator next() { 550 iterator copy = *this; 551 ++copy; 552 return copy; 553 } 554 555 iterator operator++(int) { 556 iterator copy = *this; 557 operator++(); 558 return copy; 559 } 560 561 bool encloses(iterator other) const { return Ptr >= other.Ptr; } 562 bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; } 563 564 bool operator==(iterator other) const { return Ptr == other.Ptr; } 565 bool operator!=(iterator other) const { return Ptr != other.Ptr; } 566 }; 567 568 inline EHScopeStack::iterator EHScopeStack::begin() const { 569 return iterator(StartOfData); 570 } 571 572 inline EHScopeStack::iterator EHScopeStack::end() const { 573 return iterator(EndOfBuffer); 574 } 575 576 inline void EHScopeStack::popCatch() { 577 assert(!empty() && "popping exception stack when not empty"); 578 579 EHCatchScope &scope = cast<EHCatchScope>(*begin()); 580 InnermostEHScope = scope.getEnclosingEHScope(); 581 deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers())); 582 } 583 584 inline void EHScopeStack::popTerminate() { 585 assert(!empty() && "popping exception stack when not empty"); 586 587 EHTerminateScope &scope = cast<EHTerminateScope>(*begin()); 588 InnermostEHScope = scope.getEnclosingEHScope(); 589 deallocate(EHTerminateScope::getSize()); 590 } 591 592 inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { 593 assert(sp.isValid() && "finding invalid savepoint"); 594 assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); 595 return iterator(EndOfBuffer - sp.Size); 596 } 597 598 inline EHScopeStack::stable_iterator 599 EHScopeStack::stabilize(iterator ir) const { 600 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer); 601 return stable_iterator(EndOfBuffer - ir.Ptr); 602 } 603 604 /// The exceptions personality for a function. 605 struct EHPersonality { 606 const char *PersonalityFn; 607 608 // If this is non-null, this personality requires a non-standard 609 // function for rethrowing an exception after a catchall cleanup. 610 // This function must have prototype void(void*). 611 const char *CatchallRethrowFn; 612 613 static const EHPersonality &get(CodeGenModule &CGM, const FunctionDecl *FD); 614 static const EHPersonality &get(CodeGenFunction &CGF); 615 616 static const EHPersonality GNU_C; 617 static const EHPersonality GNU_C_SJLJ; 618 static const EHPersonality GNU_C_SEH; 619 static const EHPersonality GNU_ObjC; 620 static const EHPersonality GNUstep_ObjC; 621 static const EHPersonality GNU_ObjCXX; 622 static const EHPersonality NeXT_ObjC; 623 static const EHPersonality GNU_CPlusPlus; 624 static const EHPersonality GNU_CPlusPlus_SJLJ; 625 static const EHPersonality GNU_CPlusPlus_SEH; 626 static const EHPersonality MSVC_except_handler; 627 static const EHPersonality MSVC_C_specific_handler; 628 static const EHPersonality MSVC_CxxFrameHandler3; 629 630 /// Does this personality use landingpads or the family of pad instructions 631 /// designed to form funclets? 632 bool usesFuncletPads() const { return isMSVCPersonality(); } 633 634 bool isMSVCPersonality() const { 635 return this == &MSVC_except_handler || this == &MSVC_C_specific_handler || 636 this == &MSVC_CxxFrameHandler3; 637 } 638 639 bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; } 640 }; 641 } 642 } 643 644 #endif 645