136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===//
236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//
336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//                     The LLVM Compiler Infrastructure
436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//
536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// This file is distributed under the University of Illinois Open Source
636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// License. See LICENSE.TXT for details.
736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//
836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//===----------------------------------------------------------------------===//
936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//
1036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// These classes support the generation of LLVM IR for cleanups.
1136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//
1236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//===----------------------------------------------------------------------===//
1336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
1436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#ifndef CLANG_CODEGEN_CGCLEANUP_H
1536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#define CLANG_CODEGEN_CGCLEANUP_H
1636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
1743a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner#include "EHScopeStack.h"
186fe91e448f948b78a36dd7f978125e0a882c623fReid Kleckner#include "llvm/ADT/SmallPtrSet.h"
196fe91e448f948b78a36dd7f978125e0a882c623fReid Kleckner#include "llvm/ADT/SmallVector.h"
2043a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner
2143a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknernamespace llvm {
2243a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass BasicBlock;
2343a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass Value;
2443a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass ConstantInt;
2543a75fcbe4b592d7bea1fe262117114bcebc003cReid Klecknerclass AllocaInst;
2643a75fcbe4b592d7bea1fe262117114bcebc003cReid Kleckner}
2736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
2836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallnamespace clang {
2936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallnamespace CodeGen {
3036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
3136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// A protected scope for zero-cost EH handling.
3236f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHScope {
3336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::BasicBlock *CachedLandingPad;
34777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  llvm::BasicBlock *CachedEHDispatchBlock;
3536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
36777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHScopeStack::stable_iterator EnclosingEHScope;
37777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
38777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  class CommonBitFields {
39777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    friend class EHScope;
40777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned Kind : 2;
41777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  };
42777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  enum { NumCommonBits = 2 };
4336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
4436f893c1efe367f929d92c8b125f964c22ba189eJohn McCallprotected:
45777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  class CatchBitFields {
46777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    friend class EHCatchScope;
47777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned : NumCommonBits;
48777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
49777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned NumHandlers : 32 - NumCommonBits;
50777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  };
51777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
52777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  class CleanupBitFields {
53777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    friend class EHCleanupScope;
54777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned : NumCommonBits;
55777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
56777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Whether this cleanup needs to be run along normal edges.
57777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned IsNormalCleanup : 1;
58777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
59777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Whether this cleanup needs to be run along exception edges.
60777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned IsEHCleanup : 1;
61777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
62777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Whether this cleanup is currently active.
63777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned IsActive : 1;
64777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
65777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Whether the normal cleanup should test the activation flag.
66777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned TestFlagInNormalCleanup : 1;
67777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
68777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Whether the EH cleanup should test the activation flag.
69777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned TestFlagInEHCleanup : 1;
70777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
71777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// The amount of extra storage needed by the Cleanup.
72777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// Always a multiple of the scope-stack alignment.
73777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned CleanupSize : 12;
74777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
75777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// The number of fixups required by enclosing scopes (not including
76777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// this one).  If this is the top cleanup scope, all the fixups
77777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    /// from this index onwards belong to this scope.
78777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13
79777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  };
80777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
81777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  class FilterBitFields {
82777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    friend class EHFilterScope;
83777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned : NumCommonBits;
84777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
85777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    unsigned NumFilters : 32 - NumCommonBits;
86777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  };
87777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
88777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  union {
89777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CommonBitFields CommonBits;
90777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CatchBitFields CatchBits;
91777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBitFields CleanupBits;
92777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    FilterBitFields FilterBits;
93777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  };
9436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
9536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
9636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  enum Kind { Cleanup, Catch, Terminate, Filter };
9736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
98777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
100777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall      EnclosingEHScope(enclosingEHScope) {
101777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CommonBits.Kind = kind;
102777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
10336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
104777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); }
10536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
10636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::BasicBlock *getCachedLandingPad() const {
10736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return CachedLandingPad;
10836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
10936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
110777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setCachedLandingPad(llvm::BasicBlock *block) {
111777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CachedLandingPad = block;
112777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
113777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
114777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  llvm::BasicBlock *getCachedEHDispatchBlock() const {
115777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return CachedEHDispatchBlock;
116777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
117777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
118777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setCachedEHDispatchBlock(llvm::BasicBlock *block) {
119777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CachedEHDispatchBlock = block;
120777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
121777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
122777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool hasEHBranches() const {
123777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
124777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall      return !block->use_empty();
125777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return false;
126777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
127777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
128777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHScopeStack::stable_iterator getEnclosingEHScope() const {
129777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return EnclosingEHScope;
13036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
13136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
13236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
13336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// A scope which attempts to handle some, possibly all, types of
13436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// exceptions.
13536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall///
1362ee5ba35febf830d366b65dd0dcbf8e291c41342James Dennett/// Objective C \@finally blocks are represented using a cleanup scope
13736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// after the catch scope.
13836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHCatchScope : public EHScope {
13936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  // In effect, we have a flexible array member
14036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  //   Handler Handlers[0];
14136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  // But that's only standard in C99, not C++, so we have to do
14236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  // annoying pointer arithmetic instead.
14336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
14436f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
14536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  struct Handler {
14636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    /// A type info value, or null (C++ null, not an LLVM null pointer)
14736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    /// for a catch-all.
148ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    llvm::Constant *Type;
14936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
15036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    /// The catch handler for this type.
15136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    llvm::BasicBlock *Block;
15236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
1536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    bool isCatchAll() const { return Type == nullptr; }
15436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  };
15536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
15636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallprivate:
15736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  friend class EHScopeStack;
15836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
15936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  Handler *getHandlers() {
16036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<Handler*>(this+1);
16136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
16236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
16336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  const Handler *getHandlers() const {
16436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<const Handler*>(this+1);
16536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
16636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
16736f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
16836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  static size_t getSizeForNumHandlers(unsigned N) {
16936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return sizeof(EHCatchScope) + N * sizeof(Handler);
17036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
17136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
172777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHCatchScope(unsigned numHandlers,
173777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall               EHScopeStack::stable_iterator enclosingEHScope)
174777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    : EHScope(Catch, enclosingEHScope) {
175777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CatchBits.NumHandlers = numHandlers;
17636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
17736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
17836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  unsigned getNumHandlers() const {
179777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return CatchBits.NumHandlers;
18036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
18136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
18236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
1836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    setHandler(I, /*catchall*/ nullptr, Block);
18436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
18536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
186ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) {
18736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    assert(I < getNumHandlers());
18836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    getHandlers()[I].Type = Type;
18936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    getHandlers()[I].Block = Block;
19036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
19136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
19236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  const Handler &getHandler(unsigned I) const {
19336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    assert(I < getNumHandlers());
19436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return getHandlers()[I];
19536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
19636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Clear all handler blocks.
198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // FIXME: it's better to always call clearHandlerBlocks in DTOR and have a
199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // 'takeHandler' or some such function which removes ownership from the
200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // EHCatchScope object if the handlers should live longer than EHCatchScope.
201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void clearHandlerBlocks() {
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (unsigned I = 0, N = getNumHandlers(); I != N; ++I)
203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      delete getHandler(I).Block;
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
20636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  typedef const Handler *iterator;
20736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  iterator begin() const { return getHandlers(); }
20836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  iterator end() const { return getHandlers() + getNumHandlers(); }
20936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
21036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  static bool classof(const EHScope *Scope) {
21136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return Scope->getKind() == Catch;
21236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
21336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
21436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
21536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// A cleanup scope which generates the cleanup blocks lazily.
21636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHCleanupScope : public EHScope {
21736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// The nearest normal cleanup scope enclosing this one.
21836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScopeStack::stable_iterator EnclosingNormal;
21936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
220777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  /// The nearest EH scope enclosing this one.
22136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScopeStack::stable_iterator EnclosingEH;
22236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
22336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// The dual entry/exit block along the normal edge.  This is lazily
22436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// created if needed before the cleanup is popped.
22536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::BasicBlock *NormalBlock;
22636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
22736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// An optional i1 variable indicating whether this cleanup has been
22836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// activated yet.
22936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::AllocaInst *ActiveFlag;
23036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
23136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Extra information required for cleanups that have resolved
23236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// branches through them.  This has to be allocated on the side
23336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// because everything on the cleanup stack has be trivially
23436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// movable.
23536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  struct ExtInfo {
23636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    /// The destinations of normal branch-afters and branch-throughs.
23736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
23836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
23936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    /// Normal branch-afters.
240686775deca8b8685eb90801495880e3abdd844c2Chris Lattner    SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
24136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      BranchAfters;
24236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  };
24336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  mutable struct ExtInfo *ExtInfo;
24436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
24536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  struct ExtInfo &getExtInfo() {
24636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    if (!ExtInfo) ExtInfo = new struct ExtInfo();
24736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return *ExtInfo;
24836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
24936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
25036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  const struct ExtInfo &getExtInfo() const {
25136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    if (!ExtInfo) ExtInfo = new struct ExtInfo();
25236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return *ExtInfo;
25336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
25436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
25536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
25636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Gets the size required for a lazy cleanup scope with the given
25736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// cleanup-data requirements.
25836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  static size_t getSizeForCleanupSize(size_t Size) {
25936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return sizeof(EHCleanupScope) + Size;
26036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
26136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
26236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  size_t getAllocatedSize() const {
263777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return sizeof(EHCleanupScope) + CleanupBits.CleanupSize;
26436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
26536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
266777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHCleanupScope(bool isNormal, bool isEH, bool isActive,
267777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall                 unsigned cleanupSize, unsigned fixupDepth,
268777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall                 EHScopeStack::stable_iterator enclosingNormal,
269777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall                 EHScopeStack::stable_iterator enclosingEH)
270777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    : EHScope(EHScope::Cleanup, enclosingEH), EnclosingNormal(enclosingNormal),
2716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      NormalBlock(nullptr), ActiveFlag(nullptr), ExtInfo(nullptr) {
272777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.IsNormalCleanup = isNormal;
273777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.IsEHCleanup = isEH;
274777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.IsActive = isActive;
275777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.TestFlagInNormalCleanup = false;
276777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.TestFlagInEHCleanup = false;
277777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.CleanupSize = cleanupSize;
278777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.FixupDepth = fixupDepth;
279777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall
280777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow");
28136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
28236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
28336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ~EHCleanupScope() {
28436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    delete ExtInfo;
28536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
28636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
287777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; }
28836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
28936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
29036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
291777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool isEHCleanup() const { return CleanupBits.IsEHCleanup; }
292777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  llvm::BasicBlock *getEHBlock() const { return getCachedEHDispatchBlock(); }
293777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setEHBlock(llvm::BasicBlock *BB) { setCachedEHDispatchBlock(BB); }
29436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
295777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool isActive() const { return CleanupBits.IsActive; }
296777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setActive(bool A) { CleanupBits.IsActive = A; }
29736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
29836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
29936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
30036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
301777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setTestFlagInNormalCleanup() {
302777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.TestFlagInNormalCleanup = true;
303777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
304777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool shouldTestFlagInNormalCleanup() const {
305777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return CleanupBits.TestFlagInNormalCleanup;
306777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
30736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
308777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setTestFlagInEHCleanup() {
309777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    CleanupBits.TestFlagInEHCleanup = true;
310777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
311777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  bool shouldTestFlagInEHCleanup() const {
312777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return CleanupBits.TestFlagInEHCleanup;
313777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
31436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
315777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  unsigned getFixupDepth() const { return CleanupBits.FixupDepth; }
31636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
31736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return EnclosingNormal;
31836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
31936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
320777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  size_t getCleanupSize() const { return CleanupBits.CleanupSize; }
32136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  void *getCleanupBuffer() { return this + 1; }
32236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
32336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScopeStack::Cleanup *getCleanup() {
32436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
32536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
32636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
32736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// True if this cleanup scope has any branch-afters or branch-throughs.
32836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
32936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
33036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Add a branch-after to this cleanup scope.  A branch-after is a
33136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// branch from a point protected by this (normal) cleanup to a
33236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// point in the normal cleanup scope immediately containing it.
33336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// For example,
33436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///   for (;;) { A a; break; }
33536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// contains a branch-after.
33636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///
33736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Branch-afters each have their own destination out of the
33836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// cleanup, guaranteed distinct from anything else threaded through
33936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// it.  Therefore branch-afters usually force a switch after the
34036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// cleanup.
34136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  void addBranchAfter(llvm::ConstantInt *Index,
34236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall                      llvm::BasicBlock *Block) {
34336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    struct ExtInfo &ExtInfo = getExtInfo();
34436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    if (ExtInfo.Branches.insert(Block))
34536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
34636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
34736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
34836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Return the number of unique branch-afters on this scope.
34936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  unsigned getNumBranchAfters() const {
35036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
35136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
35236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
35336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
35436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    assert(I < getNumBranchAfters());
35536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return ExtInfo->BranchAfters[I].first;
35636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
35736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
35836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
35936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    assert(I < getNumBranchAfters());
36036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return ExtInfo->BranchAfters[I].second;
36136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
36236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
36336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Add a branch-through to this cleanup scope.  A branch-through is
36436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// a branch from a scope protected by this (normal) cleanup to an
36536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// enclosing scope other than the immediately-enclosing normal
36636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// cleanup scope.
36736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///
36836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// In the following example, the branch through B's scope is a
36936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// branch-through, while the branch through A's scope is a
37036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// branch-after:
37136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///   for (;;) { A a; B b; break; }
37236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///
37336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// All branch-throughs have a common destination out of the
37436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// cleanup, one possibly shared with the fall-through.  Therefore
37536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// branch-throughs usually don't force a switch after the cleanup.
37636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  ///
37736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// \return true if the branch-through was new to this scope
37836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool addBranchThrough(llvm::BasicBlock *Block) {
37936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return getExtInfo().Branches.insert(Block);
38036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
38136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
38236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  /// Determines if this cleanup scope has any branch throughs.
38336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool hasBranchThroughs() const {
38436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    if (!ExtInfo) return false;
38536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
38636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
38736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
38836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  static bool classof(const EHScope *Scope) {
38936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return (Scope->getKind() == Cleanup);
39036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
39136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
39236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
39336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// An exceptions scope which filters exceptions thrown through it.
39436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Only exceptions matching the filter types will be permitted to be
39536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// thrown.
39636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall///
39736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// This is used to implement C++ exception specifications.
39836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHFilterScope : public EHScope {
39936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  // Essentially ends in a flexible array member:
40036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  // llvm::Value *FilterTypes[0];
40136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
40236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::Value **getFilters() {
40336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<llvm::Value**>(this+1);
40436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
40536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
40636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  llvm::Value * const *getFilters() const {
40736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<llvm::Value* const *>(this+1);
40836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
40936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
41036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
411777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHFilterScope(unsigned numFilters)
412777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    : EHScope(Filter, EHScopeStack::stable_end()) {
413777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    FilterBits.NumFilters = numFilters;
414777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  }
41536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
416777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  static size_t getSizeForNumFilters(unsigned numFilters) {
417777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*);
41836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
41936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
420777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  unsigned getNumFilters() const { return FilterBits.NumFilters; }
42136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
422777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  void setFilter(unsigned i, llvm::Value *filterValue) {
423777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    assert(i < getNumFilters());
424777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    getFilters()[i] = filterValue;
42536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
42636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
427777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  llvm::Value *getFilter(unsigned i) const {
428777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    assert(i < getNumFilters());
429777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return getFilters()[i];
43036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
43136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
432777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  static bool classof(const EHScope *scope) {
433777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return scope->getKind() == Filter;
43436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
43536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
43636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
43736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// An exceptions scope which calls std::terminate if any exception
43836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// reaches it.
43936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHTerminateScope : public EHScope {
44036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
441777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)
442777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    : EHScope(Terminate, enclosingEHScope) {}
44336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  static size_t getSize() { return sizeof(EHTerminateScope); }
44436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
445777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  static bool classof(const EHScope *scope) {
446777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall    return scope->getKind() == Terminate;
44736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
44836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
44936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
45036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// A non-stable pointer into the scope stack.
45136f893c1efe367f929d92c8b125f964c22ba189eJohn McCallclass EHScopeStack::iterator {
45236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  char *Ptr;
45336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
45436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  friend class EHScopeStack;
45536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  explicit iterator(char *Ptr) : Ptr(Ptr) {}
45636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
45736f893c1efe367f929d92c8b125f964c22ba189eJohn McCallpublic:
4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  iterator() : Ptr(nullptr) {}
45936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
46036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScope *get() const {
46136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return reinterpret_cast<EHScope*>(Ptr);
46236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
46336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
46436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScope *operator->() const { return get(); }
46536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  EHScope &operator*() const { return *get(); }
46636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
46736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  iterator &operator++() {
46836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    switch (get()->getKind()) {
46936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    case EHScope::Catch:
47036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      Ptr += EHCatchScope::getSizeForNumHandlers(
47136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall          static_cast<const EHCatchScope*>(get())->getNumHandlers());
47236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      break;
47336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
47436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    case EHScope::Filter:
47536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      Ptr += EHFilterScope::getSizeForNumFilters(
47636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall          static_cast<const EHFilterScope*>(get())->getNumFilters());
47736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      break;
47836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
47936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    case EHScope::Cleanup:
48036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      Ptr += static_cast<const EHCleanupScope*>(get())
48136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall        ->getAllocatedSize();
48236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      break;
48336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
48436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    case EHScope::Terminate:
48536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      Ptr += EHTerminateScope::getSize();
48636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall      break;
48736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    }
48836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
48936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return *this;
49036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
49136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
49236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  iterator next() {
49336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    iterator copy = *this;
49436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    ++copy;
49536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return copy;
49636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
49736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
49836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  iterator operator++(int) {
49936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    iterator copy = *this;
50036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    operator++();
50136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall    return copy;
50236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  }
50336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
50436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool encloses(iterator other) const { return Ptr >= other.Ptr; }
50536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
50636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
50736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool operator==(iterator other) const { return Ptr == other.Ptr; }
50836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  bool operator!=(iterator other) const { return Ptr != other.Ptr; }
50936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall};
51036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
51136f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline EHScopeStack::iterator EHScopeStack::begin() const {
51236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  return iterator(StartOfData);
51336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
51436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
51536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline EHScopeStack::iterator EHScopeStack::end() const {
51636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  return iterator(EndOfBuffer);
51736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
51836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
51936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline void EHScopeStack::popCatch() {
52036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  assert(!empty() && "popping exception stack when not empty");
52136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
522777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHCatchScope &scope = cast<EHCatchScope>(*begin());
523777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  InnermostEHScope = scope.getEnclosingEHScope();
524777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
52536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
52636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
52736f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline void EHScopeStack::popTerminate() {
52836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  assert(!empty() && "popping exception stack when not empty");
52936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
530777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
531777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall  InnermostEHScope = scope.getEnclosingEHScope();
53236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  StartOfData += EHTerminateScope::getSize();
53336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
53436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
53536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
53636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  assert(sp.isValid() && "finding invalid savepoint");
53736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
53836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  return iterator(EndOfBuffer - sp.Size);
53936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
54036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
54136f893c1efe367f929d92c8b125f964c22ba189eJohn McCallinline EHScopeStack::stable_iterator
54236f893c1efe367f929d92c8b125f964c22ba189eJohn McCallEHScopeStack::stabilize(iterator ir) const {
54336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
54436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall  return stable_iterator(EndOfBuffer - ir.Ptr);
54536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
54636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
54736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
54836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}
54936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall
55036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#endif
551