CGCleanup.h revision 245431
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; 32226890Sdim llvm::BasicBlock *CachedEHDispatchBlock; 33218887Sdim 34226890Sdim EHScopeStack::stable_iterator EnclosingEHScope; 35218887Sdim 36226890Sdim class CommonBitFields { 37226890Sdim friend class EHScope; 38226890Sdim unsigned Kind : 2; 39226890Sdim }; 40226890Sdim enum { NumCommonBits = 2 }; 41226890Sdim 42218887Sdimprotected: 43226890Sdim class CatchBitFields { 44226890Sdim friend class EHCatchScope; 45226890Sdim unsigned : NumCommonBits; 46218887Sdim 47226890Sdim unsigned NumHandlers : 32 - NumCommonBits; 48226890Sdim }; 49226890Sdim 50226890Sdim class CleanupBitFields { 51226890Sdim friend class EHCleanupScope; 52226890Sdim unsigned : NumCommonBits; 53226890Sdim 54226890Sdim /// Whether this cleanup needs to be run along normal edges. 55226890Sdim unsigned IsNormalCleanup : 1; 56226890Sdim 57226890Sdim /// Whether this cleanup needs to be run along exception edges. 58226890Sdim unsigned IsEHCleanup : 1; 59226890Sdim 60226890Sdim /// Whether this cleanup is currently active. 61226890Sdim unsigned IsActive : 1; 62226890Sdim 63226890Sdim /// Whether the normal cleanup should test the activation flag. 64226890Sdim unsigned TestFlagInNormalCleanup : 1; 65226890Sdim 66226890Sdim /// Whether the EH cleanup should test the activation flag. 67226890Sdim unsigned TestFlagInEHCleanup : 1; 68226890Sdim 69226890Sdim /// The amount of extra storage needed by the Cleanup. 70226890Sdim /// Always a multiple of the scope-stack alignment. 71226890Sdim unsigned CleanupSize : 12; 72226890Sdim 73226890Sdim /// The number of fixups required by enclosing scopes (not including 74226890Sdim /// this one). If this is the top cleanup scope, all the fixups 75226890Sdim /// from this index onwards belong to this scope. 76226890Sdim unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13 77226890Sdim }; 78226890Sdim 79226890Sdim class FilterBitFields { 80226890Sdim friend class EHFilterScope; 81226890Sdim unsigned : NumCommonBits; 82226890Sdim 83226890Sdim unsigned NumFilters : 32 - NumCommonBits; 84226890Sdim }; 85226890Sdim 86226890Sdim union { 87226890Sdim CommonBitFields CommonBits; 88226890Sdim CatchBitFields CatchBits; 89226890Sdim CleanupBitFields CleanupBits; 90226890Sdim FilterBitFields FilterBits; 91226890Sdim }; 92226890Sdim 93218887Sdimpublic: 94218887Sdim enum Kind { Cleanup, Catch, Terminate, Filter }; 95218887Sdim 96226890Sdim EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope) 97226890Sdim : CachedLandingPad(0), CachedEHDispatchBlock(0), 98226890Sdim EnclosingEHScope(enclosingEHScope) { 99226890Sdim CommonBits.Kind = kind; 100226890Sdim } 101218887Sdim 102226890Sdim Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); } 103218887Sdim 104218887Sdim llvm::BasicBlock *getCachedLandingPad() const { 105218887Sdim return CachedLandingPad; 106218887Sdim } 107218887Sdim 108226890Sdim void setCachedLandingPad(llvm::BasicBlock *block) { 109226890Sdim CachedLandingPad = block; 110218887Sdim } 111226890Sdim 112226890Sdim llvm::BasicBlock *getCachedEHDispatchBlock() const { 113226890Sdim return CachedEHDispatchBlock; 114226890Sdim } 115226890Sdim 116226890Sdim void setCachedEHDispatchBlock(llvm::BasicBlock *block) { 117226890Sdim CachedEHDispatchBlock = block; 118226890Sdim } 119226890Sdim 120226890Sdim bool hasEHBranches() const { 121226890Sdim if (llvm::BasicBlock *block = getCachedEHDispatchBlock()) 122226890Sdim return !block->use_empty(); 123226890Sdim return false; 124226890Sdim } 125226890Sdim 126226890Sdim EHScopeStack::stable_iterator getEnclosingEHScope() const { 127226890Sdim return EnclosingEHScope; 128226890Sdim } 129218887Sdim}; 130218887Sdim 131218887Sdim/// A scope which attempts to handle some, possibly all, types of 132218887Sdim/// exceptions. 133218887Sdim/// 134245431Sdim/// Objective C \@finally blocks are represented using a cleanup scope 135218887Sdim/// after the catch scope. 136218887Sdimclass EHCatchScope : public EHScope { 137218887Sdim // In effect, we have a flexible array member 138218887Sdim // Handler Handlers[0]; 139218887Sdim // But that's only standard in C99, not C++, so we have to do 140218887Sdim // annoying pointer arithmetic instead. 141218887Sdim 142218887Sdimpublic: 143218887Sdim struct Handler { 144218887Sdim /// A type info value, or null (C++ null, not an LLVM null pointer) 145218887Sdim /// for a catch-all. 146218887Sdim llvm::Value *Type; 147218887Sdim 148218887Sdim /// The catch handler for this type. 149218887Sdim llvm::BasicBlock *Block; 150218887Sdim 151226890Sdim bool isCatchAll() const { return Type == 0; } 152218887Sdim }; 153218887Sdim 154218887Sdimprivate: 155218887Sdim friend class EHScopeStack; 156218887Sdim 157218887Sdim Handler *getHandlers() { 158218887Sdim return reinterpret_cast<Handler*>(this+1); 159218887Sdim } 160218887Sdim 161218887Sdim const Handler *getHandlers() const { 162218887Sdim return reinterpret_cast<const Handler*>(this+1); 163218887Sdim } 164218887Sdim 165218887Sdimpublic: 166218887Sdim static size_t getSizeForNumHandlers(unsigned N) { 167218887Sdim return sizeof(EHCatchScope) + N * sizeof(Handler); 168218887Sdim } 169218887Sdim 170226890Sdim EHCatchScope(unsigned numHandlers, 171226890Sdim EHScopeStack::stable_iterator enclosingEHScope) 172226890Sdim : EHScope(Catch, enclosingEHScope) { 173226890Sdim CatchBits.NumHandlers = numHandlers; 174218887Sdim } 175218887Sdim 176218887Sdim unsigned getNumHandlers() const { 177226890Sdim return CatchBits.NumHandlers; 178218887Sdim } 179218887Sdim 180218887Sdim void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) { 181218887Sdim setHandler(I, /*catchall*/ 0, Block); 182218887Sdim } 183218887Sdim 184218887Sdim void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) { 185218887Sdim assert(I < getNumHandlers()); 186218887Sdim getHandlers()[I].Type = Type; 187218887Sdim getHandlers()[I].Block = Block; 188218887Sdim } 189218887Sdim 190218887Sdim const Handler &getHandler(unsigned I) const { 191218887Sdim assert(I < getNumHandlers()); 192218887Sdim return getHandlers()[I]; 193218887Sdim } 194218887Sdim 195218887Sdim typedef const Handler *iterator; 196218887Sdim iterator begin() const { return getHandlers(); } 197218887Sdim iterator end() const { return getHandlers() + getNumHandlers(); } 198218887Sdim 199218887Sdim static bool classof(const EHScope *Scope) { 200218887Sdim return Scope->getKind() == Catch; 201218887Sdim } 202218887Sdim}; 203218887Sdim 204218887Sdim/// A cleanup scope which generates the cleanup blocks lazily. 205218887Sdimclass EHCleanupScope : public EHScope { 206218887Sdim /// The nearest normal cleanup scope enclosing this one. 207218887Sdim EHScopeStack::stable_iterator EnclosingNormal; 208218887Sdim 209226890Sdim /// The nearest EH scope enclosing this one. 210218887Sdim EHScopeStack::stable_iterator EnclosingEH; 211218887Sdim 212218887Sdim /// The dual entry/exit block along the normal edge. This is lazily 213218887Sdim /// created if needed before the cleanup is popped. 214218887Sdim llvm::BasicBlock *NormalBlock; 215218887Sdim 216218887Sdim /// An optional i1 variable indicating whether this cleanup has been 217218887Sdim /// activated yet. 218218887Sdim llvm::AllocaInst *ActiveFlag; 219218887Sdim 220218887Sdim /// Extra information required for cleanups that have resolved 221218887Sdim /// branches through them. This has to be allocated on the side 222218887Sdim /// because everything on the cleanup stack has be trivially 223218887Sdim /// movable. 224218887Sdim struct ExtInfo { 225218887Sdim /// The destinations of normal branch-afters and branch-throughs. 226218887Sdim llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches; 227218887Sdim 228218887Sdim /// Normal branch-afters. 229226890Sdim SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4> 230218887Sdim BranchAfters; 231218887Sdim }; 232218887Sdim mutable struct ExtInfo *ExtInfo; 233218887Sdim 234218887Sdim struct ExtInfo &getExtInfo() { 235218887Sdim if (!ExtInfo) ExtInfo = new struct ExtInfo(); 236218887Sdim return *ExtInfo; 237218887Sdim } 238218887Sdim 239218887Sdim const struct ExtInfo &getExtInfo() const { 240218887Sdim if (!ExtInfo) ExtInfo = new struct ExtInfo(); 241218887Sdim return *ExtInfo; 242218887Sdim } 243218887Sdim 244218887Sdimpublic: 245218887Sdim /// Gets the size required for a lazy cleanup scope with the given 246218887Sdim /// cleanup-data requirements. 247218887Sdim static size_t getSizeForCleanupSize(size_t Size) { 248218887Sdim return sizeof(EHCleanupScope) + Size; 249218887Sdim } 250218887Sdim 251218887Sdim size_t getAllocatedSize() const { 252226890Sdim return sizeof(EHCleanupScope) + CleanupBits.CleanupSize; 253218887Sdim } 254218887Sdim 255226890Sdim EHCleanupScope(bool isNormal, bool isEH, bool isActive, 256226890Sdim unsigned cleanupSize, unsigned fixupDepth, 257226890Sdim EHScopeStack::stable_iterator enclosingNormal, 258226890Sdim EHScopeStack::stable_iterator enclosingEH) 259226890Sdim : EHScope(EHScope::Cleanup, enclosingEH), EnclosingNormal(enclosingNormal), 260226890Sdim NormalBlock(0), ActiveFlag(0), ExtInfo(0) { 261226890Sdim CleanupBits.IsNormalCleanup = isNormal; 262226890Sdim CleanupBits.IsEHCleanup = isEH; 263226890Sdim CleanupBits.IsActive = isActive; 264226890Sdim CleanupBits.TestFlagInNormalCleanup = false; 265226890Sdim CleanupBits.TestFlagInEHCleanup = false; 266226890Sdim CleanupBits.CleanupSize = cleanupSize; 267226890Sdim CleanupBits.FixupDepth = fixupDepth; 268226890Sdim 269226890Sdim assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow"); 270218887Sdim } 271218887Sdim 272218887Sdim ~EHCleanupScope() { 273218887Sdim delete ExtInfo; 274218887Sdim } 275218887Sdim 276226890Sdim bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; } 277218887Sdim llvm::BasicBlock *getNormalBlock() const { return NormalBlock; } 278218887Sdim void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; } 279218887Sdim 280226890Sdim bool isEHCleanup() const { return CleanupBits.IsEHCleanup; } 281226890Sdim llvm::BasicBlock *getEHBlock() const { return getCachedEHDispatchBlock(); } 282226890Sdim void setEHBlock(llvm::BasicBlock *BB) { setCachedEHDispatchBlock(BB); } 283218887Sdim 284226890Sdim bool isActive() const { return CleanupBits.IsActive; } 285226890Sdim void setActive(bool A) { CleanupBits.IsActive = A; } 286218887Sdim 287218887Sdim llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; } 288218887Sdim void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; } 289218887Sdim 290226890Sdim void setTestFlagInNormalCleanup() { 291226890Sdim CleanupBits.TestFlagInNormalCleanup = true; 292226890Sdim } 293226890Sdim bool shouldTestFlagInNormalCleanup() const { 294226890Sdim return CleanupBits.TestFlagInNormalCleanup; 295226890Sdim } 296218887Sdim 297226890Sdim void setTestFlagInEHCleanup() { 298226890Sdim CleanupBits.TestFlagInEHCleanup = true; 299226890Sdim } 300226890Sdim bool shouldTestFlagInEHCleanup() const { 301226890Sdim return CleanupBits.TestFlagInEHCleanup; 302226890Sdim } 303218887Sdim 304226890Sdim unsigned getFixupDepth() const { return CleanupBits.FixupDepth; } 305218887Sdim EHScopeStack::stable_iterator getEnclosingNormalCleanup() const { 306218887Sdim return EnclosingNormal; 307218887Sdim } 308218887Sdim 309226890Sdim size_t getCleanupSize() const { return CleanupBits.CleanupSize; } 310218887Sdim void *getCleanupBuffer() { return this + 1; } 311218887Sdim 312218887Sdim EHScopeStack::Cleanup *getCleanup() { 313218887Sdim return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer()); 314218887Sdim } 315218887Sdim 316218887Sdim /// True if this cleanup scope has any branch-afters or branch-throughs. 317218887Sdim bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); } 318218887Sdim 319218887Sdim /// Add a branch-after to this cleanup scope. A branch-after is a 320218887Sdim /// branch from a point protected by this (normal) cleanup to a 321218887Sdim /// point in the normal cleanup scope immediately containing it. 322218887Sdim /// For example, 323218887Sdim /// for (;;) { A a; break; } 324218887Sdim /// contains a branch-after. 325218887Sdim /// 326218887Sdim /// Branch-afters each have their own destination out of the 327218887Sdim /// cleanup, guaranteed distinct from anything else threaded through 328218887Sdim /// it. Therefore branch-afters usually force a switch after the 329218887Sdim /// cleanup. 330218887Sdim void addBranchAfter(llvm::ConstantInt *Index, 331218887Sdim llvm::BasicBlock *Block) { 332218887Sdim struct ExtInfo &ExtInfo = getExtInfo(); 333218887Sdim if (ExtInfo.Branches.insert(Block)) 334218887Sdim ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index)); 335218887Sdim } 336218887Sdim 337218887Sdim /// Return the number of unique branch-afters on this scope. 338218887Sdim unsigned getNumBranchAfters() const { 339218887Sdim return ExtInfo ? ExtInfo->BranchAfters.size() : 0; 340218887Sdim } 341218887Sdim 342218887Sdim llvm::BasicBlock *getBranchAfterBlock(unsigned I) const { 343218887Sdim assert(I < getNumBranchAfters()); 344218887Sdim return ExtInfo->BranchAfters[I].first; 345218887Sdim } 346218887Sdim 347218887Sdim llvm::ConstantInt *getBranchAfterIndex(unsigned I) const { 348218887Sdim assert(I < getNumBranchAfters()); 349218887Sdim return ExtInfo->BranchAfters[I].second; 350218887Sdim } 351218887Sdim 352218887Sdim /// Add a branch-through to this cleanup scope. A branch-through is 353218887Sdim /// a branch from a scope protected by this (normal) cleanup to an 354218887Sdim /// enclosing scope other than the immediately-enclosing normal 355218887Sdim /// cleanup scope. 356218887Sdim /// 357218887Sdim /// In the following example, the branch through B's scope is a 358218887Sdim /// branch-through, while the branch through A's scope is a 359218887Sdim /// branch-after: 360218887Sdim /// for (;;) { A a; B b; break; } 361218887Sdim /// 362218887Sdim /// All branch-throughs have a common destination out of the 363218887Sdim /// cleanup, one possibly shared with the fall-through. Therefore 364218887Sdim /// branch-throughs usually don't force a switch after the cleanup. 365218887Sdim /// 366218887Sdim /// \return true if the branch-through was new to this scope 367218887Sdim bool addBranchThrough(llvm::BasicBlock *Block) { 368218887Sdim return getExtInfo().Branches.insert(Block); 369218887Sdim } 370218887Sdim 371218887Sdim /// Determines if this cleanup scope has any branch throughs. 372218887Sdim bool hasBranchThroughs() const { 373218887Sdim if (!ExtInfo) return false; 374218887Sdim return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size()); 375218887Sdim } 376218887Sdim 377218887Sdim static bool classof(const EHScope *Scope) { 378218887Sdim return (Scope->getKind() == Cleanup); 379218887Sdim } 380218887Sdim}; 381218887Sdim 382218887Sdim/// An exceptions scope which filters exceptions thrown through it. 383218887Sdim/// Only exceptions matching the filter types will be permitted to be 384218887Sdim/// thrown. 385218887Sdim/// 386218887Sdim/// This is used to implement C++ exception specifications. 387218887Sdimclass EHFilterScope : public EHScope { 388218887Sdim // Essentially ends in a flexible array member: 389218887Sdim // llvm::Value *FilterTypes[0]; 390218887Sdim 391218887Sdim llvm::Value **getFilters() { 392218887Sdim return reinterpret_cast<llvm::Value**>(this+1); 393218887Sdim } 394218887Sdim 395218887Sdim llvm::Value * const *getFilters() const { 396218887Sdim return reinterpret_cast<llvm::Value* const *>(this+1); 397218887Sdim } 398218887Sdim 399218887Sdimpublic: 400226890Sdim EHFilterScope(unsigned numFilters) 401226890Sdim : EHScope(Filter, EHScopeStack::stable_end()) { 402226890Sdim FilterBits.NumFilters = numFilters; 403226890Sdim } 404218887Sdim 405226890Sdim static size_t getSizeForNumFilters(unsigned numFilters) { 406226890Sdim return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*); 407218887Sdim } 408218887Sdim 409226890Sdim unsigned getNumFilters() const { return FilterBits.NumFilters; } 410218887Sdim 411226890Sdim void setFilter(unsigned i, llvm::Value *filterValue) { 412226890Sdim assert(i < getNumFilters()); 413226890Sdim getFilters()[i] = filterValue; 414218887Sdim } 415218887Sdim 416226890Sdim llvm::Value *getFilter(unsigned i) const { 417226890Sdim assert(i < getNumFilters()); 418226890Sdim return getFilters()[i]; 419218887Sdim } 420218887Sdim 421226890Sdim static bool classof(const EHScope *scope) { 422226890Sdim return scope->getKind() == Filter; 423218887Sdim } 424218887Sdim}; 425218887Sdim 426218887Sdim/// An exceptions scope which calls std::terminate if any exception 427218887Sdim/// reaches it. 428218887Sdimclass EHTerminateScope : public EHScope { 429218887Sdimpublic: 430226890Sdim EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope) 431226890Sdim : EHScope(Terminate, enclosingEHScope) {} 432218887Sdim static size_t getSize() { return sizeof(EHTerminateScope); } 433218887Sdim 434226890Sdim static bool classof(const EHScope *scope) { 435226890Sdim return scope->getKind() == Terminate; 436218887Sdim } 437218887Sdim}; 438218887Sdim 439218887Sdim/// A non-stable pointer into the scope stack. 440218887Sdimclass EHScopeStack::iterator { 441218887Sdim char *Ptr; 442218887Sdim 443218887Sdim friend class EHScopeStack; 444218887Sdim explicit iterator(char *Ptr) : Ptr(Ptr) {} 445218887Sdim 446218887Sdimpublic: 447218887Sdim iterator() : Ptr(0) {} 448218887Sdim 449218887Sdim EHScope *get() const { 450218887Sdim return reinterpret_cast<EHScope*>(Ptr); 451218887Sdim } 452218887Sdim 453218887Sdim EHScope *operator->() const { return get(); } 454218887Sdim EHScope &operator*() const { return *get(); } 455218887Sdim 456218887Sdim iterator &operator++() { 457218887Sdim switch (get()->getKind()) { 458218887Sdim case EHScope::Catch: 459218887Sdim Ptr += EHCatchScope::getSizeForNumHandlers( 460218887Sdim static_cast<const EHCatchScope*>(get())->getNumHandlers()); 461218887Sdim break; 462218887Sdim 463218887Sdim case EHScope::Filter: 464218887Sdim Ptr += EHFilterScope::getSizeForNumFilters( 465218887Sdim static_cast<const EHFilterScope*>(get())->getNumFilters()); 466218887Sdim break; 467218887Sdim 468218887Sdim case EHScope::Cleanup: 469218887Sdim Ptr += static_cast<const EHCleanupScope*>(get()) 470218887Sdim ->getAllocatedSize(); 471218887Sdim break; 472218887Sdim 473218887Sdim case EHScope::Terminate: 474218887Sdim Ptr += EHTerminateScope::getSize(); 475218887Sdim break; 476218887Sdim } 477218887Sdim 478218887Sdim return *this; 479218887Sdim } 480218887Sdim 481218887Sdim iterator next() { 482218887Sdim iterator copy = *this; 483218887Sdim ++copy; 484218887Sdim return copy; 485218887Sdim } 486218887Sdim 487218887Sdim iterator operator++(int) { 488218887Sdim iterator copy = *this; 489218887Sdim operator++(); 490218887Sdim return copy; 491218887Sdim } 492218887Sdim 493218887Sdim bool encloses(iterator other) const { return Ptr >= other.Ptr; } 494218887Sdim bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; } 495218887Sdim 496218887Sdim bool operator==(iterator other) const { return Ptr == other.Ptr; } 497218887Sdim bool operator!=(iterator other) const { return Ptr != other.Ptr; } 498218887Sdim}; 499218887Sdim 500218887Sdiminline EHScopeStack::iterator EHScopeStack::begin() const { 501218887Sdim return iterator(StartOfData); 502218887Sdim} 503218887Sdim 504218887Sdiminline EHScopeStack::iterator EHScopeStack::end() const { 505218887Sdim return iterator(EndOfBuffer); 506218887Sdim} 507218887Sdim 508218887Sdiminline void EHScopeStack::popCatch() { 509218887Sdim assert(!empty() && "popping exception stack when not empty"); 510218887Sdim 511226890Sdim EHCatchScope &scope = cast<EHCatchScope>(*begin()); 512226890Sdim InnermostEHScope = scope.getEnclosingEHScope(); 513226890Sdim StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()); 514218887Sdim} 515218887Sdim 516218887Sdiminline void EHScopeStack::popTerminate() { 517218887Sdim assert(!empty() && "popping exception stack when not empty"); 518218887Sdim 519226890Sdim EHTerminateScope &scope = cast<EHTerminateScope>(*begin()); 520226890Sdim InnermostEHScope = scope.getEnclosingEHScope(); 521218887Sdim StartOfData += EHTerminateScope::getSize(); 522218887Sdim} 523218887Sdim 524218887Sdiminline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { 525218887Sdim assert(sp.isValid() && "finding invalid savepoint"); 526218887Sdim assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); 527218887Sdim return iterator(EndOfBuffer - sp.Size); 528218887Sdim} 529218887Sdim 530218887Sdiminline EHScopeStack::stable_iterator 531218887SdimEHScopeStack::stabilize(iterator ir) const { 532218887Sdim assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer); 533218887Sdim return stable_iterator(EndOfBuffer - ir.Ptr); 534218887Sdim} 535218887Sdim 536218887Sdim} 537218887Sdim} 538218887Sdim 539218887Sdim#endif 540