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