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