CGCleanup.h revision 218887
1218887Sdim//===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// These classes support the generation of LLVM IR for cleanups. 11218887Sdim// 12218887Sdim//===----------------------------------------------------------------------===// 13218887Sdim 14218887Sdim#ifndef CLANG_CODEGEN_CGCLEANUP_H 15218887Sdim#define CLANG_CODEGEN_CGCLEANUP_H 16218887Sdim 17218887Sdim/// EHScopeStack is defined in CodeGenFunction.h, but its 18218887Sdim/// implementation is in this file and in CGCleanup.cpp. 19218887Sdim#include "CodeGenFunction.h" 20218887Sdim 21218887Sdimnamespace llvm { 22218887Sdim class Value; 23218887Sdim class BasicBlock; 24218887Sdim} 25218887Sdim 26218887Sdimnamespace clang { 27218887Sdimnamespace CodeGen { 28218887Sdim 29218887Sdim/// A protected scope for zero-cost EH handling. 30218887Sdimclass EHScope { 31218887Sdim llvm::BasicBlock *CachedLandingPad; 32218887Sdim 33218887Sdim unsigned K : 2; 34218887Sdim 35218887Sdimprotected: 36218887Sdim enum { BitsRemaining = 30 }; 37218887Sdim 38218887Sdimpublic: 39218887Sdim enum Kind { Cleanup, Catch, Terminate, Filter }; 40218887Sdim 41218887Sdim EHScope(Kind K) : CachedLandingPad(0), K(K) {} 42218887Sdim 43218887Sdim Kind getKind() const { return static_cast<Kind>(K); } 44218887Sdim 45218887Sdim llvm::BasicBlock *getCachedLandingPad() const { 46218887Sdim return CachedLandingPad; 47218887Sdim } 48218887Sdim 49218887Sdim void setCachedLandingPad(llvm::BasicBlock *Block) { 50218887Sdim CachedLandingPad = Block; 51218887Sdim } 52218887Sdim}; 53218887Sdim 54218887Sdim/// A scope which attempts to handle some, possibly all, types of 55218887Sdim/// exceptions. 56218887Sdim/// 57218887Sdim/// Objective C @finally blocks are represented using a cleanup scope 58218887Sdim/// after the catch scope. 59218887Sdimclass EHCatchScope : public EHScope { 60218887Sdim unsigned NumHandlers : BitsRemaining; 61218887Sdim 62218887Sdim // In effect, we have a flexible array member 63218887Sdim // Handler Handlers[0]; 64218887Sdim // But that's only standard in C99, not C++, so we have to do 65218887Sdim // annoying pointer arithmetic instead. 66218887Sdim 67218887Sdimpublic: 68218887Sdim struct Handler { 69218887Sdim /// A type info value, or null (C++ null, not an LLVM null pointer) 70218887Sdim /// for a catch-all. 71218887Sdim llvm::Value *Type; 72218887Sdim 73218887Sdim /// The catch handler for this type. 74218887Sdim llvm::BasicBlock *Block; 75218887Sdim 76218887Sdim /// The unwind destination index for this handler. 77218887Sdim unsigned Index; 78218887Sdim }; 79218887Sdim 80218887Sdimprivate: 81218887Sdim friend class EHScopeStack; 82218887Sdim 83218887Sdim Handler *getHandlers() { 84218887Sdim return reinterpret_cast<Handler*>(this+1); 85218887Sdim } 86218887Sdim 87218887Sdim const Handler *getHandlers() const { 88218887Sdim return reinterpret_cast<const Handler*>(this+1); 89218887Sdim } 90218887Sdim 91218887Sdimpublic: 92218887Sdim static size_t getSizeForNumHandlers(unsigned N) { 93218887Sdim return sizeof(EHCatchScope) + N * sizeof(Handler); 94218887Sdim } 95218887Sdim 96218887Sdim EHCatchScope(unsigned NumHandlers) 97218887Sdim : EHScope(Catch), NumHandlers(NumHandlers) { 98218887Sdim } 99218887Sdim 100218887Sdim unsigned getNumHandlers() const { 101218887Sdim return NumHandlers; 102218887Sdim } 103218887Sdim 104218887Sdim void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) { 105218887Sdim setHandler(I, /*catchall*/ 0, Block); 106218887Sdim } 107218887Sdim 108218887Sdim void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) { 109218887Sdim assert(I < getNumHandlers()); 110218887Sdim getHandlers()[I].Type = Type; 111218887Sdim getHandlers()[I].Block = Block; 112218887Sdim } 113218887Sdim 114218887Sdim const Handler &getHandler(unsigned I) const { 115218887Sdim assert(I < getNumHandlers()); 116218887Sdim return getHandlers()[I]; 117218887Sdim } 118218887Sdim 119218887Sdim typedef const Handler *iterator; 120218887Sdim iterator begin() const { return getHandlers(); } 121218887Sdim iterator end() const { return getHandlers() + getNumHandlers(); } 122218887Sdim 123218887Sdim static bool classof(const EHScope *Scope) { 124218887Sdim return Scope->getKind() == Catch; 125218887Sdim } 126218887Sdim}; 127218887Sdim 128218887Sdim/// A cleanup scope which generates the cleanup blocks lazily. 129218887Sdimclass EHCleanupScope : public EHScope { 130218887Sdim /// Whether this cleanup needs to be run along normal edges. 131218887Sdim bool IsNormalCleanup : 1; 132218887Sdim 133218887Sdim /// Whether this cleanup needs to be run along exception edges. 134218887Sdim bool IsEHCleanup : 1; 135218887Sdim 136218887Sdim /// Whether this cleanup is currently active. 137218887Sdim bool IsActive : 1; 138218887Sdim 139218887Sdim /// Whether the normal cleanup should test the activation flag. 140218887Sdim bool TestFlagInNormalCleanup : 1; 141218887Sdim 142218887Sdim /// Whether the EH cleanup should test the activation flag. 143218887Sdim bool TestFlagInEHCleanup : 1; 144218887Sdim 145218887Sdim /// The amount of extra storage needed by the Cleanup. 146218887Sdim /// Always a multiple of the scope-stack alignment. 147218887Sdim unsigned CleanupSize : 12; 148218887Sdim 149218887Sdim /// The number of fixups required by enclosing scopes (not including 150218887Sdim /// this one). If this is the top cleanup scope, all the fixups 151218887Sdim /// from this index onwards belong to this scope. 152218887Sdim unsigned FixupDepth : BitsRemaining - 17; // currently 13 153218887Sdim 154218887Sdim /// The nearest normal cleanup scope enclosing this one. 155218887Sdim EHScopeStack::stable_iterator EnclosingNormal; 156218887Sdim 157218887Sdim /// The nearest EH cleanup scope enclosing this one. 158218887Sdim EHScopeStack::stable_iterator EnclosingEH; 159218887Sdim 160218887Sdim /// The dual entry/exit block along the normal edge. This is lazily 161218887Sdim /// created if needed before the cleanup is popped. 162218887Sdim llvm::BasicBlock *NormalBlock; 163218887Sdim 164218887Sdim /// The dual entry/exit block along the EH edge. This is lazily 165218887Sdim /// created if needed before the cleanup is popped. 166218887Sdim llvm::BasicBlock *EHBlock; 167218887Sdim 168218887Sdim /// An optional i1 variable indicating whether this cleanup has been 169218887Sdim /// activated yet. 170218887Sdim llvm::AllocaInst *ActiveFlag; 171218887Sdim 172218887Sdim /// Extra information required for cleanups that have resolved 173218887Sdim /// branches through them. This has to be allocated on the side 174218887Sdim /// because everything on the cleanup stack has be trivially 175218887Sdim /// movable. 176218887Sdim struct ExtInfo { 177218887Sdim /// The destinations of normal branch-afters and branch-throughs. 178218887Sdim llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches; 179218887Sdim 180218887Sdim /// Normal branch-afters. 181218887Sdim llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4> 182218887Sdim BranchAfters; 183218887Sdim 184218887Sdim /// The destinations of EH branch-afters and branch-throughs. 185218887Sdim /// TODO: optimize for the extremely common case of a single 186218887Sdim /// branch-through. 187218887Sdim llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches; 188218887Sdim 189218887Sdim /// EH branch-afters. 190218887Sdim llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4> 191218887Sdim EHBranchAfters; 192218887Sdim }; 193218887Sdim mutable struct ExtInfo *ExtInfo; 194218887Sdim 195218887Sdim struct ExtInfo &getExtInfo() { 196218887Sdim if (!ExtInfo) ExtInfo = new struct ExtInfo(); 197218887Sdim return *ExtInfo; 198218887Sdim } 199218887Sdim 200218887Sdim const struct ExtInfo &getExtInfo() const { 201218887Sdim if (!ExtInfo) ExtInfo = new struct ExtInfo(); 202218887Sdim return *ExtInfo; 203218887Sdim } 204218887Sdim 205218887Sdimpublic: 206218887Sdim /// Gets the size required for a lazy cleanup scope with the given 207218887Sdim /// cleanup-data requirements. 208218887Sdim static size_t getSizeForCleanupSize(size_t Size) { 209218887Sdim return sizeof(EHCleanupScope) + Size; 210218887Sdim } 211218887Sdim 212218887Sdim size_t getAllocatedSize() const { 213218887Sdim return sizeof(EHCleanupScope) + CleanupSize; 214218887Sdim } 215218887Sdim 216218887Sdim EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive, 217218887Sdim unsigned CleanupSize, unsigned FixupDepth, 218218887Sdim EHScopeStack::stable_iterator EnclosingNormal, 219218887Sdim EHScopeStack::stable_iterator EnclosingEH) 220218887Sdim : EHScope(EHScope::Cleanup), 221218887Sdim IsNormalCleanup(IsNormal), IsEHCleanup(IsEH), IsActive(IsActive), 222218887Sdim TestFlagInNormalCleanup(false), TestFlagInEHCleanup(false), 223218887Sdim CleanupSize(CleanupSize), FixupDepth(FixupDepth), 224218887Sdim EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH), 225218887Sdim NormalBlock(0), EHBlock(0), ActiveFlag(0), ExtInfo(0) 226218887Sdim { 227218887Sdim assert(this->CleanupSize == CleanupSize && "cleanup size overflow"); 228218887Sdim } 229218887Sdim 230218887Sdim ~EHCleanupScope() { 231218887Sdim delete ExtInfo; 232218887Sdim } 233218887Sdim 234218887Sdim bool isNormalCleanup() const { return IsNormalCleanup; } 235218887Sdim llvm::BasicBlock *getNormalBlock() const { return NormalBlock; } 236218887Sdim void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; } 237218887Sdim 238218887Sdim bool isEHCleanup() const { return IsEHCleanup; } 239218887Sdim llvm::BasicBlock *getEHBlock() const { return EHBlock; } 240218887Sdim void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; } 241218887Sdim 242218887Sdim bool isActive() const { return IsActive; } 243218887Sdim void setActive(bool A) { IsActive = A; } 244218887Sdim 245218887Sdim llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; } 246218887Sdim void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; } 247218887Sdim 248218887Sdim void setTestFlagInNormalCleanup() { TestFlagInNormalCleanup = true; } 249218887Sdim bool shouldTestFlagInNormalCleanup() const { return TestFlagInNormalCleanup; } 250218887Sdim 251218887Sdim void setTestFlagInEHCleanup() { TestFlagInEHCleanup = true; } 252218887Sdim bool shouldTestFlagInEHCleanup() const { return TestFlagInEHCleanup; } 253218887Sdim 254218887Sdim unsigned getFixupDepth() const { return FixupDepth; } 255218887Sdim EHScopeStack::stable_iterator getEnclosingNormalCleanup() const { 256218887Sdim return EnclosingNormal; 257218887Sdim } 258218887Sdim EHScopeStack::stable_iterator getEnclosingEHCleanup() const { 259218887Sdim return EnclosingEH; 260218887Sdim } 261218887Sdim 262218887Sdim size_t getCleanupSize() const { return CleanupSize; } 263218887Sdim void *getCleanupBuffer() { return this + 1; } 264218887Sdim 265218887Sdim EHScopeStack::Cleanup *getCleanup() { 266218887Sdim return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer()); 267218887Sdim } 268218887Sdim 269218887Sdim /// True if this cleanup scope has any branch-afters or branch-throughs. 270218887Sdim bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); } 271218887Sdim 272218887Sdim /// Add a branch-after to this cleanup scope. A branch-after is a 273218887Sdim /// branch from a point protected by this (normal) cleanup to a 274218887Sdim /// point in the normal cleanup scope immediately containing it. 275218887Sdim /// For example, 276218887Sdim /// for (;;) { A a; break; } 277218887Sdim /// contains a branch-after. 278218887Sdim /// 279218887Sdim /// Branch-afters each have their own destination out of the 280218887Sdim /// cleanup, guaranteed distinct from anything else threaded through 281218887Sdim /// it. Therefore branch-afters usually force a switch after the 282218887Sdim /// cleanup. 283218887Sdim void addBranchAfter(llvm::ConstantInt *Index, 284218887Sdim llvm::BasicBlock *Block) { 285218887Sdim struct ExtInfo &ExtInfo = getExtInfo(); 286218887Sdim if (ExtInfo.Branches.insert(Block)) 287218887Sdim ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index)); 288218887Sdim } 289218887Sdim 290218887Sdim /// Return the number of unique branch-afters on this scope. 291218887Sdim unsigned getNumBranchAfters() const { 292218887Sdim return ExtInfo ? ExtInfo->BranchAfters.size() : 0; 293218887Sdim } 294218887Sdim 295218887Sdim llvm::BasicBlock *getBranchAfterBlock(unsigned I) const { 296218887Sdim assert(I < getNumBranchAfters()); 297218887Sdim return ExtInfo->BranchAfters[I].first; 298218887Sdim } 299218887Sdim 300218887Sdim llvm::ConstantInt *getBranchAfterIndex(unsigned I) const { 301218887Sdim assert(I < getNumBranchAfters()); 302218887Sdim return ExtInfo->BranchAfters[I].second; 303218887Sdim } 304218887Sdim 305218887Sdim /// Add a branch-through to this cleanup scope. A branch-through is 306218887Sdim /// a branch from a scope protected by this (normal) cleanup to an 307218887Sdim /// enclosing scope other than the immediately-enclosing normal 308218887Sdim /// cleanup scope. 309218887Sdim /// 310218887Sdim /// In the following example, the branch through B's scope is a 311218887Sdim /// branch-through, while the branch through A's scope is a 312218887Sdim /// branch-after: 313218887Sdim /// for (;;) { A a; B b; break; } 314218887Sdim /// 315218887Sdim /// All branch-throughs have a common destination out of the 316218887Sdim /// cleanup, one possibly shared with the fall-through. Therefore 317218887Sdim /// branch-throughs usually don't force a switch after the cleanup. 318218887Sdim /// 319218887Sdim /// \return true if the branch-through was new to this scope 320218887Sdim bool addBranchThrough(llvm::BasicBlock *Block) { 321218887Sdim return getExtInfo().Branches.insert(Block); 322218887Sdim } 323218887Sdim 324218887Sdim /// Determines if this cleanup scope has any branch throughs. 325218887Sdim bool hasBranchThroughs() const { 326218887Sdim if (!ExtInfo) return false; 327218887Sdim return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size()); 328218887Sdim } 329218887Sdim 330218887Sdim // Same stuff, only for EH branches instead of normal branches. 331218887Sdim // It's quite possible that we could find a better representation 332218887Sdim // for this. 333218887Sdim 334218887Sdim bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); } 335218887Sdim void addEHBranchAfter(llvm::ConstantInt *Index, 336218887Sdim llvm::BasicBlock *Block) { 337218887Sdim struct ExtInfo &ExtInfo = getExtInfo(); 338218887Sdim if (ExtInfo.EHBranches.insert(Block)) 339218887Sdim ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index)); 340218887Sdim } 341218887Sdim 342218887Sdim unsigned getNumEHBranchAfters() const { 343218887Sdim return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0; 344218887Sdim } 345218887Sdim 346218887Sdim llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const { 347218887Sdim assert(I < getNumEHBranchAfters()); 348218887Sdim return ExtInfo->EHBranchAfters[I].first; 349218887Sdim } 350218887Sdim 351218887Sdim llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const { 352218887Sdim assert(I < getNumEHBranchAfters()); 353218887Sdim return ExtInfo->EHBranchAfters[I].second; 354218887Sdim } 355218887Sdim 356218887Sdim bool addEHBranchThrough(llvm::BasicBlock *Block) { 357218887Sdim return getExtInfo().EHBranches.insert(Block); 358218887Sdim } 359218887Sdim 360218887Sdim bool hasEHBranchThroughs() const { 361218887Sdim if (!ExtInfo) return false; 362218887Sdim return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size()); 363218887Sdim } 364218887Sdim 365218887Sdim static bool classof(const EHScope *Scope) { 366218887Sdim return (Scope->getKind() == Cleanup); 367218887Sdim } 368218887Sdim}; 369218887Sdim 370218887Sdim/// An exceptions scope which filters exceptions thrown through it. 371218887Sdim/// Only exceptions matching the filter types will be permitted to be 372218887Sdim/// thrown. 373218887Sdim/// 374218887Sdim/// This is used to implement C++ exception specifications. 375218887Sdimclass EHFilterScope : public EHScope { 376218887Sdim unsigned NumFilters : BitsRemaining; 377218887Sdim 378218887Sdim // Essentially ends in a flexible array member: 379218887Sdim // llvm::Value *FilterTypes[0]; 380218887Sdim 381218887Sdim llvm::Value **getFilters() { 382218887Sdim return reinterpret_cast<llvm::Value**>(this+1); 383218887Sdim } 384218887Sdim 385218887Sdim llvm::Value * const *getFilters() const { 386218887Sdim return reinterpret_cast<llvm::Value* const *>(this+1); 387218887Sdim } 388218887Sdim 389218887Sdimpublic: 390218887Sdim EHFilterScope(unsigned NumFilters) : 391218887Sdim EHScope(Filter), NumFilters(NumFilters) {} 392218887Sdim 393218887Sdim static size_t getSizeForNumFilters(unsigned NumFilters) { 394218887Sdim return sizeof(EHFilterScope) + NumFilters * sizeof(llvm::Value*); 395218887Sdim } 396218887Sdim 397218887Sdim unsigned getNumFilters() const { return NumFilters; } 398218887Sdim 399218887Sdim void setFilter(unsigned I, llvm::Value *FilterValue) { 400218887Sdim assert(I < getNumFilters()); 401218887Sdim getFilters()[I] = FilterValue; 402218887Sdim } 403218887Sdim 404218887Sdim llvm::Value *getFilter(unsigned I) const { 405218887Sdim assert(I < getNumFilters()); 406218887Sdim return getFilters()[I]; 407218887Sdim } 408218887Sdim 409218887Sdim static bool classof(const EHScope *Scope) { 410218887Sdim return Scope->getKind() == Filter; 411218887Sdim } 412218887Sdim}; 413218887Sdim 414218887Sdim/// An exceptions scope which calls std::terminate if any exception 415218887Sdim/// reaches it. 416218887Sdimclass EHTerminateScope : public EHScope { 417218887Sdim unsigned DestIndex : BitsRemaining; 418218887Sdimpublic: 419218887Sdim EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {} 420218887Sdim static size_t getSize() { return sizeof(EHTerminateScope); } 421218887Sdim 422218887Sdim unsigned getDestIndex() const { return DestIndex; } 423218887Sdim 424218887Sdim static bool classof(const EHScope *Scope) { 425218887Sdim return Scope->getKind() == Terminate; 426218887Sdim } 427218887Sdim}; 428218887Sdim 429218887Sdim/// A non-stable pointer into the scope stack. 430218887Sdimclass EHScopeStack::iterator { 431218887Sdim char *Ptr; 432218887Sdim 433218887Sdim friend class EHScopeStack; 434218887Sdim explicit iterator(char *Ptr) : Ptr(Ptr) {} 435218887Sdim 436218887Sdimpublic: 437218887Sdim iterator() : Ptr(0) {} 438218887Sdim 439218887Sdim EHScope *get() const { 440218887Sdim return reinterpret_cast<EHScope*>(Ptr); 441218887Sdim } 442218887Sdim 443218887Sdim EHScope *operator->() const { return get(); } 444218887Sdim EHScope &operator*() const { return *get(); } 445218887Sdim 446218887Sdim iterator &operator++() { 447218887Sdim switch (get()->getKind()) { 448218887Sdim case EHScope::Catch: 449218887Sdim Ptr += EHCatchScope::getSizeForNumHandlers( 450218887Sdim static_cast<const EHCatchScope*>(get())->getNumHandlers()); 451218887Sdim break; 452218887Sdim 453218887Sdim case EHScope::Filter: 454218887Sdim Ptr += EHFilterScope::getSizeForNumFilters( 455218887Sdim static_cast<const EHFilterScope*>(get())->getNumFilters()); 456218887Sdim break; 457218887Sdim 458218887Sdim case EHScope::Cleanup: 459218887Sdim Ptr += static_cast<const EHCleanupScope*>(get()) 460218887Sdim ->getAllocatedSize(); 461218887Sdim break; 462218887Sdim 463218887Sdim case EHScope::Terminate: 464218887Sdim Ptr += EHTerminateScope::getSize(); 465218887Sdim break; 466218887Sdim } 467218887Sdim 468218887Sdim return *this; 469218887Sdim } 470218887Sdim 471218887Sdim iterator next() { 472218887Sdim iterator copy = *this; 473218887Sdim ++copy; 474218887Sdim return copy; 475218887Sdim } 476218887Sdim 477218887Sdim iterator operator++(int) { 478218887Sdim iterator copy = *this; 479218887Sdim operator++(); 480218887Sdim return copy; 481218887Sdim } 482218887Sdim 483218887Sdim bool encloses(iterator other) const { return Ptr >= other.Ptr; } 484218887Sdim bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; } 485218887Sdim 486218887Sdim bool operator==(iterator other) const { return Ptr == other.Ptr; } 487218887Sdim bool operator!=(iterator other) const { return Ptr != other.Ptr; } 488218887Sdim}; 489218887Sdim 490218887Sdiminline EHScopeStack::iterator EHScopeStack::begin() const { 491218887Sdim return iterator(StartOfData); 492218887Sdim} 493218887Sdim 494218887Sdiminline EHScopeStack::iterator EHScopeStack::end() const { 495218887Sdim return iterator(EndOfBuffer); 496218887Sdim} 497218887Sdim 498218887Sdiminline void EHScopeStack::popCatch() { 499218887Sdim assert(!empty() && "popping exception stack when not empty"); 500218887Sdim 501218887Sdim assert(isa<EHCatchScope>(*begin())); 502218887Sdim StartOfData += EHCatchScope::getSizeForNumHandlers( 503218887Sdim cast<EHCatchScope>(*begin()).getNumHandlers()); 504218887Sdim 505218887Sdim if (empty()) NextEHDestIndex = FirstEHDestIndex; 506218887Sdim 507218887Sdim assert(CatchDepth > 0 && "mismatched catch/terminate push/pop"); 508218887Sdim CatchDepth--; 509218887Sdim} 510218887Sdim 511218887Sdiminline void EHScopeStack::popTerminate() { 512218887Sdim assert(!empty() && "popping exception stack when not empty"); 513218887Sdim 514218887Sdim assert(isa<EHTerminateScope>(*begin())); 515218887Sdim StartOfData += EHTerminateScope::getSize(); 516218887Sdim 517218887Sdim if (empty()) NextEHDestIndex = FirstEHDestIndex; 518218887Sdim 519218887Sdim assert(CatchDepth > 0 && "mismatched catch/terminate push/pop"); 520218887Sdim CatchDepth--; 521218887Sdim} 522218887Sdim 523218887Sdiminline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { 524218887Sdim assert(sp.isValid() && "finding invalid savepoint"); 525218887Sdim assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); 526218887Sdim return iterator(EndOfBuffer - sp.Size); 527218887Sdim} 528218887Sdim 529218887Sdiminline EHScopeStack::stable_iterator 530218887SdimEHScopeStack::stabilize(iterator ir) const { 531218887Sdim assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer); 532218887Sdim return stable_iterator(EndOfBuffer - ir.Ptr); 533218887Sdim} 534218887Sdim 535218887Sdiminline EHScopeStack::stable_iterator 536218887SdimEHScopeStack::getInnermostActiveNormalCleanup() const { 537218887Sdim for (EHScopeStack::stable_iterator 538218887Sdim I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) { 539218887Sdim EHCleanupScope &S = cast<EHCleanupScope>(*find(I)); 540218887Sdim if (S.isActive()) return I; 541218887Sdim I = S.getEnclosingNormalCleanup(); 542218887Sdim } 543218887Sdim return stable_end(); 544218887Sdim} 545218887Sdim 546218887Sdiminline EHScopeStack::stable_iterator 547218887SdimEHScopeStack::getInnermostActiveEHCleanup() const { 548218887Sdim for (EHScopeStack::stable_iterator 549218887Sdim I = getInnermostEHCleanup(), E = stable_end(); I != E; ) { 550218887Sdim EHCleanupScope &S = cast<EHCleanupScope>(*find(I)); 551218887Sdim if (S.isActive()) return I; 552218887Sdim I = S.getEnclosingEHCleanup(); 553218887Sdim } 554218887Sdim return stable_end(); 555218887Sdim} 556218887Sdim 557218887Sdim} 558218887Sdim} 559218887Sdim 560218887Sdim#endif 561