136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//===--- CGCleanup.cpp - Bookkeeping and code emission for cleanups -------===// 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// This file contains code dealing with the IR generation for cleanups 1136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// and related information. 1236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// 1336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// A "cleanup" is a piece of code which needs to be executed whenever 1436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// control transfers out of a particular scope. This can be 1536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// conditionalized to occur only on exceptional control flow, only on 1636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// normal control flow, or both. 1736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall// 1836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall//===----------------------------------------------------------------------===// 1936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 2036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#include "CodeGenFunction.h" 2136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#include "CGCleanup.h" 2236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 2336f893c1efe367f929d92c8b125f964c22ba189eJohn McCallusing namespace clang; 2436f893c1efe367f929d92c8b125f964c22ba189eJohn McCallusing namespace CodeGen; 2536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 2636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallbool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) { 2736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (rv.isScalar()) 2836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return DominatingLLVMValue::needsSaving(rv.getScalarVal()); 2936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (rv.isAggregate()) 3036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return DominatingLLVMValue::needsSaving(rv.getAggregateAddr()); 3136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return true; 3236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 3336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 3436f893c1efe367f929d92c8b125f964c22ba189eJohn McCallDominatingValue<RValue>::saved_type 3536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallDominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) { 3636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (rv.isScalar()) { 3736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *V = rv.getScalarVal(); 3836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 3936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // These automatically dominate and don't need to be saved. 4036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!DominatingLLVMValue::needsSaving(V)) 4136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return saved_type(V, ScalarLiteral); 4236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 4336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Everything else needs an alloca. 4436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); 4536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.Builder.CreateStore(V, addr); 4636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return saved_type(addr, ScalarAddress); 4736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 4836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 4936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (rv.isComplex()) { 5036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); 512acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *ComplexTy = 527650d95a1a616ea300f37126a8dfc93dc19a662aChris Lattner llvm::StructType::get(V.first->getType(), V.second->getType(), 5336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (void*) 0); 5436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex"); 559d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); 569d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); 5736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return saved_type(addr, ComplexAddress); 5836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 5936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 6036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(rv.isAggregate()); 6136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *V = rv.getAggregateAddr(); // TODO: volatile? 6236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!DominatingLLVMValue::needsSaving(V)) 6336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return saved_type(V, AggregateLiteral); 6436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 6536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); 6636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.Builder.CreateStore(V, addr); 6736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return saved_type(addr, AggregateAddress); 6836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 6936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 7036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Given a saved r-value produced by SaveRValue, perform the code 7136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// necessary to restore it to usability at the current insertion 7236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// point. 7336f893c1efe367f929d92c8b125f964c22ba189eJohn McCallRValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) { 7436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall switch (K) { 7536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall case ScalarLiteral: 7636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return RValue::get(Value); 7736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall case ScalarAddress: 7836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return RValue::get(CGF.Builder.CreateLoad(Value)); 7936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall case AggregateLiteral: 8036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return RValue::getAggregate(Value); 8136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall case AggregateAddress: 8236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return RValue::getAggregate(CGF.Builder.CreateLoad(Value)); 839d232c884ea9872d6555df0fd7359699819bc1f1John McCall case ComplexAddress: { 849d232c884ea9872d6555df0fd7359699819bc1f1John McCall llvm::Value *real = 859d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 0)); 869d232c884ea9872d6555df0fd7359699819bc1f1John McCall llvm::Value *imag = 879d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(Value, 1)); 889d232c884ea9872d6555df0fd7359699819bc1f1John McCall return RValue::getComplex(real, imag); 899d232c884ea9872d6555df0fd7359699819bc1f1John McCall } 9036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 9136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 9236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm_unreachable("bad saved r-value kind"); 9336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 9436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 9536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Push an entry of the given size onto this protected-scope stack. 9636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallchar *EHScopeStack::allocate(size_t Size) { 9736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!StartOfBuffer) { 9836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned Capacity = 1024; 9936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall while (Capacity < Size) Capacity *= 2; 10036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfBuffer = new char[Capacity]; 10136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfData = EndOfBuffer = StartOfBuffer + Capacity; 10236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) { 10336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer; 10436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer); 10536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 10636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned NewCapacity = CurrentCapacity; 10736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall do { 10836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall NewCapacity *= 2; 10936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } while (NewCapacity < UsedCapacity + Size); 11036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 11136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall char *NewStartOfBuffer = new char[NewCapacity]; 11236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity; 11336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall char *NewStartOfData = NewEndOfBuffer - UsedCapacity; 11436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall memcpy(NewStartOfData, StartOfData, UsedCapacity); 11536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall delete [] StartOfBuffer; 11636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfBuffer = NewStartOfBuffer; 11736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EndOfBuffer = NewEndOfBuffer; 11836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfData = NewStartOfData; 11936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 12036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 12136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(StartOfBuffer + Size <= StartOfData); 12236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfData -= Size; 12336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return StartOfData; 12436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 12536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 12636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallEHScopeStack::stable_iterator 127777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallEHScopeStack::getInnermostActiveNormalCleanup() const { 128777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end(); 129777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall si != se; ) { 130777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCleanupScope &cleanup = cast<EHCleanupScope>(*find(si)); 131777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (cleanup.isActive()) return si; 132777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall si = cleanup.getEnclosingNormalCleanup(); 133777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 134777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return stable_end(); 135777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall} 136777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 137777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallEHScopeStack::stable_iterator EHScopeStack::getInnermostActiveEHScope() const { 138777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall for (stable_iterator si = getInnermostEHScope(), se = stable_end(); 139777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall si != se; ) { 140777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Skip over inactive cleanups. 141777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*find(si)); 142777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (cleanup && !cleanup->isActive()) { 143777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall si = cleanup->getEnclosingEHScope(); 144777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall continue; 14536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 146777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 147777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // All other scopes are always active. 148777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return si; 149777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 150777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 15136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return stable_end(); 15236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 15336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 15436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 15536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) { 15636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned"); 15736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size)); 15836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool IsNormalCleanup = Kind & NormalCleanup; 15936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool IsEHCleanup = Kind & EHCleanup; 16036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool IsActive = !(Kind & InactiveCleanup); 16136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope *Scope = 16236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new (Buffer) EHCleanupScope(IsNormalCleanup, 16336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall IsEHCleanup, 16436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall IsActive, 16536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Size, 16636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixups.size(), 16736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InnermostNormalCleanup, 168777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope); 16936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (IsNormalCleanup) 17036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InnermostNormalCleanup = stable_begin(); 17136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (IsEHCleanup) 172777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = stable_begin(); 17336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 17436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return Scope->getCleanupBuffer(); 17536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 17636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 17736f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid EHScopeStack::popCleanup() { 17836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!empty() && "popping exception stack when not empty"); 17936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 18036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(isa<EHCleanupScope>(*begin())); 18136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin()); 18236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); 183777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = Cleanup.getEnclosingEHScope(); 18436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall StartOfData += Cleanup.getAllocatedSize(); 18536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 18636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Destroy the cleanup. 18736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Cleanup.~EHCleanupScope(); 18836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 18936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check whether we can shrink the branch-fixups stack. 19036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!BranchFixups.empty()) { 19136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we no longer have any normal cleanups, all the fixups are 19236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // complete. 19336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!hasNormalCleanups()) 19436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixups.clear(); 19536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 19636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Otherwise we can still trim out unnecessary nulls. 19736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall else 19836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall popNullFixups(); 19936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 20036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 20136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 202777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallEHFilterScope *EHScopeStack::pushFilter(unsigned numFilters) { 203777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(getInnermostEHScope() == stable_end()); 204777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall char *buffer = allocate(EHFilterScope::getSizeForNumFilters(numFilters)); 205777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHFilterScope *filter = new (buffer) EHFilterScope(numFilters); 206777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = stable_begin(); 207777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return filter; 20836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 20936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 21036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid EHScopeStack::popFilter() { 21136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!empty() && "popping exception stack when not empty"); 21236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 213777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHFilterScope &filter = cast<EHFilterScope>(*begin()); 214777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters()); 21536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 216777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = filter.getEnclosingEHScope(); 21736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 21836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 219777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallEHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) { 220777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers)); 221777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope *scope = 222777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall new (buffer) EHCatchScope(numHandlers, InnermostEHScope); 223777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = stable_begin(); 224777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return scope; 22536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 22636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 22736f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid EHScopeStack::pushTerminate() { 22836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall char *Buffer = allocate(EHTerminateScope::getSize()); 229777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall new (Buffer) EHTerminateScope(InnermostEHScope); 230777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall InnermostEHScope = stable_begin(); 23136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 23236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 23336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Remove any 'null' fixups on the stack. However, we can't pop more 23436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// fixups than the fixup depth on the innermost normal cleanup, or 23536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// else fixups that we try to add to that cleanup will end up in the 23636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// wrong place. We *could* try to shrink fixup depths, but that's 23736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// actually a lot of work for little benefit. 23836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid EHScopeStack::popNullFixups() { 23936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // We expect this to only be called when there's still an innermost 24036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // normal cleanup; otherwise there really shouldn't be any fixups. 24136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(hasNormalCleanups()); 24236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 24336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::iterator it = find(InnermostNormalCleanup); 24436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth(); 24536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(BranchFixups.size() >= MinSize && "fixup stack out of order"); 24636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 24736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall while (BranchFixups.size() > MinSize && 24836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixups.back().Destination == 0) 24936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixups.pop_back(); 25036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 25136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 25236f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid CodeGenFunction::initFullExprCleanup() { 25336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Create a variable to decide whether the cleanup needs to be run. 25436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::AllocaInst *active 25536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall = CreateTempAlloca(Builder.getInt1Ty(), "cleanup.cond"); 25636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 25736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Initialize it to false at a site that's guaranteed to be run 25836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // before each evaluation. 2596f103ba42cb69d50005a977c5ea583984ab63fc4John McCall setBeforeOutermostConditional(Builder.getFalse(), active); 26036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 26136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Initialize it to true at the current location. 26236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.CreateStore(Builder.getTrue(), active); 26336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 26436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Set that as the active flag in the cleanup. 26536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin()); 26636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(cleanup.getActiveFlag() == 0 && "cleanup already has active flag?"); 26736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall cleanup.setActiveFlag(active); 26836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 26936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup(); 27036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup(); 27136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 27236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 273c4a1a8450a3613ef256a71b9d8305b41f79eef50John McCallvoid EHScopeStack::Cleanup::anchor() {} 27436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 27536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// All the branch fixups on the EH stack have propagated out past the 27636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// outermost normal cleanup; resolve them all by adding cases to the 27736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// given switch instruction. 27836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic void ResolveAllBranchFixups(CodeGenFunction &CGF, 27936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst *Switch, 28036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *CleanupEntry) { 28136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded; 28236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 28336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) { 28436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Skip this fixup if its destination isn't set. 28536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I); 28636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Fixup.Destination == 0) continue; 28736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 28836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If there isn't an OptimisticBranchBlock, then InitialBranch is 28936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // still pointing directly to its destination; forward it to the 29036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // appropriate cleanup entry. This is required in the specific 29136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // case of 29236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // { std::string s; goto lbl; } 29336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // lbl: 29436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // i.e. where there's an unresolved fixup inside a single cleanup 29536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // entry which we're currently popping. 29636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Fixup.OptimisticBranchBlock == 0) { 29736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new llvm::StoreInst(CGF.Builder.getInt32(Fixup.DestinationIndex), 29836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.getNormalCleanupDestSlot(), 29936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.InitialBranch); 30036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.InitialBranch->setSuccessor(0, CleanupEntry); 30136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 30236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 30336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Don't add this case to the switch statement twice. 30436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!CasesAdded.insert(Fixup.Destination)) continue; 30536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 30636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Switch->addCase(CGF.Builder.getInt32(Fixup.DestinationIndex), 30736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.Destination); 30836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 30936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 31036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.EHStack.clearFixups(); 31136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 31236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 31336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Transitions the terminator of the given exit-block of a cleanup to 31436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// be a cleanup switch. 31536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, 31636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *Block) { 31736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it's a branch, turn it into a switch whose default 31836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // destination is its original target. 31936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::TerminatorInst *Term = Block->getTerminator(); 32036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Term && "can't transition block without terminator"); 32136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 32236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { 32336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Br->isUnconditional()); 32436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::LoadInst *Load = 32536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new llvm::LoadInst(CGF.getNormalCleanupDestSlot(), "cleanup.dest", Term); 32636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst *Switch = 32736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); 32836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Br->eraseFromParent(); 32936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return Switch; 33036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 33136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return cast<llvm::SwitchInst>(Term); 33236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 33336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 33436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 33536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) { 33636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Block && "resolving a null target block"); 33736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!EHStack.getNumBranchFixups()) return; 33836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 33936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(EHStack.hasNormalCleanups() && 34036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall "branch fixups exist with no normal cleanups on stack"); 34136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 34236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SmallPtrSet<llvm::BasicBlock*, 4> ModifiedOptimisticBlocks; 34336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool ResolvedAny = false; 34436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 34536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) { 34636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Skip this fixup if its destination doesn't match. 34736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixup &Fixup = EHStack.getBranchFixup(I); 34836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Fixup.Destination != Block) continue; 34936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 35036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.Destination = 0; 35136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall ResolvedAny = true; 35236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 35336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it doesn't have an optimistic branch block, LatestBranch is 35436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // already pointing to the right place. 35536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *BranchBB = Fixup.OptimisticBranchBlock; 35636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!BranchBB) 35736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall continue; 35836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 35936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Don't process the same optimistic branch block twice. 36036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!ModifiedOptimisticBlocks.insert(BranchBB)) 36136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall continue; 36236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 36336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst *Switch = TransitionToCleanupSwitch(*this, BranchBB); 36436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 36536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Add a case to the switch. 36636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Switch->addCase(Builder.getInt32(Fixup.DestinationIndex), Block); 36736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 36836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 36936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (ResolvedAny) 37036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.popNullFixups(); 37136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 37236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 37336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Pops cleanup blocks until the given savepoint is reached. 37436f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) { 37536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Old.isValid()); 37636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 37736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall while (EHStack.stable_begin() != Old) { 37836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); 37936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 38036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // As long as Old strictly encloses the scope's enclosing normal 38136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // cleanup, we're going to emit another normal cleanup which 38236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // fallthrough can propagate through. 38336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool FallThroughIsBranchThrough = 38436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Old.strictlyEncloses(Scope.getEnclosingNormalCleanup()); 38536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 38636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall PopCleanupBlock(FallThroughIsBranchThrough); 38736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 38836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 38936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 39036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF, 39136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope) { 39236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Scope.isNormalCleanup()); 39336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *Entry = Scope.getNormalBlock(); 39436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Entry) { 39536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Entry = CGF.createBasicBlock("cleanup"); 39636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.setNormalBlock(Entry); 39736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 39836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return Entry; 39936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 40036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 40136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Attempts to reduce a cleanup's entry block to a fallthrough. This 40236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// is basically llvm::MergeBlockIntoPredecessor, except 40336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// simplified/optimized for the tighter constraints on cleanup blocks. 40436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// 40536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Returns the new block, whatever it is. 40636f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF, 40736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *Entry) { 40836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *Pred = Entry->getSinglePredecessor(); 40936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Pred) return Entry; 41036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 41136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator()); 41236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Br || Br->isConditional()) return Entry; 41336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Br->getSuccessor(0) == Entry); 41436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 41536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we were previously inserting at the end of the cleanup entry 41636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // block, we'll need to continue inserting at the end of the 41736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // predecessor. 41836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool WasInsertBlock = CGF.Builder.GetInsertBlock() == Entry; 41936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!WasInsertBlock || CGF.Builder.GetInsertPoint() == Entry->end()); 42036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 42136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Kill the branch. 42236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Br->eraseFromParent(); 42336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 42436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Replace all uses of the entry with the predecessor, in case there 42536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // are phis in the cleanup. 42636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Entry->replaceAllUsesWith(Pred); 42736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 428d36d036c819f7925b933974fa18eacc95d46049aJay Foad // Merge the blocks. 429d36d036c819f7925b933974fa18eacc95d46049aJay Foad Pred->getInstList().splice(Pred->end(), Entry->getInstList()); 430d36d036c819f7925b933974fa18eacc95d46049aJay Foad 43136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Kill the entry block. 43236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Entry->eraseFromParent(); 43336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 43436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (WasInsertBlock) 43536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.Builder.SetInsertPoint(Pred); 43636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 43736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return Pred; 43836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 43936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 44036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic void EmitCleanup(CodeGenFunction &CGF, 44136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::Cleanup *Fn, 442ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall EHScopeStack::Cleanup::Flags flags, 44336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *ActiveFlag) { 44436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // EH cleanups always occur within a terminate scope. 445ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall if (flags.isForEHCleanup()) CGF.EHStack.pushTerminate(); 44636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 44736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If there's an active flag, load it and skip the cleanup if it's 44836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // false. 44936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *ContBB = 0; 45036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (ActiveFlag) { 45136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall ContBB = CGF.createBasicBlock("cleanup.done"); 45236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action"); 45336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *IsActive 45436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active"); 45536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB); 45636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.EmitBlock(CleanupBB); 45736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 45836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 45936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Ask the cleanup to emit itself. 460ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall Fn->Emit(CGF, flags); 46136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); 46236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 46336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Emit the continuation block if there was an active flag. 46436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (ActiveFlag) 46536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGF.EmitBlock(ContBB); 46636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 46736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Leave the terminate scope. 468ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall if (flags.isForEHCleanup()) CGF.EHStack.popTerminate(); 46936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 47036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 47136f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit, 47236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *From, 47336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *To) { 47436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Exit is the exit block of a cleanup, so it always terminates in 47536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // an unconditional branch or a switch. 47636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::TerminatorInst *Term = Exit->getTerminator(); 47736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 47836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { 47936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Br->isUnconditional() && Br->getSuccessor(0) == From); 48036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Br->setSuccessor(0, To); 48136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 48236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Term); 48336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = 0, E = Switch->getNumSuccessors(); I != E; ++I) 48436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Switch->getSuccessor(I) == From) 48536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Switch->setSuccessor(I, To); 48636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 48736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 48836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 48982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// We don't need a normal entry block for the given cleanup. 49082cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// Optimistic fixup branches can cause these blocks to come into 49182cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// existence anyway; if so, destroy it. 49282cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// 49382cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// The validity of this transformation is very much specific to the 49482cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall/// exact ways in which we form branches to cleanup entries. 49582cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCallstatic void destroyOptimisticNormalEntry(CodeGenFunction &CGF, 49682cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall EHCleanupScope &scope) { 49782cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall llvm::BasicBlock *entry = scope.getNormalBlock(); 49882cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall if (!entry) return; 49982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 50082cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // Replace all the uses with unreachable. 50182cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall llvm::BasicBlock *unreachableBB = CGF.getUnreachableBlock(); 50282cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall for (llvm::BasicBlock::use_iterator 50382cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall i = entry->use_begin(), e = entry->use_end(); i != e; ) { 50482cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall llvm::Use &use = i.getUse(); 50582cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall ++i; 50682cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 50782cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall use.set(unreachableBB); 50882cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 50982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // The only uses should be fixup switches. 51082cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser()); 511ab14ae2ab16088b6a7f69eac6e152c3e9f9ea01bStepan Dyatkovskiy if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) { 51282cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // Replace the switch with a branch. 5137c02cfeb0861278c09ba05d1b92bd2a996bbe2e0Stepan Dyatkovskiy llvm::BranchInst::Create(si->case_begin().getCaseSuccessor(), si); 51482cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 51582cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // The switch operand is a load from the cleanup-dest alloca. 51682cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition()); 51782cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 51882cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // Destroy the switch. 51982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall si->eraseFromParent(); 52082cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 52182cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall // Destroy the load. 52282cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall assert(condition->getOperand(0) == CGF.NormalCleanupDest); 52382cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall assert(condition->use_empty()); 52482cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall condition->eraseFromParent(); 52582cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall } 52682cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall } 52782cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 52882cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall assert(entry->use_empty()); 52982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall delete entry; 53082cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall} 53182cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall 53236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Pops a cleanup block. If the block includes a normal cleanup, the 53336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// current insertion point is threaded through the cleanup, as are 53436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// any branch fixups on the cleanup. 53536f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { 53636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!EHStack.empty() && "cleanup stack is empty!"); 53736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!"); 53836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); 53936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups()); 54036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 54136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Remember activation information. 54236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool IsActive = Scope.isActive(); 54336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *NormalActiveFlag = 54436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() : 0; 54536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::Value *EHActiveFlag = 54636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() : 0; 54736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 54836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check whether we need an EH cleanup. This is only true if we've 54936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // generated a lazy EH cleanup block. 550777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *EHEntry = Scope.getCachedEHDispatchBlock(); 551777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(Scope.hasEHBranches() == (EHEntry != 0)); 552777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall bool RequiresEHCleanup = (EHEntry != 0); 553777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope(); 55436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 55536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check the three conditions which might require a normal cleanup: 55636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 55736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - whether there are branch fix-ups through this cleanup 55836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall unsigned FixupDepth = Scope.getFixupDepth(); 55936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth; 56036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 56136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - whether there are branch-throughs or branch-afters 56236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool HasExistingBranches = Scope.hasBranches(); 56336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 56436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - whether there's a fallthrough 56536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock(); 56636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool HasFallthrough = (FallthroughSource != 0 && IsActive); 56736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 56836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Branch-through fall-throughs leave the insertion point set to the 56936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // end of the last cleanup, which points to the current scope. The 57036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // rest of IR gen doesn't need to worry about this; it only happens 57136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // during the execution of PopCleanupBlocks(). 57236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool HasPrebranchedFallthrough = 57336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (FallthroughSource && FallthroughSource->getTerminator()); 57436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 57536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If this is a normal cleanup, then having a prebranched 57636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // fallthrough implies that the fallthrough source unconditionally 57736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // jumps here. 57836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!Scope.isNormalCleanup() || !HasPrebranchedFallthrough || 57936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (Scope.getNormalBlock() && 58036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall FallthroughSource->getTerminator()->getSuccessor(0) 58136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall == Scope.getNormalBlock())); 58236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 58336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool RequiresNormalCleanup = false; 58436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Scope.isNormalCleanup() && 58536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (HasFixups || HasExistingBranches || HasFallthrough)) { 58636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall RequiresNormalCleanup = true; 58736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 58836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 589f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // If we have a prebranched fallthrough into an inactive normal 590f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // cleanup, rewrite it so that it leads to the appropriate place. 591f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) { 592f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall llvm::BasicBlock *prebranchDest; 593f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall 594f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // If the prebranch is semantically branching through the next 595f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // cleanup, just forward it to the next block, leaving the 596f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // insertion point in the prebranched block. 59736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (FallthroughIsBranchThrough) { 598f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall EHScope &enclosing = *EHStack.find(Scope.getEnclosingNormalCleanup()); 599f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall prebranchDest = CreateNormalEntry(*this, cast<EHCleanupScope>(enclosing)); 60036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 601f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Otherwise, we need to make a new block. If the normal cleanup 602f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // isn't being used at all, we could actually reuse the normal 603f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // entry block, but this is simpler, and it avoids conflicts with 604f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // dead optimistic fixup branches. 60536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 606f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall prebranchDest = createBasicBlock("forwarded-prebranch"); 607f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall EmitBlock(prebranchDest); 60836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 609f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall 610f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall llvm::BasicBlock *normalEntry = Scope.getNormalBlock(); 611f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall assert(normalEntry && !normalEntry->use_empty()); 612f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall 613f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall ForwardPrebranchedFallthrough(FallthroughSource, 614f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall normalEntry, prebranchDest); 61536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 61636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 61736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we don't need the cleanup at all, we're done. 61836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!RequiresNormalCleanup && !RequiresEHCleanup) { 61982cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall destroyOptimisticNormalEntry(*this, Scope); 62036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.popCleanup(); // safe because there are no fixups 62136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(EHStack.getNumBranchFixups() == 0 || 62236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.hasNormalCleanups()); 62336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return; 62436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 62536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 62636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Copy the cleanup emission data out. Note that SmallVector 62736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // guarantees maximal alignment for its buffer regardless of its 62836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // type parameter. 6295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<char, 8*sizeof(void*)> CleanupBuffer; 63036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CleanupBuffer.reserve(Scope.getCleanupSize()); 63136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall memcpy(CleanupBuffer.data(), 63236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.getCleanupBuffer(), Scope.getCleanupSize()); 63336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CleanupBuffer.set_size(Scope.getCleanupSize()); 63436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::Cleanup *Fn = 63536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall reinterpret_cast<EHScopeStack::Cleanup*>(CleanupBuffer.data()); 63636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 637777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScopeStack::Cleanup::Flags cleanupFlags; 638777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (Scope.isNormalCleanup()) 639777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall cleanupFlags.setIsNormalCleanupKind(); 640777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (Scope.isEHCleanup()) 641777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall cleanupFlags.setIsEHCleanupKind(); 64236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 64336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!RequiresNormalCleanup) { 64482cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall destroyOptimisticNormalEntry(*this, Scope); 64536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.popCleanup(); 64636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 64736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we have a fallthrough and no other need for the cleanup, 64836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // emit it directly. 64936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (HasFallthrough && !HasPrebranchedFallthrough && 65036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall !HasFixups && !HasExistingBranches) { 65136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 65282cd2e5c15aa909ec9613c4228ab69e07f1c6f7aJohn McCall destroyOptimisticNormalEntry(*this, Scope); 65336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.popCleanup(); 65436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 655ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); 65636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 65736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Otherwise, the best approach is to thread everything through 65836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // the cleanup block and then try to clean up after ourselves. 65936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 66036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Force the entry block to exist. 66136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *NormalEntry = CreateNormalEntry(*this, Scope); 66236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 66336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // I. Set up the fallthrough edge in. 66436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 665e7d002041dc60521f237b4219fd4167d1fe67aa7John McCall CGBuilderTy::InsertPoint savedInactiveFallthroughIP; 666f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall 66736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If there's a fallthrough, we need to store the cleanup 66836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // destination index. For fall-throughs this is always zero. 66936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (HasFallthrough) { 67036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!HasPrebranchedFallthrough) 67136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.CreateStore(Builder.getInt32(0), getNormalCleanupDestSlot()); 67236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 673f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Otherwise, save and clear the IP if we don't have fallthrough 674f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // because the cleanup is inactive. 67536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else if (FallthroughSource) { 67636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!IsActive && "source without fallthrough for active cleanup"); 677f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall savedInactiveFallthroughIP = Builder.saveAndClearIP(); 67836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 67936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 68036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // II. Emit the entry block. This implicitly branches to it if 68136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // we have fallthrough. All the fixups and existing branches 68236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // should already be branched to it. 68336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EmitBlock(NormalEntry); 68436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 68536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // III. Figure out where we're going and build the cleanup 68636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // epilogue. 68736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 68836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall bool HasEnclosingCleanups = 68936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (Scope.getEnclosingNormalCleanup() != EHStack.stable_end()); 69036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 69136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Compute the branch-through dest if we need it: 69236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if there are branch-throughs threaded through the scope 69336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if fall-through is a branch-through 69436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if there are fixups that will be optimistically forwarded 69536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // to the enclosing cleanup 69636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *BranchThroughDest = 0; 69736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (Scope.hasBranchThroughs() || 69836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (FallthroughSource && FallthroughIsBranchThrough) || 69936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (HasFixups && HasEnclosingCleanups)) { 70036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(HasEnclosingCleanups); 70136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup()); 70236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S)); 70336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 70436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 70536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *FallthroughDest = 0; 7065f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<llvm::Instruction*, 2> InstsToAppend; 70736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 70836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If there's exactly one branch-after and no other threads, 70936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // we can route it without a switch. 71036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough && 71136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.getNumBranchAfters() == 1) { 71236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!BranchThroughDest || !IsActive); 71336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 71436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // TODO: clean up the possibly dead stores to the cleanup dest slot. 71536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); 71636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter)); 71736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 71836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Build a switch-out if we need it: 71936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if there are branch-afters threaded through the scope 72036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if fall-through is a branch-after 72136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - if there are fixups that have nowhere left to go and 72236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // so must be immediately resolved 72336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else if (Scope.getNumBranchAfters() || 72436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (HasFallthrough && !FallthroughIsBranchThrough) || 72536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (HasFixups && !HasEnclosingCleanups)) { 72636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 72736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *Default = 72836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall (BranchThroughDest ? BranchThroughDest : getUnreachableBlock()); 72936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 73036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // TODO: base this on the number of branch-afters and fixups 73136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall const unsigned SwitchCapacity = 10; 73236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 73336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::LoadInst *Load = 73436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new llvm::LoadInst(getNormalCleanupDestSlot(), "cleanup.dest"); 73536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst *Switch = 73636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::SwitchInst::Create(Load, Default, SwitchCapacity); 73736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 73836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InstsToAppend.push_back(Load); 73936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InstsToAppend.push_back(Switch); 74036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 74136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Branch-after fallthrough. 74236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (FallthroughSource && !FallthroughIsBranchThrough) { 74336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall FallthroughDest = createBasicBlock("cleanup.cont"); 74436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (HasFallthrough) 74536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Switch->addCase(Builder.getInt32(0), FallthroughDest); 74636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 74736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 74836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = 0, E = Scope.getNumBranchAfters(); I != E; ++I) { 74936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Switch->addCase(Scope.getBranchAfterIndex(I), 75036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.getBranchAfterBlock(I)); 75136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 75236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 75336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If there aren't any enclosing cleanups, we can resolve all 75436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // the fixups now. 75536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (HasFixups && !HasEnclosingCleanups) 75636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall ResolveAllBranchFixups(*this, Switch, NormalEntry); 75736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 75836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // We should always have a branch-through destination in this case. 75936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(BranchThroughDest); 76036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest)); 76136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 76236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 76336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // IV. Pop the cleanup and emit it. 76436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHStack.popCleanup(); 76536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(EHStack.hasNormalCleanups() == HasEnclosingCleanups); 76636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 767ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); 76836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 76936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Append the prepared cleanup prologue from above. 77036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *NormalExit = Builder.GetInsertBlock(); 77136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = 0, E = InstsToAppend.size(); I != E; ++I) 77236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall NormalExit->getInstList().push_back(InstsToAppend[I]); 77336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 77436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Optimistically hope that any fixups will continue falling through. 77536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); 77636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I < E; ++I) { 777d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall BranchFixup &Fixup = EHStack.getBranchFixup(I); 77836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Fixup.Destination) continue; 77936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Fixup.OptimisticBranchBlock) { 78036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new llvm::StoreInst(Builder.getInt32(Fixup.DestinationIndex), 78136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall getNormalCleanupDestSlot(), 78236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.InitialBranch); 78336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.InitialBranch->setSuccessor(0, NormalEntry); 78436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 78536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.OptimisticBranchBlock = NormalExit; 78636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 78736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 78836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // V. Set up the fallthrough edge out. 78936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 790f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Case 1: a fallthrough source exists but doesn't branch to the 791f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // cleanup because the cleanup is inactive. 79236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!HasFallthrough && FallthroughSource) { 793f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Prebranched fallthrough was forwarded earlier. 794f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Non-prebranched fallthrough doesn't need to be forwarded. 795f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall // Either way, all we need to do is restore the IP we cleared before. 79636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!IsActive); 797f66a3ea8595d44843f43b8c4b0825b1f8ceeda78John McCall Builder.restoreIP(savedInactiveFallthroughIP); 79836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 79936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Case 2: a fallthrough source exists and should branch to the 80036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // cleanup, but we're not supposed to branch through to the next 80136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // cleanup. 80236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else if (HasFallthrough && FallthroughDest) { 80336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!FallthroughIsBranchThrough); 80436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EmitBlock(FallthroughDest); 80536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 80636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Case 3: a fallthrough source exists and should branch to the 80736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // cleanup and then through to the next. 80836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else if (HasFallthrough) { 80936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Everything is already set up for this. 81036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 81136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Case 4: no fallthrough source exists. 81236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } else { 81336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.ClearInsertionPoint(); 81436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 81536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 81636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // VI. Assorted cleaning. 81736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 81836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check whether we can merge NormalEntry into a single predecessor. 81936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // This might invalidate (non-IR) pointers to NormalEntry. 82036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BasicBlock *NewNormalEntry = 82136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall SimplifyCleanupEntry(*this, NormalEntry); 82236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 82336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it did invalidate those pointers, and NormalEntry was the same 82436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // as NormalExit, go back and patch up the fixups. 82536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (NewNormalEntry != NormalEntry && NormalEntry == NormalExit) 82636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); 82736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I < E; ++I) 828d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall EHStack.getBranchFixup(I).OptimisticBranchBlock = NewNormalEntry; 82936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 83036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 83136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 83236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0); 83336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 83436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Emit the EH cleanup if required. 83536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (RequiresEHCleanup) { 83636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 83736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 83836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EmitBlock(EHEntry); 839ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall 840ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman // We only actually emit the cleanup code if the cleanup is either 841ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman // active or was used before it was deactivated. 842ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman if (EHActiveFlag || IsActive) { 843ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman cleanupFlags.setIsForEHCleanup(); 844ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); 845ea66f9f9e17d619d617885e26adc1530cec7c0fdEli Friedman } 84636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 847777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall Builder.CreateBr(getEHDispatchBlock(EHParent)); 84836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 84936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.restoreIP(SavedIP); 85036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 85136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall SimplifyCleanupEntry(*this, EHEntry); 85236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 85336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 85436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 855b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner/// isObviouslyBranchWithoutCleanups - Return true if a branch to the 856b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner/// specified destination obviously has no cleanups to run. 'false' is always 857b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner/// a conservatively correct answer for this method. 858b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattnerbool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const { 859b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) 860b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner && "stale jump destination"); 861b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner 862b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner // Calculate the innermost active normal cleanup. 863b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner EHScopeStack::stable_iterator TopCleanup = 864b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner EHStack.getInnermostActiveNormalCleanup(); 865b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner 866b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner // If we're not in an active normal cleanup scope, or if the 867b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner // destination scope is within the innermost active normal cleanup 868b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner // scope, we don't need to worry about fixups. 869b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner if (TopCleanup == EHStack.stable_end() || 870b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner TopCleanup.encloses(Dest.getScopeDepth())) // works for invalid 871b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner return true; 872b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner 873b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner // Otherwise, we might need some cleanups. 874b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner return false; 875b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner} 876b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner 877b11f9198111796ada02b57f62cdea92134fde9f7Chris Lattner 87836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Terminate the current block by emitting a branch which might leave 87936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// the current cleanup-protected scope. The target scope may not yet 88036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// be known, in which case this will require a fixup. 88136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// 88236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// As a side-effect, this method clears the insertion point. 88336f893c1efe367f929d92c8b125f964c22ba189eJohn McCallvoid CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { 88427f8d703e65095ca9c8c5d08a5a835b5510a730dJohn McCall assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) 88536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall && "stale jump destination"); 88636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 88736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!HaveInsertPoint()) 88836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return; 88936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 89036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Create the branch. 89136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock()); 89236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 89336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Calculate the innermost active normal cleanup. 89436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::stable_iterator 89536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall TopCleanup = EHStack.getInnermostActiveNormalCleanup(); 89636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 89736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we're not in an active normal cleanup scope, or if the 89836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // destination scope is within the innermost active normal cleanup 89936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // scope, we don't need to worry about fixups. 90036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (TopCleanup == EHStack.stable_end() || 90136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall TopCleanup.encloses(Dest.getScopeDepth())) { // works for invalid 90236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.ClearInsertionPoint(); 90336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return; 90436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 90536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 90636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we can't resolve the destination cleanup scope, just add this 90736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // to the current cleanup scope as a branch fixup. 90836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Dest.getScopeDepth().isValid()) { 90936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BranchFixup &Fixup = EHStack.addBranchFixup(); 91036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.Destination = Dest.getBlock(); 91136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.DestinationIndex = Dest.getDestIndex(); 91236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.InitialBranch = BI; 91336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Fixup.OptimisticBranchBlock = 0; 91436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 91536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.ClearInsertionPoint(); 91636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return; 91736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 91836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 91936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Otherwise, thread through all the normal cleanups in scope. 92036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 92136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Store the index at the start. 92236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); 92336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall new llvm::StoreInst(Index, getNormalCleanupDestSlot(), BI); 92436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 92536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Adjust BI to point to the first cleanup block. 92636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall { 92736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = 92836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall cast<EHCleanupScope>(*EHStack.find(TopCleanup)); 92936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall BI->setSuccessor(0, CreateNormalEntry(*this, Scope)); 93036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 93136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 93236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Add this destination to all the scopes involved. 93336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::stable_iterator I = TopCleanup; 93436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::stable_iterator E = Dest.getScopeDepth(); 93536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (E.strictlyEncloses(I)) { 93636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall while (true) { 93736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I)); 93836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Scope.isNormalCleanup()); 93936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I = Scope.getEnclosingNormalCleanup(); 94036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 94136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If this is the last cleanup we're propagating through, tell it 94236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // that there's a resolved jump moving through it. 94336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!E.strictlyEncloses(I)) { 94436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.addBranchAfter(Index, Dest.getBlock()); 94536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall break; 94636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 94736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 94836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Otherwise, tell the scope that there's a jump propoagating 94936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // through it. If this isn't new information, all the rest of 95036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // the work has been done before. 95136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!Scope.addBranchThrough(Dest.getBlock())) 95236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall break; 95336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 95436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 95536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 95636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.ClearInsertionPoint(); 95736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 95836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 95936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic bool IsUsedAsNormalCleanup(EHScopeStack &EHStack, 96036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::stable_iterator C) { 96136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we needed a normal block for any reason, that counts. 96236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (cast<EHCleanupScope>(*EHStack.find(C)).getNormalBlock()) 96336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return true; 96436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 96536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check whether any enclosed cleanups were needed. 96636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (EHScopeStack::stable_iterator 96736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I = EHStack.getInnermostNormalCleanup(); 96836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I != C; ) { 96936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(C.strictlyEncloses(I)); 97036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I)); 97136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (S.getNormalBlock()) return true; 97236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall I = S.getEnclosingNormalCleanup(); 97336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 97436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 97536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return false; 97636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 97736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 97836f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic bool IsUsedAsEHCleanup(EHScopeStack &EHStack, 979777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScopeStack::stable_iterator cleanup) { 98036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If we needed an EH block for any reason, that counts. 981777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (EHStack.find(cleanup)->hasEHBranches()) 98236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return true; 98336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 98436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Check whether any enclosed cleanups were needed. 98536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall for (EHScopeStack::stable_iterator 986777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall i = EHStack.getInnermostEHScope(); i != cleanup; ) { 987777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(cleanup.strictlyEncloses(i)); 988777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 989777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScope &scope = *EHStack.find(i); 990777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (scope.hasEHBranches()) 991777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return true; 992777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 993777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall i = scope.getEnclosingEHScope(); 99436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 99536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 99636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return false; 99736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 99836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 99936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallenum ForActivation_t { 100036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall ForActivation, 100136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall ForDeactivation 100236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall}; 100336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 100436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// The given cleanup block is changing activation state. Configure a 100536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// cleanup variable if necessary. 100636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// 100736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// It would be good if we had some way of determining if there were 100836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// extra uses *after* the change-over point. 100936f893c1efe367f929d92c8b125f964c22ba189eJohn McCallstatic void SetupCleanupBlockActivation(CodeGenFunction &CGF, 101036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHScopeStack::stable_iterator C, 10116f103ba42cb69d50005a977c5ea583984ab63fc4John McCall ForActivation_t kind, 10126f103ba42cb69d50005a977c5ea583984ab63fc4John McCall llvm::Instruction *dominatingIP) { 101336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C)); 101436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 1015b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // We always need the flag if we're activating the cleanup in a 1016b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // conditional context, because we have to assume that the current 1017b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall // location doesn't necessarily dominate the cleanup's code. 1018b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall bool isActivatedInConditional = 10196f103ba42cb69d50005a977c5ea583984ab63fc4John McCall (kind == ForActivation && CGF.isInConditionalBranch()); 1020b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall 1021b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall bool needFlag = false; 102236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 102336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Calculate whether the cleanup was used: 102436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 102536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - as a normal cleanup 1026b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall if (Scope.isNormalCleanup() && 1027b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall (isActivatedInConditional || IsUsedAsNormalCleanup(CGF.EHStack, C))) { 102836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.setTestFlagInNormalCleanup(); 1029b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall needFlag = true; 103036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 103136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 103236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // - as an EH cleanup 1033b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall if (Scope.isEHCleanup() && 1034b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall (isActivatedInConditional || IsUsedAsEHCleanup(CGF.EHStack, C))) { 103536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.setTestFlagInEHCleanup(); 1036b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall needFlag = true; 103736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 103836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 103936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it hasn't yet been used as either, we're done. 1040b99785bdd1cc9ce1ba4f94eeb871faba1a22e95fJohn McCall if (!needFlag) return; 104136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 10426f103ba42cb69d50005a977c5ea583984ab63fc4John McCall llvm::AllocaInst *var = Scope.getActiveFlag(); 10436f103ba42cb69d50005a977c5ea583984ab63fc4John McCall if (!var) { 10446f103ba42cb69d50005a977c5ea583984ab63fc4John McCall var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive"); 10456f103ba42cb69d50005a977c5ea583984ab63fc4John McCall Scope.setActiveFlag(var); 10466f103ba42cb69d50005a977c5ea583984ab63fc4John McCall 10476f103ba42cb69d50005a977c5ea583984ab63fc4John McCall assert(dominatingIP && "no existing variable and no dominating IP!"); 104836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 104936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Initialize to true or false depending on whether it was 105036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // active up to this point. 10516f103ba42cb69d50005a977c5ea583984ab63fc4John McCall llvm::Value *value = CGF.Builder.getInt1(kind == ForDeactivation); 10526f103ba42cb69d50005a977c5ea583984ab63fc4John McCall 10536f103ba42cb69d50005a977c5ea583984ab63fc4John McCall // If we're in a conditional block, ignore the dominating IP and 10546f103ba42cb69d50005a977c5ea583984ab63fc4John McCall // use the outermost conditional branch. 10556f103ba42cb69d50005a977c5ea583984ab63fc4John McCall if (CGF.isInConditionalBranch()) { 10566f103ba42cb69d50005a977c5ea583984ab63fc4John McCall CGF.setBeforeOutermostConditional(value, var); 10576f103ba42cb69d50005a977c5ea583984ab63fc4John McCall } else { 10586f103ba42cb69d50005a977c5ea583984ab63fc4John McCall new llvm::StoreInst(value, var, dominatingIP); 10596f103ba42cb69d50005a977c5ea583984ab63fc4John McCall } 106036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 106136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 10626f103ba42cb69d50005a977c5ea583984ab63fc4John McCall CGF.Builder.CreateStore(CGF.Builder.getInt1(kind == ForActivation), var); 106336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 106436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 106536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Activate a cleanup that was created in an inactivated state. 10666f103ba42cb69d50005a977c5ea583984ab63fc4John McCallvoid CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C, 10676f103ba42cb69d50005a977c5ea583984ab63fc4John McCall llvm::Instruction *dominatingIP) { 106836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(C != EHStack.stable_end() && "activating bottom of stack?"); 106936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); 107036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(!Scope.isActive() && "double activation"); 107136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 10726f103ba42cb69d50005a977c5ea583984ab63fc4John McCall SetupCleanupBlockActivation(*this, C, ForActivation, dominatingIP); 107336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 107436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.setActive(true); 107536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 107636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 107736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall/// Deactive a cleanup that was created in an active state. 10786f103ba42cb69d50005a977c5ea583984ab63fc4John McCallvoid CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, 10796f103ba42cb69d50005a977c5ea583984ab63fc4John McCall llvm::Instruction *dominatingIP) { 108036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(C != EHStack.stable_end() && "deactivating bottom of stack?"); 108136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); 108236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall assert(Scope.isActive() && "double deactivation"); 108336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 108436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it's the top of the stack, just pop it. 108536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (C == EHStack.stable_begin()) { 108636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // If it's a normal cleanup, we need to pretend that the 108736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // fallthrough is unreachable. 108836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 108936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall PopCleanupBlock(); 109036f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Builder.restoreIP(SavedIP); 109136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return; 109236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall } 109336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 109436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall // Otherwise, follow the general case. 10956f103ba42cb69d50005a977c5ea583984ab63fc4John McCall SetupCleanupBlockActivation(*this, C, ForDeactivation, dominatingIP); 109636f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 109736f893c1efe367f929d92c8b125f964c22ba189eJohn McCall Scope.setActive(false); 109836f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 109936f893c1efe367f929d92c8b125f964c22ba189eJohn McCall 110036f893c1efe367f929d92c8b125f964c22ba189eJohn McCallllvm::Value *CodeGenFunction::getNormalCleanupDestSlot() { 110136f893c1efe367f929d92c8b125f964c22ba189eJohn McCall if (!NormalCleanupDest) 110236f893c1efe367f929d92c8b125f964c22ba189eJohn McCall NormalCleanupDest = 110336f893c1efe367f929d92c8b125f964c22ba189eJohn McCall CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); 110436f893c1efe367f929d92c8b125f964c22ba189eJohn McCall return NormalCleanupDest; 110536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall} 110686811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne 110786811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne/// Emits all the code to cause the given temporary to be cleaned up. 110886811609d9353e3aed198045d56e790eb3b6118cPeter Collingbournevoid CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, 110986811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne QualType TempType, 111086811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne llvm::Value *Ptr) { 1111516bbd42e62d709013824d6fb8445a0cfda3129aPeter Collingbourne pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, 111286811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne /*useEHCleanup*/ true); 111386811609d9353e3aed198045d56e790eb3b6118cPeter Collingbourne} 1114