1*67e74705SXin Li //===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li // 10*67e74705SXin Li // These classes should be the minimum interface required for other parts of 11*67e74705SXin Li // CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other 12*67e74705SXin Li // implemenentation details that are not widely needed are in CGCleanup.h. 13*67e74705SXin Li // 14*67e74705SXin Li //===----------------------------------------------------------------------===// 15*67e74705SXin Li 16*67e74705SXin Li #ifndef LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H 17*67e74705SXin Li #define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H 18*67e74705SXin Li 19*67e74705SXin Li #include "clang/Basic/LLVM.h" 20*67e74705SXin Li #include "llvm/ADT/STLExtras.h" 21*67e74705SXin Li #include "llvm/ADT/SmallVector.h" 22*67e74705SXin Li #include "llvm/IR/BasicBlock.h" 23*67e74705SXin Li #include "llvm/IR/Instructions.h" 24*67e74705SXin Li #include "llvm/IR/Value.h" 25*67e74705SXin Li 26*67e74705SXin Li namespace clang { 27*67e74705SXin Li namespace CodeGen { 28*67e74705SXin Li 29*67e74705SXin Li class CodeGenFunction; 30*67e74705SXin Li 31*67e74705SXin Li /// A branch fixup. These are required when emitting a goto to a 32*67e74705SXin Li /// label which hasn't been emitted yet. The goto is optimistically 33*67e74705SXin Li /// emitted as a branch to the basic block for the label, and (if it 34*67e74705SXin Li /// occurs in a scope with non-trivial cleanups) a fixup is added to 35*67e74705SXin Li /// the innermost cleanup. When a (normal) cleanup is popped, any 36*67e74705SXin Li /// unresolved fixups in that scope are threaded through the cleanup. 37*67e74705SXin Li struct BranchFixup { 38*67e74705SXin Li /// The block containing the terminator which needs to be modified 39*67e74705SXin Li /// into a switch if this fixup is resolved into the current scope. 40*67e74705SXin Li /// If null, LatestBranch points directly to the destination. 41*67e74705SXin Li llvm::BasicBlock *OptimisticBranchBlock; 42*67e74705SXin Li 43*67e74705SXin Li /// The ultimate destination of the branch. 44*67e74705SXin Li /// 45*67e74705SXin Li /// This can be set to null to indicate that this fixup was 46*67e74705SXin Li /// successfully resolved. 47*67e74705SXin Li llvm::BasicBlock *Destination; 48*67e74705SXin Li 49*67e74705SXin Li /// The destination index value. 50*67e74705SXin Li unsigned DestinationIndex; 51*67e74705SXin Li 52*67e74705SXin Li /// The initial branch of the fixup. 53*67e74705SXin Li llvm::BranchInst *InitialBranch; 54*67e74705SXin Li }; 55*67e74705SXin Li 56*67e74705SXin Li template <class T> struct InvariantValue { 57*67e74705SXin Li typedef T type; 58*67e74705SXin Li typedef T saved_type; needsSavingInvariantValue59*67e74705SXin Li static bool needsSaving(type value) { return false; } saveInvariantValue60*67e74705SXin Li static saved_type save(CodeGenFunction &CGF, type value) { return value; } restoreInvariantValue61*67e74705SXin Li static type restore(CodeGenFunction &CGF, saved_type value) { return value; } 62*67e74705SXin Li }; 63*67e74705SXin Li 64*67e74705SXin Li /// A metaprogramming class for ensuring that a value will dominate an 65*67e74705SXin Li /// arbitrary position in a function. 66*67e74705SXin Li template <class T> struct DominatingValue : InvariantValue<T> {}; 67*67e74705SXin Li 68*67e74705SXin Li template <class T, bool mightBeInstruction = 69*67e74705SXin Li std::is_base_of<llvm::Value, T>::value && 70*67e74705SXin Li !std::is_base_of<llvm::Constant, T>::value && 71*67e74705SXin Li !std::is_base_of<llvm::BasicBlock, T>::value> 72*67e74705SXin Li struct DominatingPointer; 73*67e74705SXin Li template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {}; 74*67e74705SXin Li // template <class T> struct DominatingPointer<T,true> at end of file 75*67e74705SXin Li 76*67e74705SXin Li template <class T> struct DominatingValue<T*> : DominatingPointer<T> {}; 77*67e74705SXin Li 78*67e74705SXin Li enum CleanupKind : unsigned { 79*67e74705SXin Li /// Denotes a cleanup that should run when a scope is exited using exceptional 80*67e74705SXin Li /// control flow (a throw statement leading to stack unwinding, ). 81*67e74705SXin Li EHCleanup = 0x1, 82*67e74705SXin Li 83*67e74705SXin Li /// Denotes a cleanup that should run when a scope is exited using normal 84*67e74705SXin Li /// control flow (falling off the end of the scope, return, goto, ...). 85*67e74705SXin Li NormalCleanup = 0x2, 86*67e74705SXin Li 87*67e74705SXin Li NormalAndEHCleanup = EHCleanup | NormalCleanup, 88*67e74705SXin Li 89*67e74705SXin Li InactiveCleanup = 0x4, 90*67e74705SXin Li InactiveEHCleanup = EHCleanup | InactiveCleanup, 91*67e74705SXin Li InactiveNormalCleanup = NormalCleanup | InactiveCleanup, 92*67e74705SXin Li InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup, 93*67e74705SXin Li 94*67e74705SXin Li LifetimeMarker = 0x8, 95*67e74705SXin Li NormalEHLifetimeMarker = LifetimeMarker | NormalAndEHCleanup, 96*67e74705SXin Li }; 97*67e74705SXin Li 98*67e74705SXin Li /// A stack of scopes which respond to exceptions, including cleanups 99*67e74705SXin Li /// and catch blocks. 100*67e74705SXin Li class EHScopeStack { 101*67e74705SXin Li public: 102*67e74705SXin Li /* Should switch to alignof(uint64_t) instead of 8, when EHCleanupScope can */ 103*67e74705SXin Li enum { ScopeStackAlignment = 8 }; 104*67e74705SXin Li 105*67e74705SXin Li /// A saved depth on the scope stack. This is necessary because 106*67e74705SXin Li /// pushing scopes onto the stack invalidates iterators. 107*67e74705SXin Li class stable_iterator { 108*67e74705SXin Li friend class EHScopeStack; 109*67e74705SXin Li 110*67e74705SXin Li /// Offset from StartOfData to EndOfBuffer. 111*67e74705SXin Li ptrdiff_t Size; 112*67e74705SXin Li 113*67e74705SXin Li stable_iterator(ptrdiff_t Size) : Size(Size) {} 114*67e74705SXin Li 115*67e74705SXin Li public: 116*67e74705SXin Li static stable_iterator invalid() { return stable_iterator(-1); } 117*67e74705SXin Li stable_iterator() : Size(-1) {} 118*67e74705SXin Li 119*67e74705SXin Li bool isValid() const { return Size >= 0; } 120*67e74705SXin Li 121*67e74705SXin Li /// Returns true if this scope encloses I. 122*67e74705SXin Li /// Returns false if I is invalid. 123*67e74705SXin Li /// This scope must be valid. 124*67e74705SXin Li bool encloses(stable_iterator I) const { return Size <= I.Size; } 125*67e74705SXin Li 126*67e74705SXin Li /// Returns true if this scope strictly encloses I: that is, 127*67e74705SXin Li /// if it encloses I and is not I. 128*67e74705SXin Li /// Returns false is I is invalid. 129*67e74705SXin Li /// This scope must be valid. 130*67e74705SXin Li bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; } 131*67e74705SXin Li 132*67e74705SXin Li friend bool operator==(stable_iterator A, stable_iterator B) { 133*67e74705SXin Li return A.Size == B.Size; 134*67e74705SXin Li } 135*67e74705SXin Li friend bool operator!=(stable_iterator A, stable_iterator B) { 136*67e74705SXin Li return A.Size != B.Size; 137*67e74705SXin Li } 138*67e74705SXin Li }; 139*67e74705SXin Li 140*67e74705SXin Li /// Information for lazily generating a cleanup. Subclasses must be 141*67e74705SXin Li /// POD-like: cleanups will not be destructed, and they will be 142*67e74705SXin Li /// allocated on the cleanup stack and freely copied and moved 143*67e74705SXin Li /// around. 144*67e74705SXin Li /// 145*67e74705SXin Li /// Cleanup implementations should generally be declared in an 146*67e74705SXin Li /// anonymous namespace. 147*67e74705SXin Li class Cleanup { 148*67e74705SXin Li // Anchor the construction vtable. 149*67e74705SXin Li virtual void anchor(); 150*67e74705SXin Li 151*67e74705SXin Li protected: 152*67e74705SXin Li ~Cleanup() = default; 153*67e74705SXin Li 154*67e74705SXin Li public: 155*67e74705SXin Li Cleanup(const Cleanup &) = default; 156*67e74705SXin Li Cleanup(Cleanup &&) {} 157*67e74705SXin Li Cleanup() = default; 158*67e74705SXin Li 159*67e74705SXin Li /// Generation flags. 160*67e74705SXin Li class Flags { 161*67e74705SXin Li enum { 162*67e74705SXin Li F_IsForEH = 0x1, 163*67e74705SXin Li F_IsNormalCleanupKind = 0x2, 164*67e74705SXin Li F_IsEHCleanupKind = 0x4 165*67e74705SXin Li }; 166*67e74705SXin Li unsigned flags; 167*67e74705SXin Li 168*67e74705SXin Li public: 169*67e74705SXin Li Flags() : flags(0) {} 170*67e74705SXin Li 171*67e74705SXin Li /// isForEH - true if the current emission is for an EH cleanup. 172*67e74705SXin Li bool isForEHCleanup() const { return flags & F_IsForEH; } 173*67e74705SXin Li bool isForNormalCleanup() const { return !isForEHCleanup(); } 174*67e74705SXin Li void setIsForEHCleanup() { flags |= F_IsForEH; } 175*67e74705SXin Li 176*67e74705SXin Li bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; } 177*67e74705SXin Li void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; } 178*67e74705SXin Li 179*67e74705SXin Li /// isEHCleanupKind - true if the cleanup was pushed as an EH 180*67e74705SXin Li /// cleanup. 181*67e74705SXin Li bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; } 182*67e74705SXin Li void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; } 183*67e74705SXin Li }; 184*67e74705SXin Li 185*67e74705SXin Li 186*67e74705SXin Li /// Emit the cleanup. For normal cleanups, this is run in the 187*67e74705SXin Li /// same EH context as when the cleanup was pushed, i.e. the 188*67e74705SXin Li /// immediately-enclosing context of the cleanup scope. For 189*67e74705SXin Li /// EH cleanups, this is run in a terminate context. 190*67e74705SXin Li /// 191*67e74705SXin Li // \param flags cleanup kind. 192*67e74705SXin Li virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0; 193*67e74705SXin Li }; 194*67e74705SXin Li 195*67e74705SXin Li /// ConditionalCleanup stores the saved form of its parameters, 196*67e74705SXin Li /// then restores them and performs the cleanup. 197*67e74705SXin Li template <class T, class... As> 198*67e74705SXin Li class ConditionalCleanup final : public Cleanup { 199*67e74705SXin Li typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple; 200*67e74705SXin Li SavedTuple Saved; 201*67e74705SXin Li 202*67e74705SXin Li template <std::size_t... Is> 203*67e74705SXin Li T restore(CodeGenFunction &CGF, llvm::index_sequence<Is...>) { 204*67e74705SXin Li // It's important that the restores are emitted in order. The braced init 205*67e74705SXin Li // list guarentees that. 206*67e74705SXin Li return T{DominatingValue<As>::restore(CGF, std::get<Is>(Saved))...}; 207*67e74705SXin Li } 208*67e74705SXin Li 209*67e74705SXin Li void Emit(CodeGenFunction &CGF, Flags flags) override { 210*67e74705SXin Li restore(CGF, llvm::index_sequence_for<As...>()).Emit(CGF, flags); 211*67e74705SXin Li } 212*67e74705SXin Li 213*67e74705SXin Li public: 214*67e74705SXin Li ConditionalCleanup(typename DominatingValue<As>::saved_type... A) 215*67e74705SXin Li : Saved(A...) {} 216*67e74705SXin Li 217*67e74705SXin Li ConditionalCleanup(SavedTuple Tuple) : Saved(std::move(Tuple)) {} 218*67e74705SXin Li }; 219*67e74705SXin Li 220*67e74705SXin Li private: 221*67e74705SXin Li // The implementation for this class is in CGException.h and 222*67e74705SXin Li // CGException.cpp; the definition is here because it's used as a 223*67e74705SXin Li // member of CodeGenFunction. 224*67e74705SXin Li 225*67e74705SXin Li /// The start of the scope-stack buffer, i.e. the allocated pointer 226*67e74705SXin Li /// for the buffer. All of these pointers are either simultaneously 227*67e74705SXin Li /// null or simultaneously valid. 228*67e74705SXin Li char *StartOfBuffer; 229*67e74705SXin Li 230*67e74705SXin Li /// The end of the buffer. 231*67e74705SXin Li char *EndOfBuffer; 232*67e74705SXin Li 233*67e74705SXin Li /// The first valid entry in the buffer. 234*67e74705SXin Li char *StartOfData; 235*67e74705SXin Li 236*67e74705SXin Li /// The innermost normal cleanup on the stack. 237*67e74705SXin Li stable_iterator InnermostNormalCleanup; 238*67e74705SXin Li 239*67e74705SXin Li /// The innermost EH scope on the stack. 240*67e74705SXin Li stable_iterator InnermostEHScope; 241*67e74705SXin Li 242*67e74705SXin Li /// The current set of branch fixups. A branch fixup is a jump to 243*67e74705SXin Li /// an as-yet unemitted label, i.e. a label for which we don't yet 244*67e74705SXin Li /// know the EH stack depth. Whenever we pop a cleanup, we have 245*67e74705SXin Li /// to thread all the current branch fixups through it. 246*67e74705SXin Li /// 247*67e74705SXin Li /// Fixups are recorded as the Use of the respective branch or 248*67e74705SXin Li /// switch statement. The use points to the final destination. 249*67e74705SXin Li /// When popping out of a cleanup, these uses are threaded through 250*67e74705SXin Li /// the cleanup and adjusted to point to the new cleanup. 251*67e74705SXin Li /// 252*67e74705SXin Li /// Note that branches are allowed to jump into protected scopes 253*67e74705SXin Li /// in certain situations; e.g. the following code is legal: 254*67e74705SXin Li /// struct A { ~A(); }; // trivial ctor, non-trivial dtor 255*67e74705SXin Li /// goto foo; 256*67e74705SXin Li /// A a; 257*67e74705SXin Li /// foo: 258*67e74705SXin Li /// bar(); 259*67e74705SXin Li SmallVector<BranchFixup, 8> BranchFixups; 260*67e74705SXin Li 261*67e74705SXin Li char *allocate(size_t Size); 262*67e74705SXin Li void deallocate(size_t Size); 263*67e74705SXin Li 264*67e74705SXin Li void *pushCleanup(CleanupKind K, size_t DataSize); 265*67e74705SXin Li 266*67e74705SXin Li public: 267*67e74705SXin Li EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr), 268*67e74705SXin Li StartOfData(nullptr), InnermostNormalCleanup(stable_end()), 269*67e74705SXin Li InnermostEHScope(stable_end()) {} 270*67e74705SXin Li ~EHScopeStack() { delete[] StartOfBuffer; } 271*67e74705SXin Li 272*67e74705SXin Li /// Push a lazily-created cleanup on the stack. 273*67e74705SXin Li template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) { 274*67e74705SXin Li static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment, 275*67e74705SXin Li "Cleanup's alignment is too large."); 276*67e74705SXin Li void *Buffer = pushCleanup(Kind, sizeof(T)); 277*67e74705SXin Li Cleanup *Obj = new (Buffer) T(A...); 278*67e74705SXin Li (void) Obj; 279*67e74705SXin Li } 280*67e74705SXin Li 281*67e74705SXin Li /// Push a lazily-created cleanup on the stack. Tuple version. 282*67e74705SXin Li template <class T, class... As> 283*67e74705SXin Li void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) { 284*67e74705SXin Li static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment, 285*67e74705SXin Li "Cleanup's alignment is too large."); 286*67e74705SXin Li void *Buffer = pushCleanup(Kind, sizeof(T)); 287*67e74705SXin Li Cleanup *Obj = new (Buffer) T(std::move(A)); 288*67e74705SXin Li (void) Obj; 289*67e74705SXin Li } 290*67e74705SXin Li 291*67e74705SXin Li // Feel free to add more variants of the following: 292*67e74705SXin Li 293*67e74705SXin Li /// Push a cleanup with non-constant storage requirements on the 294*67e74705SXin Li /// stack. The cleanup type must provide an additional static method: 295*67e74705SXin Li /// static size_t getExtraSize(size_t); 296*67e74705SXin Li /// The argument to this method will be the value N, which will also 297*67e74705SXin Li /// be passed as the first argument to the constructor. 298*67e74705SXin Li /// 299*67e74705SXin Li /// The data stored in the extra storage must obey the same 300*67e74705SXin Li /// restrictions as normal cleanup member data. 301*67e74705SXin Li /// 302*67e74705SXin Li /// The pointer returned from this method is valid until the cleanup 303*67e74705SXin Li /// stack is modified. 304*67e74705SXin Li template <class T, class... As> 305*67e74705SXin Li T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) { 306*67e74705SXin Li static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment, 307*67e74705SXin Li "Cleanup's alignment is too large."); 308*67e74705SXin Li void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N)); 309*67e74705SXin Li return new (Buffer) T(N, A...); 310*67e74705SXin Li } 311*67e74705SXin Li 312*67e74705SXin Li void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) { 313*67e74705SXin Li void *Buffer = pushCleanup(Kind, Size); 314*67e74705SXin Li std::memcpy(Buffer, Cleanup, Size); 315*67e74705SXin Li } 316*67e74705SXin Li 317*67e74705SXin Li /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp. 318*67e74705SXin Li void popCleanup(); 319*67e74705SXin Li 320*67e74705SXin Li /// Push a set of catch handlers on the stack. The catch is 321*67e74705SXin Li /// uninitialized and will need to have the given number of handlers 322*67e74705SXin Li /// set on it. 323*67e74705SXin Li class EHCatchScope *pushCatch(unsigned NumHandlers); 324*67e74705SXin Li 325*67e74705SXin Li /// Pops a catch scope off the stack. This is private to CGException.cpp. 326*67e74705SXin Li void popCatch(); 327*67e74705SXin Li 328*67e74705SXin Li /// Push an exceptions filter on the stack. 329*67e74705SXin Li class EHFilterScope *pushFilter(unsigned NumFilters); 330*67e74705SXin Li 331*67e74705SXin Li /// Pops an exceptions filter off the stack. 332*67e74705SXin Li void popFilter(); 333*67e74705SXin Li 334*67e74705SXin Li /// Push a terminate handler on the stack. 335*67e74705SXin Li void pushTerminate(); 336*67e74705SXin Li 337*67e74705SXin Li /// Pops a terminate handler off the stack. 338*67e74705SXin Li void popTerminate(); 339*67e74705SXin Li 340*67e74705SXin Li // Returns true iff the current scope is either empty or contains only 341*67e74705SXin Li // lifetime markers, i.e. no real cleanup code 342*67e74705SXin Li bool containsOnlyLifetimeMarkers(stable_iterator Old) const; 343*67e74705SXin Li 344*67e74705SXin Li /// Determines whether the exception-scopes stack is empty. 345*67e74705SXin Li bool empty() const { return StartOfData == EndOfBuffer; } 346*67e74705SXin Li 347*67e74705SXin Li bool requiresLandingPad() const; 348*67e74705SXin Li 349*67e74705SXin Li /// Determines whether there are any normal cleanups on the stack. 350*67e74705SXin Li bool hasNormalCleanups() const { 351*67e74705SXin Li return InnermostNormalCleanup != stable_end(); 352*67e74705SXin Li } 353*67e74705SXin Li 354*67e74705SXin Li /// Returns the innermost normal cleanup on the stack, or 355*67e74705SXin Li /// stable_end() if there are no normal cleanups. 356*67e74705SXin Li stable_iterator getInnermostNormalCleanup() const { 357*67e74705SXin Li return InnermostNormalCleanup; 358*67e74705SXin Li } 359*67e74705SXin Li stable_iterator getInnermostActiveNormalCleanup() const; 360*67e74705SXin Li 361*67e74705SXin Li stable_iterator getInnermostEHScope() const { 362*67e74705SXin Li return InnermostEHScope; 363*67e74705SXin Li } 364*67e74705SXin Li 365*67e74705SXin Li 366*67e74705SXin Li /// An unstable reference to a scope-stack depth. Invalidated by 367*67e74705SXin Li /// pushes but not pops. 368*67e74705SXin Li class iterator; 369*67e74705SXin Li 370*67e74705SXin Li /// Returns an iterator pointing to the innermost EH scope. 371*67e74705SXin Li iterator begin() const; 372*67e74705SXin Li 373*67e74705SXin Li /// Returns an iterator pointing to the outermost EH scope. 374*67e74705SXin Li iterator end() const; 375*67e74705SXin Li 376*67e74705SXin Li /// Create a stable reference to the top of the EH stack. The 377*67e74705SXin Li /// returned reference is valid until that scope is popped off the 378*67e74705SXin Li /// stack. 379*67e74705SXin Li stable_iterator stable_begin() const { 380*67e74705SXin Li return stable_iterator(EndOfBuffer - StartOfData); 381*67e74705SXin Li } 382*67e74705SXin Li 383*67e74705SXin Li /// Create a stable reference to the bottom of the EH stack. 384*67e74705SXin Li static stable_iterator stable_end() { 385*67e74705SXin Li return stable_iterator(0); 386*67e74705SXin Li } 387*67e74705SXin Li 388*67e74705SXin Li /// Translates an iterator into a stable_iterator. 389*67e74705SXin Li stable_iterator stabilize(iterator it) const; 390*67e74705SXin Li 391*67e74705SXin Li /// Turn a stable reference to a scope depth into a unstable pointer 392*67e74705SXin Li /// to the EH stack. 393*67e74705SXin Li iterator find(stable_iterator save) const; 394*67e74705SXin Li 395*67e74705SXin Li /// Add a branch fixup to the current cleanup scope. 396*67e74705SXin Li BranchFixup &addBranchFixup() { 397*67e74705SXin Li assert(hasNormalCleanups() && "adding fixup in scope without cleanups"); 398*67e74705SXin Li BranchFixups.push_back(BranchFixup()); 399*67e74705SXin Li return BranchFixups.back(); 400*67e74705SXin Li } 401*67e74705SXin Li 402*67e74705SXin Li unsigned getNumBranchFixups() const { return BranchFixups.size(); } 403*67e74705SXin Li BranchFixup &getBranchFixup(unsigned I) { 404*67e74705SXin Li assert(I < getNumBranchFixups()); 405*67e74705SXin Li return BranchFixups[I]; 406*67e74705SXin Li } 407*67e74705SXin Li 408*67e74705SXin Li /// Pops lazily-removed fixups from the end of the list. This 409*67e74705SXin Li /// should only be called by procedures which have just popped a 410*67e74705SXin Li /// cleanup or resolved one or more fixups. 411*67e74705SXin Li void popNullFixups(); 412*67e74705SXin Li 413*67e74705SXin Li /// Clears the branch-fixups list. This should only be called by 414*67e74705SXin Li /// ResolveAllBranchFixups. 415*67e74705SXin Li void clearFixups() { BranchFixups.clear(); } 416*67e74705SXin Li }; 417*67e74705SXin Li 418*67e74705SXin Li } // namespace CodeGen 419*67e74705SXin Li } // namespace clang 420*67e74705SXin Li 421*67e74705SXin Li #endif 422