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