xref: /aosp_15_r20/external/clang/lib/CodeGen/EHScopeStack.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
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