143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===//
243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//
343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//                     The LLVM Compiler Infrastructure
443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//
543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// This file is distributed under the University of Illinois Open Source
643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// License. See LICENSE.TXT for details.
743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//
843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//===----------------------------------------------------------------------===//
943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//
1043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// These classes should be the minimum interface required for other parts of
1143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// CodeGen to emit cleanups.  The implementation is in CGCleanup.cpp and other
1243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// implemenentation details that are not widely needed are in CGCleanup.h.
1343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//
1443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner//===----------------------------------------------------------------------===//
1543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
1643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#ifndef CLANG_CODEGEN_EHSCOPESTACK_H
1743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#define CLANG_CODEGEN_EHSCOPESTACK_H
1843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
1943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#include "clang/Basic/LLVM.h"
2043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#include "llvm/ADT/SmallVector.h"
2143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#include "llvm/IR/BasicBlock.h"
2243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#include "llvm/IR/Instructions.h"
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/IR/Value.h"
2443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
2543a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknernamespace clang {
2643a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknernamespace CodeGen {
2743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
2843a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass CodeGenFunction;
2943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
3043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// A branch fixup.  These are required when emitting a goto to a
3143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// label which hasn't been emitted yet.  The goto is optimistically
3243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// emitted as a branch to the basic block for the label, and (if it
3343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// occurs in a scope with non-trivial cleanups) a fixup is added to
3443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// the innermost cleanup.  When a (normal) cleanup is popped, any
3543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// unresolved fixups in that scope are threaded through the cleanup.
3643a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerstruct BranchFixup {
3743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The block containing the terminator which needs to be modified
3843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// into a switch if this fixup is resolved into the current scope.
3943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// If null, LatestBranch points directly to the destination.
4043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  llvm::BasicBlock *OptimisticBranchBlock;
4143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
4243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The ultimate destination of the branch.
4343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
4443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// This can be set to null to indicate that this fixup was
4543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// successfully resolved.
4643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  llvm::BasicBlock *Destination;
4743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
4843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The destination index value.
4943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  unsigned DestinationIndex;
5043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
5143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The initial branch of the fixup.
5243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  llvm::BranchInst *InitialBranch;
5343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner};
5443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
5543a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknertemplate <class T> struct InvariantValue {
5643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  typedef T type;
5743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  typedef T saved_type;
5843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  static bool needsSaving(type value) { return false; }
5943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  static saved_type save(CodeGenFunction &CGF, type value) { return value; }
6043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
6143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner};
6243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
6343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// A metaprogramming class for ensuring that a value will dominate an
6443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// arbitrary position in a function.
6543a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknertemplate <class T> struct DominatingValue : InvariantValue<T> {};
6643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
6743a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknertemplate <class T, bool mightBeInstruction =
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            std::is_base_of<llvm::Value, T>::value &&
69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            !std::is_base_of<llvm::Constant, T>::value &&
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            !std::is_base_of<llvm::BasicBlock, T>::value>
7143a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerstruct DominatingPointer;
7243a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknertemplate <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
7343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner// template <class T> struct DominatingPointer<T,true> at end of file
7443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
7543a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknertemplate <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
7643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
7743a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerenum CleanupKind {
7843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  EHCleanup = 0x1,
7943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  NormalCleanup = 0x2,
8043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  NormalAndEHCleanup = EHCleanup | NormalCleanup,
8143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
8243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  InactiveCleanup = 0x4,
8343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  InactiveEHCleanup = EHCleanup | InactiveCleanup,
8443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
8543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
8643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner};
8743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
8843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// A stack of scopes which respond to exceptions, including cleanups
8943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner/// and catch blocks.
9043a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass EHScopeStack {
9143a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerpublic:
9243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// A saved depth on the scope stack.  This is necessary because
9343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// pushing scopes onto the stack invalidates iterators.
9443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class stable_iterator {
9543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    friend class EHScopeStack;
9643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
9743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Offset from StartOfData to EndOfBuffer.
9843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ptrdiff_t Size;
9943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
10043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    stable_iterator(ptrdiff_t Size) : Size(Size) {}
10143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
10243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
10343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    static stable_iterator invalid() { return stable_iterator(-1); }
10443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    stable_iterator() : Size(-1) {}
10543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
10643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    bool isValid() const { return Size >= 0; }
10743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
10843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Returns true if this scope encloses I.
10943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Returns false if I is invalid.
11043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// This scope must be valid.
11143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    bool encloses(stable_iterator I) const { return Size <= I.Size; }
11243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
11343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Returns true if this scope strictly encloses I: that is,
11443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// if it encloses I and is not I.
11543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Returns false is I is invalid.
11643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// This scope must be valid.
11743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
11843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
11943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    friend bool operator==(stable_iterator A, stable_iterator B) {
12043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      return A.Size == B.Size;
12143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
12243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    friend bool operator!=(stable_iterator A, stable_iterator B) {
12343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      return A.Size != B.Size;
12443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
12543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
12643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
12743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Information for lazily generating a cleanup.  Subclasses must be
12843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// POD-like: cleanups will not be destructed, and they will be
12943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// allocated on the cleanup stack and freely copied and moved
13043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// around.
13143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
13243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Cleanup implementations should generally be declared in an
13343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// anonymous namespace.
13443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class Cleanup {
13543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    // Anchor the construction vtable.
13643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    virtual void anchor();
13743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
13843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Generation flags.
13943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    class Flags {
14043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      enum {
14143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner        F_IsForEH             = 0x1,
14243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner        F_IsNormalCleanupKind = 0x2,
14343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner        F_IsEHCleanupKind     = 0x4
14443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      };
14543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      unsigned flags;
14643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
14743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    public:
14843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      Flags() : flags(0) {}
14943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
15043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      /// isForEH - true if the current emission is for an EH cleanup.
15143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      bool isForEHCleanup() const { return flags & F_IsForEH; }
15243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      bool isForNormalCleanup() const { return !isForEHCleanup(); }
15343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      void setIsForEHCleanup() { flags |= F_IsForEH; }
15443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
15543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
15643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
15743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
15843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      /// isEHCleanupKind - true if the cleanup was pushed as an EH
15943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      /// cleanup.
16043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
16143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
16243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    };
16343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
16443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    // Provide a virtual destructor to suppress a very common warning
16543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    // that unfortunately cannot be suppressed without this.  Cleanups
16643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    // should not rely on this destructor ever being called.
16743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    virtual ~Cleanup() {}
16843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
16943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// Emit the cleanup.  For normal cleanups, this is run in the
17043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// same EH context as when the cleanup was pushed, i.e. the
17143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// immediately-enclosing context of the cleanup scope.  For
17243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    /// EH cleanups, this is run in a terminate context.
17343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ///
17443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    // \param flags cleanup kind.
17543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
17643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
17743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
17843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// ConditionalCleanupN stores the saved form of its N parameters,
17943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// then restores them and performs the cleanup.
18043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0>
18143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class ConditionalCleanup1 : public Cleanup {
18243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A0>::saved_type A0_saved;
18343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A0_saved a0_saved;
18443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void Emit(CodeGenFunction &CGF, Flags flags) override {
18643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
18743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      T(a0).Emit(CGF, flags);
18843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
18943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
19043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
19143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ConditionalCleanup1(A0_saved a0)
19243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      : a0_saved(a0) {}
19343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
19443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
19543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1>
19643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class ConditionalCleanup2 : public Cleanup {
19743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A0>::saved_type A0_saved;
19843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A1>::saved_type A1_saved;
19943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A0_saved a0_saved;
20043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A1_saved a1_saved;
20143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void Emit(CodeGenFunction &CGF, Flags flags) override {
20343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
20443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
20543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      T(a0, a1).Emit(CGF, flags);
20643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
20743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
20843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
20943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ConditionalCleanup2(A0_saved a0, A1_saved a1)
21043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      : a0_saved(a0), a1_saved(a1) {}
21143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
21243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
21343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2>
21443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class ConditionalCleanup3 : public Cleanup {
21543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A0>::saved_type A0_saved;
21643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A1>::saved_type A1_saved;
21743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A2>::saved_type A2_saved;
21843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A0_saved a0_saved;
21943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A1_saved a1_saved;
22043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A2_saved a2_saved;
22143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void Emit(CodeGenFunction &CGF, Flags flags) override {
22343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
22443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
22543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
22643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      T(a0, a1, a2).Emit(CGF, flags);
22743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
22843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
22943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
23043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
23143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
23243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
23343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
23443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2, class A3>
23543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class ConditionalCleanup4 : public Cleanup {
23643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A0>::saved_type A0_saved;
23743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A1>::saved_type A1_saved;
23843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A2>::saved_type A2_saved;
23943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    typedef typename DominatingValue<A3>::saved_type A3_saved;
24043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A0_saved a0_saved;
24143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A1_saved a1_saved;
24243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A2_saved a2_saved;
24343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    A3_saved a3_saved;
24443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    void Emit(CodeGenFunction &CGF, Flags flags) override {
24643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
24743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
24843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
24943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
25043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      T(a0, a1, a2, a3).Emit(CGF, flags);
25143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    }
25243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
25343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  public:
25443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
25543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner      : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
25643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  };
25743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
25843a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerprivate:
25943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  // The implementation for this class is in CGException.h and
26043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  // CGException.cpp; the definition is here because it's used as a
26143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  // member of CodeGenFunction.
26243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
26343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The start of the scope-stack buffer, i.e. the allocated pointer
26443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// for the buffer.  All of these pointers are either simultaneously
26543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// null or simultaneously valid.
26643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  char *StartOfBuffer;
26743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
26843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The end of the buffer.
26943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  char *EndOfBuffer;
27043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
27143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The first valid entry in the buffer.
27243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  char *StartOfData;
27343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
27443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The innermost normal cleanup on the stack.
27543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator InnermostNormalCleanup;
27643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
27743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The innermost EH scope on the stack.
27843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator InnermostEHScope;
27943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
28043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The current set of branch fixups.  A branch fixup is a jump to
28143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// an as-yet unemitted label, i.e. a label for which we don't yet
28243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// know the EH stack depth.  Whenever we pop a cleanup, we have
28343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// to thread all the current branch fixups through it.
28443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
28543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Fixups are recorded as the Use of the respective branch or
28643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// switch statement.  The use points to the final destination.
28743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// When popping out of a cleanup, these uses are threaded through
28843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// the cleanup and adjusted to point to the new cleanup.
28943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
29043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Note that branches are allowed to jump into protected scopes
29143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// in certain situations;  e.g. the following code is legal:
29243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///     struct A { ~A(); }; // trivial ctor, non-trivial dtor
29343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///     goto foo;
29443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///     A a;
29543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///    foo:
29643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///     bar();
29743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  SmallVector<BranchFixup, 8> BranchFixups;
29843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
29943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  char *allocate(size_t Size);
30043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
30143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void *pushCleanup(CleanupKind K, size_t DataSize);
30243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
30343a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerpublic:
3046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr),
3056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                   StartOfData(nullptr), InnermostNormalCleanup(stable_end()),
30643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner                   InnermostEHScope(stable_end()) {}
30743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ~EHScopeStack() { delete[] StartOfBuffer; }
30843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
30943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  // Variadic templates would make this not terrible.
31043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
31143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
31243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T>
31343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind) {
31443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
31543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T();
31643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
31743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
31843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
31943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
32043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0>
32143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind, A0 a0) {
32243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
32343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T(a0);
32443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
32543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
32643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
32743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
32843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1>
32943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
33043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
33143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T(a0, a1);
33243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
33343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
33443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
33543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
33643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2>
33743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
33843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
33943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T(a0, a1, a2);
34043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
34143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
34243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
34343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
34443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2, class A3>
34543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
34643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
34743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
34843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
34943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
35043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
35143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a lazily-created cleanup on the stack.
35243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2, class A3, class A4>
35343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
35443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T));
35543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
35643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    (void) Obj;
35743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
35843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
35943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  // Feel free to add more variants of the following:
36043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
36143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a cleanup with non-constant storage requirements on the
36243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// stack.  The cleanup type must provide an additional static method:
36343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///   static size_t getExtraSize(size_t);
36443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The argument to this method will be the value N, which will also
36543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// be passed as the first argument to the constructor.
36643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
36743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The data stored in the extra storage must obey the same
36843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// restrictions as normal cleanup member data.
36943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  ///
37043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// The pointer returned from this method is valid until the cleanup
37143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// stack is modified.
37243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  template <class T, class A0, class A1, class A2>
37343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  T *pushCleanupWithExtra(CleanupKind Kind, size_t N, A0 a0, A1 a1, A2 a2) {
37443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
37543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return new (Buffer) T(N, a0, a1, a2);
37643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
37743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
37843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) {
37943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    void *Buffer = pushCleanup(Kind, Size);
38043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    std::memcpy(Buffer, Cleanup, Size);
38143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
38243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
38343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Pops a cleanup scope off the stack.  This is private to CGCleanup.cpp.
38443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void popCleanup();
38543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
38643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a set of catch handlers on the stack.  The catch is
38743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// uninitialized and will need to have the given number of handlers
38843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// set on it.
38943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class EHCatchScope *pushCatch(unsigned NumHandlers);
39043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
39143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Pops a catch scope off the stack.  This is private to CGException.cpp.
39243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void popCatch();
39343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
39443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push an exceptions filter on the stack.
39543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class EHFilterScope *pushFilter(unsigned NumFilters);
39643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
39743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Pops an exceptions filter off the stack.
39843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void popFilter();
39943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
40043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Push a terminate handler on the stack.
40143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void pushTerminate();
40243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
40343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Pops a terminate handler off the stack.
40443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void popTerminate();
40543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
40643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Determines whether the exception-scopes stack is empty.
40743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  bool empty() const { return StartOfData == EndOfBuffer; }
40843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
40943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  bool requiresLandingPad() const {
41043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return InnermostEHScope != stable_end();
41143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
41243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
41343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Determines whether there are any normal cleanups on the stack.
41443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  bool hasNormalCleanups() const {
41543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return InnermostNormalCleanup != stable_end();
41643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
41743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
41843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Returns the innermost normal cleanup on the stack, or
41943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// stable_end() if there are no normal cleanups.
42043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator getInnermostNormalCleanup() const {
42143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return InnermostNormalCleanup;
42243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
42343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator getInnermostActiveNormalCleanup() const;
42443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
42543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator getInnermostEHScope() const {
42643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return InnermostEHScope;
42743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
42843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
42943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator getInnermostActiveEHScope() const;
43043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
43143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// An unstable reference to a scope-stack depth.  Invalidated by
43243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// pushes but not pops.
43343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  class iterator;
43443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
43543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Returns an iterator pointing to the innermost EH scope.
43643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  iterator begin() const;
43743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
43843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Returns an iterator pointing to the outermost EH scope.
43943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  iterator end() const;
44043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
44143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Create a stable reference to the top of the EH stack.  The
44243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// returned reference is valid until that scope is popped off the
44343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// stack.
44443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator stable_begin() const {
44543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return stable_iterator(EndOfBuffer - StartOfData);
44643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
44743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
44843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Create a stable reference to the bottom of the EH stack.
44943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  static stable_iterator stable_end() {
45043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return stable_iterator(0);
45143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
45243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
45343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Translates an iterator into a stable_iterator.
45443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  stable_iterator stabilize(iterator it) const;
45543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
45643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Turn a stable reference to a scope depth into a unstable pointer
45743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// to the EH stack.
45843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  iterator find(stable_iterator save) const;
45943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
46043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Removes the cleanup pointed to by the given stable_iterator.
46143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void removeCleanup(stable_iterator save);
46243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
46343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Add a branch fixup to the current cleanup scope.
46443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  BranchFixup &addBranchFixup() {
46543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
46643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    BranchFixups.push_back(BranchFixup());
46743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return BranchFixups.back();
46843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
46943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
47043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  unsigned getNumBranchFixups() const { return BranchFixups.size(); }
47143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  BranchFixup &getBranchFixup(unsigned I) {
47243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    assert(I < getNumBranchFixups());
47343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner    return BranchFixups[I];
47443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  }
47543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
47643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Pops lazily-removed fixups from the end of the list.  This
47743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// should only be called by procedures which have just popped a
47843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// cleanup or resolved one or more fixups.
47943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void popNullFixups();
48043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
48143a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// Clears the branch-fixups list.  This should only be called by
48243a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  /// ResolveAllBranchFixups.
48343a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner  void clearFixups() { BranchFixups.clear(); }
48443a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner};
48543a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
48643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner} // namespace CodeGen
48743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner} // namespace clang
48843a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
48943a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#endif
490