CGException.cpp revision fcd5c0c62ef3d86ecd991753bb43c88c861470e7
1756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===// 2756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 3756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// The LLVM Compiler Infrastructure 4756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 5756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// This file is distributed under the University of Illinois Open Source 6756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// License. See LICENSE.TXT for details. 7756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 8756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===----------------------------------------------------------------------===// 9756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 10756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// This contains code dealing with C++ exception related code generation. 11756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 12756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===----------------------------------------------------------------------===// 13756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson 142bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump#include "clang/AST/StmtCXX.h" 152bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 162bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump#include "llvm/Intrinsics.h" 17f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall#include "llvm/Support/CallSite.h" 182bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 19756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson#include "CodeGenFunction.h" 20f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall#include "CGException.h" 21f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 22756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlssonusing namespace clang; 23756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlssonusing namespace CodeGen; 24756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson 25f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Push an entry of the given size onto this protected-scope stack. 26f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallchar *EHScopeStack::allocate(size_t Size) { 27f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!StartOfBuffer) { 28f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned Capacity = 1024; 29f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall while (Capacity < Size) Capacity *= 2; 30f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfBuffer = new char[Capacity]; 31f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfData = EndOfBuffer = StartOfBuffer + Capacity; 32f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) { 33f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer; 34f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer); 35f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 36f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NewCapacity = CurrentCapacity; 37f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall do { 38f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NewCapacity *= 2; 39f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } while (NewCapacity < UsedCapacity + Size); 40f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 41f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *NewStartOfBuffer = new char[NewCapacity]; 42f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity; 43f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *NewStartOfData = NewEndOfBuffer - UsedCapacity; 44f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall memcpy(NewStartOfData, StartOfData, UsedCapacity); 45f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall delete [] StartOfBuffer; 46f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfBuffer = NewStartOfBuffer; 47f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EndOfBuffer = NewEndOfBuffer; 48f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfData = NewStartOfData; 49f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 50f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 51f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(StartOfBuffer + Size <= StartOfData); 52f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfData -= Size; 53f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return StartOfData; 54f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 55f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 56f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallEHScopeStack::stable_iterator 57f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallEHScopeStack::getEnclosingEHCleanup(iterator it) const { 58f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(it != end()); 59f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall do { 60f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (isa<EHCleanupScope>(*it)) { 61f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (cast<EHCleanupScope>(*it).isEHCleanup()) 62f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return stabilize(it); 63f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return cast<EHCleanupScope>(*it).getEnclosingEHCleanup(); 64f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 65da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (isa<EHLazyCleanupScope>(*it)) { 66da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (cast<EHLazyCleanupScope>(*it).isEHCleanup()) 67da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return stabilize(it); 68da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return cast<EHLazyCleanupScope>(*it).getEnclosingEHCleanup(); 69da65ea86482bc116906edfb9ba1d7124f76cc867John McCall } 70f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ++it; 71f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } while (it != end()); 72f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return stable_end(); 73f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 74f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 75f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 76da65ea86482bc116906edfb9ba1d7124f76cc867John McCallvoid *EHScopeStack::pushLazyCleanup(CleanupKind Kind, size_t Size) { 77da65ea86482bc116906edfb9ba1d7124f76cc867John McCall assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned"); 78da65ea86482bc116906edfb9ba1d7124f76cc867John McCall char *Buffer = allocate(EHLazyCleanupScope::getSizeForCleanupSize(Size)); 79da65ea86482bc116906edfb9ba1d7124f76cc867John McCall bool IsNormalCleanup = Kind != EHCleanup; 80da65ea86482bc116906edfb9ba1d7124f76cc867John McCall bool IsEHCleanup = Kind != NormalCleanup; 81da65ea86482bc116906edfb9ba1d7124f76cc867John McCall EHLazyCleanupScope *Scope = 82da65ea86482bc116906edfb9ba1d7124f76cc867John McCall new (Buffer) EHLazyCleanupScope(IsNormalCleanup, 83da65ea86482bc116906edfb9ba1d7124f76cc867John McCall IsEHCleanup, 84da65ea86482bc116906edfb9ba1d7124f76cc867John McCall Size, 85da65ea86482bc116906edfb9ba1d7124f76cc867John McCall BranchFixups.size(), 86da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostNormalCleanup, 87da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostEHCleanup); 88da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (IsNormalCleanup) 89da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostNormalCleanup = stable_begin(); 90da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (IsEHCleanup) 91da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostEHCleanup = stable_begin(); 92da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 93da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return Scope->getCleanupBuffer(); 94da65ea86482bc116906edfb9ba1d7124f76cc867John McCall} 95da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 96f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::pushCleanup(llvm::BasicBlock *NormalEntry, 97f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *NormalExit, 98f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *EHEntry, 99f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *EHExit) { 100f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *Buffer = allocate(EHCleanupScope::getSize()); 101f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall new (Buffer) EHCleanupScope(BranchFixups.size(), 102f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall InnermostNormalCleanup, 103f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall InnermostEHCleanup, 104f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalEntry, NormalExit, EHEntry, EHExit); 105f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (NormalEntry) 106f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall InnermostNormalCleanup = stable_begin(); 107f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EHEntry) 108f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall InnermostEHCleanup = stable_begin(); 109f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 110f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 111f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::popCleanup() { 112f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!empty() && "popping exception stack when not empty"); 113f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 114da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (isa<EHLazyCleanupScope>(*begin())) { 115da65ea86482bc116906edfb9ba1d7124f76cc867John McCall EHLazyCleanupScope &Cleanup = cast<EHLazyCleanupScope>(*begin()); 116da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); 117da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostEHCleanup = Cleanup.getEnclosingEHCleanup(); 118da65ea86482bc116906edfb9ba1d7124f76cc867John McCall StartOfData += Cleanup.getAllocatedSize(); 119da65ea86482bc116906edfb9ba1d7124f76cc867John McCall } else { 120da65ea86482bc116906edfb9ba1d7124f76cc867John McCall assert(isa<EHCleanupScope>(*begin())); 121da65ea86482bc116906edfb9ba1d7124f76cc867John McCall EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin()); 122da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); 123da65ea86482bc116906edfb9ba1d7124f76cc867John McCall InnermostEHCleanup = Cleanup.getEnclosingEHCleanup(); 124da65ea86482bc116906edfb9ba1d7124f76cc867John McCall StartOfData += EHCleanupScope::getSize(); 125da65ea86482bc116906edfb9ba1d7124f76cc867John McCall } 126f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 127f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check whether we can shrink the branch-fixups stack. 128f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!BranchFixups.empty()) { 129f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we no longer have any normal cleanups, all the fixups are 130f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // complete. 131f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!hasNormalCleanups()) 132f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BranchFixups.clear(); 133f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 134f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise we can still trim out unnecessary nulls. 135f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 136f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall popNullFixups(); 137f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 138f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 139f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 140f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallEHFilterScope *EHScopeStack::pushFilter(unsigned NumFilters) { 141f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *Buffer = allocate(EHFilterScope::getSizeForNumFilters(NumFilters)); 142f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchDepth++; 143f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return new (Buffer) EHFilterScope(NumFilters); 144f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 145f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 146f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::popFilter() { 147f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!empty() && "popping exception stack when not empty"); 148f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 149f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHFilterScope &Filter = cast<EHFilterScope>(*begin()); 150f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters()); 151f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 152f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(CatchDepth > 0 && "mismatched filter push/pop"); 153f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchDepth--; 154f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 155f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 156f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallEHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) { 157f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers)); 158f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchDepth++; 159f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return new (Buffer) EHCatchScope(NumHandlers); 160f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 161f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 162f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::pushTerminate() { 163f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall char *Buffer = allocate(EHTerminateScope::getSize()); 164f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchDepth++; 165f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall new (Buffer) EHTerminateScope(); 166f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 167f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 168f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Remove any 'null' fixups on the stack. However, we can't pop more 169f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// fixups than the fixup depth on the innermost normal cleanup, or 170f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// else fixups that we try to add to that cleanup will end up in the 171f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// wrong place. We *could* try to shrink fixup depths, but that's 172f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// actually a lot of work for little benefit. 173f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::popNullFixups() { 174f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We expect this to only be called when there's still an innermost 175f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // normal cleanup; otherwise there really shouldn't be any fixups. 176f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(hasNormalCleanups()); 177f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 178f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHScopeStack::iterator it = find(InnermostNormalCleanup); 179da65ea86482bc116906edfb9ba1d7124f76cc867John McCall unsigned MinSize; 180da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (isa<EHCleanupScope>(*it)) 181da65ea86482bc116906edfb9ba1d7124f76cc867John McCall MinSize = cast<EHCleanupScope>(*it).getFixupDepth(); 182da65ea86482bc116906edfb9ba1d7124f76cc867John McCall else 183da65ea86482bc116906edfb9ba1d7124f76cc867John McCall MinSize = cast<EHLazyCleanupScope>(*it).getFixupDepth(); 184f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(BranchFixups.size() >= MinSize && "fixup stack out of order"); 185f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 186f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall while (BranchFixups.size() > MinSize && 187f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BranchFixups.back().Destination == 0) 188f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BranchFixups.pop_back(); 189f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 190f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 191f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid EHScopeStack::resolveBranchFixups(llvm::BasicBlock *Dest) { 192f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(Dest && "null block passed to resolveBranchFixups"); 193f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 194f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (BranchFixups.empty()) return; 195f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(hasNormalCleanups() && 196f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "branch fixups exist with no normal cleanups on stack"); 197f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 198f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0, E = BranchFixups.size(); I != E; ++I) 199f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (BranchFixups[I].Destination == Dest) 200f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BranchFixups[I].Destination = 0; 201f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 202f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall popNullFixups(); 203f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 204f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 205d3379292f90e1381d3236c68891bb725b02464b6Anders Carlssonstatic llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { 206d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // void *__cxa_allocate_exception(size_t thrown_size); 207d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 208d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson std::vector<const llvm::Type*> Args(1, SizeTy); 2098755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2108755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 211d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()), 212d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson Args, false); 2138755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 214d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); 215d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson} 216d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 21799533834ba8f3658559f334e68a518ebb6388ceaMike Stumpstatic llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) { 21899533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_free_exception(void *thrown_exception); 21999533834ba8f3658559f334e68a518ebb6388ceaMike Stump const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 22099533834ba8f3658559f334e68a518ebb6388ceaMike Stump std::vector<const llvm::Type*> Args(1, Int8PtrTy); 2218755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2228755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 22399533834ba8f3658559f334e68a518ebb6388ceaMike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 22499533834ba8f3658559f334e68a518ebb6388ceaMike Stump Args, false); 2258755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 22699533834ba8f3658559f334e68a518ebb6388ceaMike Stump return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); 22799533834ba8f3658559f334e68a518ebb6388ceaMike Stump} 22899533834ba8f3658559f334e68a518ebb6388ceaMike Stump 229d3379292f90e1381d3236c68891bb725b02464b6Anders Carlssonstatic llvm::Constant *getThrowFn(CodeGenFunction &CGF) { 2308755ec336108839b9621c3b18f0e175f8a3b671cMike Stump // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, 23199533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void (*dest) (void *)); 232d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 233d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 234d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson std::vector<const llvm::Type*> Args(3, Int8PtrTy); 2358755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2368755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 237b4eea691866a3fa75722da9eba735c44f140398aMike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 238b4eea691866a3fa75722da9eba735c44f140398aMike Stump Args, false); 2398755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 240d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); 241d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson} 242d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 243b4eea691866a3fa75722da9eba735c44f140398aMike Stumpstatic llvm::Constant *getReThrowFn(CodeGenFunction &CGF) { 24499533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_rethrow(); 245b4eea691866a3fa75722da9eba735c44f140398aMike Stump 2468755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 247b4eea691866a3fa75722da9eba735c44f140398aMike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 2488755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 249b4eea691866a3fa75722da9eba735c44f140398aMike Stump return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); 250b4eea691866a3fa75722da9eba735c44f140398aMike Stump} 251b4eea691866a3fa75722da9eba735c44f140398aMike Stump 252f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) { 253f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void *__cxa_get_exception_ptr(void*); 254f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 255f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall std::vector<const llvm::Type*> Args(1, Int8PtrTy); 256f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 257f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::FunctionType *FTy = 258f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::FunctionType::get(Int8PtrTy, Args, false); 259f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 260f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); 261f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 262f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 2632bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stumpstatic llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) { 264f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void *__cxa_begin_catch(void*); 2652bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 2662bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 2672bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump std::vector<const llvm::Type*> Args(1, Int8PtrTy); 2688755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2698755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 2700f590be3808365e851352543faa6acbece50b686Mike Stump llvm::FunctionType::get(Int8PtrTy, Args, false); 2718755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2722bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); 2732bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump} 2742bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 2752bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stumpstatic llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) { 27699533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_end_catch(); 2772bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 2788755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 2792bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 2808755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2812bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); 2822bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump} 2832bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 284cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stumpstatic llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { 285cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump // void __cxa_call_unexepcted(void *thrown_exception); 286cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 287cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 288cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump std::vector<const llvm::Type*> Args(1, Int8PtrTy); 2898755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 2908755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 291cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 292cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump Args, false); 2938755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 294cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); 295cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 296cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 29786a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregorllvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { 29886a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 2990f590be3808365e851352543faa6acbece50b686Mike Stump std::vector<const llvm::Type*> Args(1, Int8PtrTy); 3008755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 3018755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 30286a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args, 3030f590be3808365e851352543faa6acbece50b686Mike Stump false); 3048755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 30586a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor if (CGM.getLangOptions().SjLjExceptions) 30686a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); 30786a3a03667bdb0dcab7e6a2877dfd234b07a6d43Douglas Gregor return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); 3080f590be3808365e851352543faa6acbece50b686Mike Stump} 3090f590be3808365e851352543faa6acbece50b686Mike Stump 31099533834ba8f3658559f334e68a518ebb6388ceaMike Stumpstatic llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { 31199533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __terminate(); 31299533834ba8f3658559f334e68a518ebb6388ceaMike Stump 3138755ec336108839b9621c3b18f0e175f8a3b671cMike Stump const llvm::FunctionType *FTy = 31499533834ba8f3658559f334e68a518ebb6388ceaMike Stump llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 3158755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 31679a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall return CGF.CGM.CreateRuntimeFunction(FTy, 31779a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort"); 31879a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall} 31979a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall 320f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic const char *getCPersonalityFn(CodeGenFunction &CGF) { 321f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__gcc_personality_v0"; 322f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 323f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 324f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic const char *getObjCPersonalityFn(CodeGenFunction &CGF) { 325f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CGF.CGM.getLangOptions().NeXTRuntime) { 326f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CGF.CGM.getLangOptions().ObjCNonFragileABI) 327f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__objc_personality_v0"; 328f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 329f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return getCPersonalityFn(CGF); 330f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 331f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__gnu_objc_personality_v0"; 332f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 333f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 334f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 335f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic const char *getCXXPersonalityFn(CodeGenFunction &CGF) { 336f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CGF.CGM.getLangOptions().SjLjExceptions) 337f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__gxx_personality_sj0"; 338f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 339f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__gxx_personality_v0"; 340f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 341f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 342f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Determines the personality function to use when both C++ 343f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// and Objective-C exceptions are being caught. 344f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic const char *getObjCXXPersonalityFn(CodeGenFunction &CGF) { 345f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The ObjC personality defers to the C++ personality for non-ObjC 346f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // handlers. Unlike the C++ case, we use the same personality 347f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // function on targets using (backend-driven) SJLJ EH. 348f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CGF.CGM.getLangOptions().NeXTRuntime) { 349f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CGF.CGM.getLangOptions().ObjCNonFragileABI) 350f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return "__objc_personality_v0"; 351f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 352f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // In the fragile ABI, just use C++ exception handling and hope 353f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // they're not doing crazy exception mixing. 3548019c45024be3026f854e3d22bfd89842be82266Daniel Dunbar else 355f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return getCXXPersonalityFn(CGF); 356dcf22ad88fdb6c4dd74f9065262cde8bac4f807bChandler Carruth } 35779a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall 358f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // I'm pretty sure the GNU runtime doesn't support mixed EH. 359f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // TODO: we don't necessarily need mixed EH here; remember what 360f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // kind of exceptions we actually try to catch in this function. 361f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.CGM.ErrorUnsupported(CGF.CurCodeDecl, 362f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "the GNU Objective C runtime does not support " 363f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "catching C++ and Objective C exceptions in the " 364f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "same function"); 365f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Use the C++ personality just to avoid returning null. 366f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return getCXXPersonalityFn(CGF); 367f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 368f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 369f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic llvm::Constant *getPersonalityFn(CodeGenFunction &CGF) { 370f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const char *Name; 371f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const LangOptions &Opts = CGF.CGM.getLangOptions(); 372f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (Opts.CPlusPlus && Opts.ObjC1) 373f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Name = getObjCXXPersonalityFn(CGF); 374f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else if (Opts.CPlusPlus) 375f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Name = getCXXPersonalityFn(CGF); 376f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else if (Opts.ObjC1) 377f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Name = getObjCPersonalityFn(CGF); 378f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 379f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Name = getCPersonalityFn(CGF); 380f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 38179a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall llvm::Constant *Personality = 382f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get( 383f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Type::getInt32Ty( 384f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.CGM.getLLVMContext()), 385f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall true), 386f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Name); 387f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return llvm::ConstantExpr::getBitCast(Personality, CGF.CGM.PtrToInt8Ty); 388f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 389f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 390f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Returns the value to inject into a selector to indicate the 391f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// presence of a catch-all. 392f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { 393f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Possibly we should use @llvm.eh.catch.all.value here. 394f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return llvm::ConstantPointerNull::get(CGF.CGM.PtrToInt8Ty); 395f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 396f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 397f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Returns the value to inject into a selector to indicate the 398f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// presence of a cleanup. 399f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic llvm::Constant *getCleanupValue(CodeGenFunction &CGF) { 400f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); 40199533834ba8f3658559f334e68a518ebb6388ceaMike Stump} 40299533834ba8f3658559f334e68a518ebb6388ceaMike Stump 40309faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCallnamespace { 40409faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall /// A cleanup to free the exception object if its initialization 40509faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall /// throws. 40609faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall struct FreeExceptionCleanup : EHScopeStack::LazyCleanup { 40709faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall FreeExceptionCleanup(llvm::Value *ShouldFreeVar, 40809faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::Value *ExnLocVar) 40909faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall : ShouldFreeVar(ShouldFreeVar), ExnLocVar(ExnLocVar) {} 41009faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall 41109faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::Value *ShouldFreeVar; 41209faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::Value *ExnLocVar; 41309faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall 41409faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 41509faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj"); 41609faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done"); 41709faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall 41809faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar, 41909faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall "should-free-exnobj"); 42009faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB); 42109faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall CGF.EmitBlock(FreeBB); 42209faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj"); 42309faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal) 42409faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall ->setDoesNotThrow(); 42509faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall CGF.EmitBlock(DoneBB); 42609faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall } 42709faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall }; 42809faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall} 42909faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall 430ac418162692a951ca3796d6830496a85a2d12493John McCall// Emits an exception expression into the given location. This 431ac418162692a951ca3796d6830496a85a2d12493John McCall// differs from EmitAnyExprToMem only in that, if a final copy-ctor 432ac418162692a951ca3796d6830496a85a2d12493John McCall// call is required, an exception within that copy ctor causes 433ac418162692a951ca3796d6830496a85a2d12493John McCall// std::terminate to be invoked. 434ac418162692a951ca3796d6830496a85a2d12493John McCallstatic void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E, 435ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::Value *ExnLoc) { 436ac418162692a951ca3796d6830496a85a2d12493John McCall // We want to release the allocated exception object if this 437ac418162692a951ca3796d6830496a85a2d12493John McCall // expression throws. We do this by pushing an EH-only cleanup 438ac418162692a951ca3796d6830496a85a2d12493John McCall // block which, furthermore, deactivates itself after the expression 439ac418162692a951ca3796d6830496a85a2d12493John McCall // is complete. 440ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::AllocaInst *ShouldFreeVar = 441ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()), 442ac418162692a951ca3796d6830496a85a2d12493John McCall "should-free-exnobj.var"); 443ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.InitTempAlloca(ShouldFreeVar, 444ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::ConstantInt::getFalse(CGF.getLLVMContext())); 445ac418162692a951ca3796d6830496a85a2d12493John McCall 446ac418162692a951ca3796d6830496a85a2d12493John McCall // A variable holding the exception pointer. This is necessary 447ac418162692a951ca3796d6830496a85a2d12493John McCall // because the throw expression does not necessarily dominate the 448ac418162692a951ca3796d6830496a85a2d12493John McCall // cleanup, for example if it appears in a conditional expression. 449ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::AllocaInst *ExnLocVar = 450ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.CreateTempAlloca(ExnLoc->getType(), "exnobj.var"); 451ac418162692a951ca3796d6830496a85a2d12493John McCall 452f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Make sure the exception object is cleaned up if there's an 453f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // exception during initialization. 45409faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall // FIXME: stmt expressions might require this to be a normal 45509faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall // cleanup, too. 45609faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall CGF.EHStack.pushLazyCleanup<FreeExceptionCleanup>(EHCleanup, 45709faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall ShouldFreeVar, 45809faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall ExnLocVar); 459f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHScopeStack::stable_iterator Cleanup = CGF.EHStack.stable_begin(); 460ac418162692a951ca3796d6830496a85a2d12493John McCall 461ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.Builder.CreateStore(ExnLoc, ExnLocVar); 462ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()), 463ac418162692a951ca3796d6830496a85a2d12493John McCall ShouldFreeVar); 464ac418162692a951ca3796d6830496a85a2d12493John McCall 465ac418162692a951ca3796d6830496a85a2d12493John McCall // __cxa_allocate_exception returns a void*; we need to cast this 466ac418162692a951ca3796d6830496a85a2d12493John McCall // to the appropriate type for the object. 467ac418162692a951ca3796d6830496a85a2d12493John McCall const llvm::Type *Ty = CGF.ConvertType(E->getType())->getPointerTo(); 468ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::Value *TypedExnLoc = CGF.Builder.CreateBitCast(ExnLoc, Ty); 469ac418162692a951ca3796d6830496a85a2d12493John McCall 470ac418162692a951ca3796d6830496a85a2d12493John McCall // FIXME: this isn't quite right! If there's a final unelided call 471ac418162692a951ca3796d6830496a85a2d12493John McCall // to a copy constructor, then according to [except.terminate]p1 we 472ac418162692a951ca3796d6830496a85a2d12493John McCall // must call std::terminate() if that constructor throws, because 473ac418162692a951ca3796d6830496a85a2d12493John McCall // technically that copy occurs after the exception expression is 474ac418162692a951ca3796d6830496a85a2d12493John McCall // evaluated but before the exception is caught. But the best way 475ac418162692a951ca3796d6830496a85a2d12493John McCall // to handle that is to teach EmitAggExpr to do the final copy 476ac418162692a951ca3796d6830496a85a2d12493John McCall // differently if it can't be elided. 477ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false); 478ac418162692a951ca3796d6830496a85a2d12493John McCall 479ac418162692a951ca3796d6830496a85a2d12493John McCall CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), 480ac418162692a951ca3796d6830496a85a2d12493John McCall ShouldFreeVar); 481ac418162692a951ca3796d6830496a85a2d12493John McCall 482f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Technically, the exception object is like a temporary; it has to 483f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // be cleaned up when its full-expression is complete. 484f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Unfortunately, the AST represents full-expressions by creating a 485f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // CXXExprWithTemporaries, which it only does when there are actually 486f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // temporaries. 487f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 488f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If any cleanups have been added since we pushed ours, they must 489f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // be from temporaries; this will get popped at the same time. 490f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise we need to pop ours off. FIXME: this is very brittle. 491f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (Cleanup == CGF.EHStack.stable_begin()) 492f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.PopCleanupBlock(); 493f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 494f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 495f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::Value *CodeGenFunction::getExceptionSlot() { 496f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!ExceptionSlot) { 497f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::Type *i8p = llvm::Type::getInt8PtrTy(getLLVMContext()); 498f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ExceptionSlot = CreateTempAlloca(i8p, "exn.slot"); 4990f590be3808365e851352543faa6acbece50b686Mike Stump } 500f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return ExceptionSlot; 5010f590be3808365e851352543faa6acbece50b686Mike Stump} 5020f590be3808365e851352543faa6acbece50b686Mike Stump 503756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlssonvoid CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { 504d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson if (!E->getSubExpr()) { 5051eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor if (getInvokeDest()) { 506f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateInvoke(getReThrowFn(*this), 507f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall getUnreachableBlock(), 508f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall getInvokeDest()) 5091eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor ->setDoesNotReturn(); 510f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 5111eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn(); 512f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 513f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 5141eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor 5151eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor // Clear the insertion point to indicate we are in unreachable code. 5161eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor Builder.ClearInsertionPoint(); 517d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson return; 518d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson } 5198755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 520d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson QualType ThrowType = E->getSubExpr()->getType(); 5218755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 522d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // Now allocate the exception object. 523d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 5243d3ec1c099ec8bfac3aa1fb0126fe515b7c7fa05John McCall uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); 5258755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 526d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this); 527f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *ExceptionPtr = 5288755ec336108839b9621c3b18f0e175f8a3b671cMike Stump Builder.CreateCall(AllocExceptionFn, 529d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson llvm::ConstantInt::get(SizeTy, TypeSize), 530d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson "exception"); 531f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ExceptionPtr->setDoesNotThrow(); 5328370c58b9295b32bee50443fe3ac43a47a2047e8Anders Carlsson 533ac418162692a951ca3796d6830496a85a2d12493John McCall EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr); 5348755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 535d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // Now throw the exception. 536d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 5379dffe6f51c676c1e423c382c62d1648746e36cd4John McCall llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, true); 538ac418162692a951ca3796d6830496a85a2d12493John McCall 539ac418162692a951ca3796d6830496a85a2d12493John McCall // The address of the destructor. If the exception type has a 540ac418162692a951ca3796d6830496a85a2d12493John McCall // trivial destructor (or isn't a record), we just pass null. 541ac418162692a951ca3796d6830496a85a2d12493John McCall llvm::Constant *Dtor = 0; 542ac418162692a951ca3796d6830496a85a2d12493John McCall if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { 543ac418162692a951ca3796d6830496a85a2d12493John McCall CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); 544ac418162692a951ca3796d6830496a85a2d12493John McCall if (!Record->hasTrivialDestructor()) { 5451d110e05e0ff48c1c7a483d6b7fd094cdf28316aDouglas Gregor CXXDestructorDecl *DtorD = Record->getDestructor(); 546ac418162692a951ca3796d6830496a85a2d12493John McCall Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete); 547ac418162692a951ca3796d6830496a85a2d12493John McCall Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy); 548ac418162692a951ca3796d6830496a85a2d12493John McCall } 549ac418162692a951ca3796d6830496a85a2d12493John McCall } 550ac418162692a951ca3796d6830496a85a2d12493John McCall if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy); 5518755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 5520a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump if (getInvokeDest()) { 5538755ec336108839b9621c3b18f0e175f8a3b671cMike Stump llvm::InvokeInst *ThrowCall = 554f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateInvoke3(getThrowFn(*this), 555f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall getUnreachableBlock(), getInvokeDest(), 5560a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump ExceptionPtr, TypeInfo, Dtor); 5570a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump ThrowCall->setDoesNotReturn(); 5580a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump } else { 5598755ec336108839b9621c3b18f0e175f8a3b671cMike Stump llvm::CallInst *ThrowCall = 5600a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor); 5610a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump ThrowCall->setDoesNotReturn(); 562f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 5630a3816e566db7cd6084310a2f5a3167d0ec30b31Mike Stump } 5648755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 565d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // Clear the insertion point to indicate we are in unreachable code. 566d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson Builder.ClearInsertionPoint(); 567c2ab48698094f3e6f3acebc38a19b8cb04069b41Mike Stump 568c2ab48698094f3e6f3acebc38a19b8cb04069b41Mike Stump // FIXME: For now, emit a dummy basic block because expr emitters in generally 569c2ab48698094f3e6f3acebc38a19b8cb04069b41Mike Stump // are not ready to handle emitting expressions at unreachable points. 570c2ab48698094f3e6f3acebc38a19b8cb04069b41Mike Stump EnsureInsertPoint(); 571756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson} 5722bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 573cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stumpvoid CodeGenFunction::EmitStartEHSpec(const Decl *D) { 574a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson if (!Exceptions) 575a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson return; 576a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson 577cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 578cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (FD == 0) 579cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 580cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 581cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (Proto == 0) 582cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 583cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 584cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack"); 585cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 586cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (!Proto->hasExceptionSpec()) 587cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 588cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 589f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NumExceptions = Proto->getNumExceptions(); 590f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); 591cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 592f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0; I != NumExceptions; ++I) { 593f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall QualType Ty = Proto->getExceptionType(I); 594f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); 595f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, true); 596f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Filter->setFilter(I, EHType); 597cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump } 598cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 599cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 600cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stumpvoid CodeGenFunction::EmitEndEHSpec(const Decl *D) { 601a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson if (!Exceptions) 602a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson return; 603a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson 604cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 605cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (FD == 0) 606cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 607cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 608cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (Proto == 0) 609cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 610cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 611cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump if (!Proto->hasExceptionSpec()) 612cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 613cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 614f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHStack.popFilter(); 615cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 616cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 6172bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stumpvoid CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 61859a7000a79118e4c140885ccbb2ac6a686a73092John McCall EnterCXXTryStmt(S); 6199fc6a7774643a810c8501dae2323e863fefb623eJohn McCall EmitStmt(S.getTryBlock()); 62059a7000a79118e4c140885ccbb2ac6a686a73092John McCall ExitCXXTryStmt(S); 6219fc6a7774643a810c8501dae2323e863fefb623eJohn McCall} 6229fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 62359a7000a79118e4c140885ccbb2ac6a686a73092John McCallvoid CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 624f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NumHandlers = S.getNumHandlers(); 625f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers); 626f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 627f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0; I != NumHandlers; ++I) { 628f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const CXXCatchStmt *C = S.getHandler(I); 629f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 630f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *Handler = createBasicBlock("catch"); 631f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (C->getExceptionDecl()) { 632f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // FIXME: Dropping the reference type on the type into makes it 633f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // impossible to correctly implement catch-by-reference 634f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // semantics for pointers. Unfortunately, this is what all 635f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // existing compilers do, and it's not clear that the standard 636f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // personality routine is capable of doing this right. See C++ DR 388: 637f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 638f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall QualType CaughtType = C->getCaughtType(); 639f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType(); 640f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, true); 641f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope->setHandler(I, TypeInfo, Handler); 642f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 643f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // No exception decl indicates '...', a catch-all. 644f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope->setCatchAllHandler(I, Handler); 645f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 646f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 647f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 648f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 649f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Check whether this is a non-EH scope, i.e. a scope which doesn't 650f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// affect exception handling. Currently, the only non-EH scopes are 651f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// normal-only cleanup scopes. 652f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic bool isNonEHScope(const EHScope &S) { 653da65ea86482bc116906edfb9ba1d7124f76cc867John McCall switch (S.getKind()) { 654da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Cleanup: 655da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return !cast<EHCleanupScope>(S).isEHCleanup(); 656da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::LazyCleanup: 657da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return !cast<EHLazyCleanupScope>(S).isEHCleanup(); 658da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Filter: 659da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Catch: 660da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Terminate: 661da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return false; 662da65ea86482bc116906edfb9ba1d7124f76cc867John McCall } 663da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 664da65ea86482bc116906edfb9ba1d7124f76cc867John McCall // Suppress warning. 665da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return false; 666f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 6679fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 668f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { 669f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHStack.requiresLandingPad()); 670f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!EHStack.empty()); 6719fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 672da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (!Exceptions) 673da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return 0; 674da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 675f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check the innermost scope for a cached landing pad. If this is 676f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. 677f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); 678f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (LP) return LP; 679f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 680f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Build the landing pad for this scope. 681f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall LP = EmitLandingPad(); 682f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(LP); 683f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 684f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Cache the landing pad on the innermost scope. If this is a 685f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // non-EH scope, cache the landing pad on the enclosing scope, too. 686f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) { 687f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ir->setCachedLandingPad(LP); 688f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!isNonEHScope(*ir)) break; 689f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 690f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 691f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return LP; 6929fc6a7774643a810c8501dae2323e863fefb623eJohn McCall} 6939fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 694f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::EmitLandingPad() { 695f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHStack.requiresLandingPad()); 696f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 697f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // This function contains a hack to work around a design flaw in 698f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // LLVM's EH IR which breaks semantics after inlining. This same 699f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // hack is implemented in llvm-gcc. 700f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 701f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The LLVM EH abstraction is basically a thin veneer over the 702f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // traditional GCC zero-cost design: for each range of instructions 703f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // in the function, there is (at most) one "landing pad" with an 704f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // associated chain of EH actions. A language-specific personality 705f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // function interprets this chain of actions and (1) decides whether 706f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // or not to resume execution at the landing pad and (2) if so, 707f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // provides an integer indicating why it's stopping. In LLVM IR, 708f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the association of a landing pad with a range of instructions is 709f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // achieved via an invoke instruction, the chain of actions becomes 710f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the arguments to the @llvm.eh.selector call, and the selector 711f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // call returns the integer indicator. Other than the required 712f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // presence of two intrinsic function calls in the landing pad, 713f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the IR exactly describes the layout of the output code. 714f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 715f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // A principal advantage of this design is that it is completely 716f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // language-agnostic; in theory, the LLVM optimizers can treat 717f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // landing pads neutrally, and targets need only know how to lower 718f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the intrinsics to have a functioning exceptions system (assuming 719f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // that platform exceptions follow something approximately like the 720f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // GCC design). Unfortunately, landing pads cannot be combined in a 721f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // language-agnostic way: given selectors A and B, there is no way 722f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // to make a single landing pad which faithfully represents the 723f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // semantics of propagating an exception first through A, then 724f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // through B, without knowing how the personality will interpret the 725f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // (lowered form of the) selectors. This means that inlining has no 726f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // choice but to crudely chain invokes (i.e., to ignore invokes in 727f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the inlined function, but to turn all unwindable calls into 728f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // invokes), which is only semantically valid if every unwind stops 729f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // at every landing pad. 730f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 731f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Therefore, the invoke-inline hack is to guarantee that every 732f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // landing pad has a catch-all. 733f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const bool UseInvokeInlineHack = true; 734f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 735f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (EHScopeStack::iterator ir = EHStack.begin(); ; ) { 736f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(ir != EHStack.end() && 737f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "stack requiring landing pad is nothing but non-EH scopes?"); 738f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 739f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If this is a terminate scope, just use the singleton terminate 740f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // landing pad. 741f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (isa<EHTerminateScope>(*ir)) 742f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return getTerminateLandingPad(); 743f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 744f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If this isn't an EH scope, iterate; otherwise break out. 745f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!isNonEHScope(*ir)) break; 746f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ++ir; 747f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 748f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We haven't checked this scope for a cached landing pad yet. 749f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (llvm::BasicBlock *LP = ir->getCachedLandingPad()) 750f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return LP; 751f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 752f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 753f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Save the current IR generation state. 754f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 755f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 756f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Create and configure the landing pad. 757f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *LP = createBasicBlock("lpad"); 758f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(LP); 759f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 760f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Save the exception pointer. It's safe to use a single exception 761f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer per function because EH cleanups can never have nested 762f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // try/catches. 763f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *Exn = 764f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); 765f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Exn->setDoesNotThrow(); 766f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateStore(Exn, getExceptionSlot()); 767f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 768f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Build the selector arguments. 769f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::SmallVector<llvm::Value*, 8> EHSelector; 770f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(Exn); 771f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(getPersonalityFn(*this)); 772f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 773f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Accumulate all the handlers in scope. 774f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::DenseMap<llvm::Value*, JumpDest> EHHandlers; 775f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall JumpDest CatchAll; 776f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall bool HasEHCleanup = false; 777f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall bool HasEHFilter = false; 778f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::SmallVector<llvm::Value*, 8> EHFilters; 779f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); 780f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall I != E; ++I) { 781f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 782f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall switch (I->getKind()) { 783da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::LazyCleanup: 784da65ea86482bc116906edfb9ba1d7124f76cc867John McCall if (!HasEHCleanup) 785da65ea86482bc116906edfb9ba1d7124f76cc867John McCall HasEHCleanup = cast<EHLazyCleanupScope>(*I).isEHCleanup(); 786da65ea86482bc116906edfb9ba1d7124f76cc867John McCall // We otherwise don't care about cleanups. 787da65ea86482bc116906edfb9ba1d7124f76cc867John McCall continue; 788da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 789f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Cleanup: 790f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!HasEHCleanup) 791f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall HasEHCleanup = cast<EHCleanupScope>(*I).isEHCleanup(); 792f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We otherwise don't care about cleanups. 793f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall continue; 794f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 795f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Filter: { 796f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); 797f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!CatchAll.Block && "EH filter reached after catch-all"); 798f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 799f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Filter scopes get added to the selector in wierd ways. 800f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHFilterScope &Filter = cast<EHFilterScope>(*I); 801f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall HasEHFilter = true; 802f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 803f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Add all the filter values which we aren't already explicitly 804f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // catching. 805f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0, E = Filter.getNumFilters(); I != E; ++I) { 806f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *FV = Filter.getFilter(I); 807f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!EHHandlers.count(FV)) 808f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHFilters.push_back(FV); 809f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 810f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall goto done; 811f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 812f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 813f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Terminate: 814f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Terminate scopes are basically catch-alls. 815f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!CatchAll.Block); 816f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchAll.Block = getTerminateHandler(); 817f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I); 818f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall goto done; 819f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 820f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Catch: 821f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall break; 822f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 823f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 824f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope &Catch = cast<EHCatchScope>(*I); 825f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned HI = 0, HE = Catch.getNumHandlers(); HI != HE; ++HI) { 826f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope::Handler Handler = Catch.getHandler(HI); 827f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 828f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Catch-all. We should only have one of these per catch. 829f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!Handler.Type) { 830f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!CatchAll.Block); 831f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchAll.Block = Handler.Block; 832f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I); 833f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall continue; 834f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 835f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 836f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check whether we already have a handler for this type. 837f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall JumpDest &Dest = EHHandlers[Handler.Type]; 838f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (Dest.Block) continue; 839f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 840f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(Handler.Type); 841f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Dest.Block = Handler.Block; 842f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Dest.ScopeDepth = EHStack.getEnclosingEHCleanup(I); 8432bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump } 844f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 845f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Stop if we found a catch-all. 846f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CatchAll.Block) break; 8472bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump } 8482bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 849f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall done: 850f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned LastToEmitInLoop = EHSelector.size(); 851f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 852f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we have a catch-all, add null to the selector. 853f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CatchAll.Block) { 854f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(getCatchAllValue(CGF)); 855f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 856f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we have an EH filter, we need to add those handlers in the 857f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // right place in the selector, which is to say, at the end. 858f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else if (HasEHFilter) { 859f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Create a filter expression: an integer constant saying how many 860f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // filters there are (+1 to avoid ambiguity with 0 for cleanup), 861f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // followed by the filter types. The personality routine only 862f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // lands here if the filter doesn't match. 863f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(llvm::ConstantInt::get(Builder.getInt32Ty(), 864f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHFilters.size() + 1)); 865f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.append(EHFilters.begin(), EHFilters.end()); 866f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 867f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Also check whether we need a cleanup. 868f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (UseInvokeInlineHack || HasEHCleanup) 869f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(UseInvokeInlineHack 870f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ? getCatchAllValue(CGF) 871f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall : getCleanupValue(CGF)); 872f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 873f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, signal that we at least have cleanups. 874f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else if (UseInvokeInlineHack || HasEHCleanup) { 875f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.push_back(UseInvokeInlineHack 876f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ? getCatchAllValue(CGF) 877f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall : getCleanupValue(CGF)); 878f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 879f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(LastToEmitInLoop > 2); 880f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall LastToEmitInLoop--; 8810f590be3808365e851352543faa6acbece50b686Mike Stump } 8822bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 883f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHSelector.size() >= 3 && "selector call has only two arguments!"); 884f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 885f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the backend how to generate the landing pad. 886f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *Selection = 887f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), 888f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHSelector.begin(), EHSelector.end(), "eh.selector"); 889f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Selection->setDoesNotThrow(); 890f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 891f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Select the right handler. 892f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *llvm_eh_typeid_for = 893f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 894f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 895f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The results of llvm_eh_typeid_for aren't reliable --- at least 896f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // not locally --- so we basically have to do this as an 'if' chain. 897f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We walk through the first N-1 catch clauses, testing and chaining, 898f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // and then fall into the final clause (which is either a cleanup, a 899f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // filter (possibly with a cleanup), a catch-all, or another catch). 900f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 2; I != LastToEmitInLoop; ++I) { 901f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Type = EHSelector[I]; 902f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall JumpDest Dest = EHHandlers[Type]; 903f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(Dest.Block && "no handler entry for value in selector?"); 904f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 905f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Figure out where to branch on a match. As a debug code-size 906f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // optimization, if the scope depth matches the innermost cleanup, 907f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // we branch directly to the catch handler. 908f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *Match = Dest.Block; 909f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall bool MatchNeedsCleanup = Dest.ScopeDepth != EHStack.getInnermostEHCleanup(); 910f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (MatchNeedsCleanup) 911f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Match = createBasicBlock("eh.match"); 912f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 913f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *Next = createBasicBlock("eh.next"); 914f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 915f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check whether the exception matches. 916f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *Id 917f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall = Builder.CreateCall(llvm_eh_typeid_for, 918f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateBitCast(Type, CGM.PtrToInt8Ty)); 919f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Id->setDoesNotThrow(); 920f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCondBr(Builder.CreateICmpEQ(Selection, Id), 921f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Match, Next); 922f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 923f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Emit match code if necessary. 924f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (MatchNeedsCleanup) { 9250f590be3808365e851352543faa6acbece50b686Mike Stump EmitBlock(Match); 926f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughEHCleanup(Dest); 9270f590be3808365e851352543faa6acbece50b686Mike Stump } 9280f590be3808365e851352543faa6acbece50b686Mike Stump 929f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Continue to the next match. 930f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(Next); 931f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 932f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 933f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Emit the final case in the selector. 934f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // This might be a catch-all.... 935f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CatchAll.Block) { 936f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(isa<llvm::ConstantPointerNull>(EHSelector.back())); 937f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughEHCleanup(CatchAll); 938f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 939f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // ...or an EH filter... 940f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else if (HasEHFilter) { 941f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *SavedSelection = Selection; 942f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 943f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // First, unwind out to the outermost scope if necessary. 944f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EHStack.hasEHCleanups()) { 945f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The end here might not dominate the beginning, so we might need to 946f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // save the selector if we need it. 947f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::AllocaInst *SelectorVar = 0; 948f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HasEHCleanup) { 949f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall SelectorVar = CreateTempAlloca(Builder.getInt32Ty(), "selector.var"); 950f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateStore(Selection, SelectorVar); 951f7f74675d4e63c4529a4b890c0dd62cf6dc4c476Mike Stump } 952f7f74675d4e63c4529a4b890c0dd62cf6dc4c476Mike Stump 953f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont"); 954f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughEHCleanup(JumpDest(CleanupContBB, EHStack.stable_end())); 955f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(CleanupContBB); 956f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 957f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HasEHCleanup) 958f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall SavedSelection = Builder.CreateLoad(SelectorVar, "ehspec.saved-selector"); 9590f590be3808365e851352543faa6acbece50b686Mike Stump } 9600f590be3808365e851352543faa6acbece50b686Mike Stump 961f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If there was a cleanup, we'll need to actually check whether we 962f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // landed here because the filter triggered. 963f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (UseInvokeInlineHack || HasEHCleanup) { 964f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *RethrowBB = createBasicBlock("cleanup"); 965f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *UnexpectedBB = createBasicBlock("ehspec.unexpected"); 966f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 967f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Constant *Zero = llvm::ConstantInt::get(Builder.getInt32Ty(), 0); 968f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *FailsFilter = 969f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateICmpSLT(SavedSelection, Zero, "ehspec.fails"); 970f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCondBr(FailsFilter, UnexpectedBB, RethrowBB); 971f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 972f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The rethrow block is where we land if this was a cleanup. 973f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // TODO: can this be _Unwind_Resume if the InvokeInlineHack is off? 974f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(RethrowBB); 975f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(getUnwindResumeOrRethrowFn(), 976f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateLoad(getExceptionSlot())) 977f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->setDoesNotReturn(); 978f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 9790f590be3808365e851352543faa6acbece50b686Mike Stump 980f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(UnexpectedBB); 981f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 9820f590be3808365e851352543faa6acbece50b686Mike Stump 983f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Call __cxa_call_unexpected. This doesn't need to be an invoke 984f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // because __cxa_call_unexpected magically filters exceptions 985f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // according to the last landing pad the exception was thrown 986f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // into. Seriously. 987f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(getUnexpectedFn(*this), 988f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateLoad(getExceptionSlot())) 989f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->setDoesNotReturn(); 990f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 9910f590be3808365e851352543faa6acbece50b686Mike Stump 992f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // ...or a normal catch handler... 993f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else if (!UseInvokeInlineHack && !HasEHCleanup) { 994f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Type = EHSelector.back(); 995f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughEHCleanup(EHHandlers[Type]); 9960f590be3808365e851352543faa6acbece50b686Mike Stump 997f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // ...or a cleanup. 998f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 999f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We emit a jump to a notional label at the outermost unwind state. 1000f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *Unwind = createBasicBlock("eh.resume"); 1001f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall JumpDest Dest(Unwind, EHStack.stable_end()); 1002f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughEHCleanup(Dest); 1003f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1004f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The unwind block. We have to reload the exception here because 1005f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // we might have unwound through arbitrary blocks, so the landing 1006f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pad might not dominate. 1007f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(Unwind); 10080f590be3808365e851352543faa6acbece50b686Mike Stump 1009f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // This can always be a call because we necessarily didn't find 1010f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // anything on the EH stack which needs our help. 1011f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(getUnwindResumeOrRethrowFn(), 1012f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateLoad(getExceptionSlot())) 1013f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->setDoesNotReturn(); 1014f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 1015f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1016f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1017f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Restore the old IR generation state. 1018f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1019f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1020f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return LP; 1021f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 10220f590be3808365e851352543faa6acbece50b686Mike Stump 10238e3f86193995c47ee0d229e4336c3382410f09f5John McCallnamespace { 10248e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// A cleanup to call __cxa_end_catch. In many cases, the caught 10258e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// exception type lets us state definitively that the thrown exception 10268e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// type does not have a destructor. In particular: 10278e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catch-alls tell us nothing, so we have to conservatively 10288e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// assume that the thrown exception might have a destructor. 10298e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches by reference behave according to their base types. 10308e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches of non-record types will only trigger for exceptions 10318e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// of non-record types, which never have destructors. 10328e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches of record types can trigger for arbitrary subclasses 10338e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// of the caught type, so we have to assume the actual thrown 10348e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// exception type might have a throwing destructor, even if the 10358e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// caught type's destructor is trivial or nothrow. 10368e3f86193995c47ee0d229e4336c3382410f09f5John McCall struct CallEndCatch : EHScopeStack::LazyCleanup { 10378e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} 10388e3f86193995c47ee0d229e4336c3382410f09f5John McCall bool MightThrow; 10398e3f86193995c47ee0d229e4336c3382410f09f5John McCall 10408e3f86193995c47ee0d229e4336c3382410f09f5John McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 10418e3f86193995c47ee0d229e4336c3382410f09f5John McCall if (!MightThrow) { 10428e3f86193995c47ee0d229e4336c3382410f09f5John McCall CGF.Builder.CreateCall(getEndCatchFn(CGF))->setDoesNotThrow(); 10438e3f86193995c47ee0d229e4336c3382410f09f5John McCall return; 10448e3f86193995c47ee0d229e4336c3382410f09f5John McCall } 10458e3f86193995c47ee0d229e4336c3382410f09f5John McCall 10468e3f86193995c47ee0d229e4336c3382410f09f5John McCall CGF.EmitCallOrInvoke(getEndCatchFn(CGF), 0, 0); 10478e3f86193995c47ee0d229e4336c3382410f09f5John McCall } 10488e3f86193995c47ee0d229e4336c3382410f09f5John McCall }; 10498e3f86193995c47ee0d229e4336c3382410f09f5John McCall} 10508e3f86193995c47ee0d229e4336c3382410f09f5John McCall 1051f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Emits a call to __cxa_begin_catch and enters a cleanup to call 1052f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// __cxa_end_catch. 10538e3f86193995c47ee0d229e4336c3382410f09f5John McCall/// 10548e3f86193995c47ee0d229e4336c3382410f09f5John McCall/// \param EndMightThrow - true if __cxa_end_catch might throw 10558e3f86193995c47ee0d229e4336c3382410f09f5John McCallstatic llvm::Value *CallBeginCatch(CodeGenFunction &CGF, 10568e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *Exn, 10578e3f86193995c47ee0d229e4336c3382410f09f5John McCall bool EndMightThrow) { 1058f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn); 1059f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Call->setDoesNotThrow(); 10600f590be3808365e851352543faa6acbece50b686Mike Stump 10618e3f86193995c47ee0d229e4336c3382410f09f5John McCall CGF.EHStack.pushLazyCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); 1062f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1063f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return Call; 1064f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1065f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1066f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// A "special initializer" callback for initializing a catch 1067f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// parameter during catch initialization. 1068f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic void InitCatchParam(CodeGenFunction &CGF, 1069f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const VarDecl &CatchParam, 1070f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ParamAddr) { 1071f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Load the exception from where the landing pad saved it. 1072f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn"); 1073f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1074f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CanQualType CatchType = 1075f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); 1076f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); 1077f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1078f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we're catching by reference, we can just cast the object 1079f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer to the appropriate pointer. 1080f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (isa<ReferenceType>(CatchType)) { 10818e3f86193995c47ee0d229e4336c3382410f09f5John McCall bool EndCatchMightThrow = cast<ReferenceType>(CatchType)->getPointeeType() 10828e3f86193995c47ee0d229e4336c3382410f09f5John McCall ->isRecordType(); 10838e3f86193995c47ee0d229e4336c3382410f09f5John McCall 1084f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // __cxa_begin_catch returns the adjusted object pointer. 10858e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); 1086f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ExnCast = 1087f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); 1088f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateStore(ExnCast, ParamAddr); 1089f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1090a086783570f76062a345e761811296dc8df571c8Mike Stump } 10912bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1092f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Non-aggregates (plus complexes). 1093f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall bool IsComplex = false; 1094f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!CGF.hasAggregateLLVMType(CatchType) || 1095f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall (IsComplex = CatchType->isAnyComplexType())) { 10968e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); 1097f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1098f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If the catch type is a pointer type, __cxa_begin_catch returns 1099f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the pointer by value. 1100f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CatchType->hasPointerRepresentation()) { 1101f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *CastExn = 1102f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); 1103f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateStore(CastExn, ParamAddr); 1104f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1105f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 11062bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1107f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, it returns a pointer into the exception object. 11082bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1109f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 1110f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 11112bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1112f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (IsComplex) { 1113f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false), 1114f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ParamAddr, /*volatile*/ false); 1115f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 1116f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar"); 1117f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, CatchType); 1118f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1119f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1120f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 11210f590be3808365e851352543faa6acbece50b686Mike Stump 1122f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // FIXME: this *really* needs to be done via a proper, Sema-emitted 1123f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // initializer expression. 11242bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1125f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CXXRecordDecl *RD = CatchType.getTypePtr()->getAsCXXRecordDecl(); 1126f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(RD && "aggregate catch type was not a record!"); 1127b2c9c0b1c5e25cfbee1403cde12b98f180e6b315Mike Stump 1128f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 1129f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1130f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (RD->hasTrivialCopyConstructor()) { 11318e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, true); 1132f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 1133f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EmitAggregateCopy(ParamAddr, Cast, CatchType); 1134f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1135f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1136f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1137f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We have to call __cxa_get_exception_ptr to get the adjusted 1138f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer before copying. 1139f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *AdjustedExn = 1140f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn); 1141f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall AdjustedExn->setDoesNotThrow(); 1142f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 1143f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1144f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CXXConstructorDecl *CD = RD->getCopyConstructor(CGF.getContext(), 0); 1145f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(CD && "record has no copy constructor!"); 1146f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *CopyCtor = CGF.CGM.GetAddrOfCXXConstructor(CD, Ctor_Complete); 1147f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1148f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CallArgList CallArgs; 1149f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CallArgs.push_back(std::make_pair(RValue::get(ParamAddr), 1150f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CD->getThisType(CGF.getContext()))); 1151f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CallArgs.push_back(std::make_pair(RValue::get(Cast), 1152f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CD->getParamDecl(0)->getType())); 1153f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1154f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const FunctionProtoType *FPT 1155f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall = CD->getType()->getAs<FunctionProtoType>(); 1156f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1157f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Call the copy ctor in a terminate scope. 1158f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.pushTerminate(); 1159f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT), 1160f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CopyCtor, ReturnValueSlot(), CallArgs, CD); 1161f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.popTerminate(); 1162f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1163f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Finally we can call __cxa_begin_catch. 11648e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallBeginCatch(CGF, Exn, true); 1165f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1166f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1167f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Begins a catch statement by initializing the catch variable and 1168f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// calling __cxa_begin_catch. 1169f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic void BeginCatch(CodeGenFunction &CGF, 1170f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const CXXCatchStmt *S) { 1171f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We have to be very careful with the ordering of cleanups here: 1172f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // C++ [except.throw]p4: 1173f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The destruction [of the exception temporary] occurs 1174f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // immediately after the destruction of the object declared in 1175f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the exception-declaration in the handler. 1176f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 1177f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // So the precise ordering is: 1178f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 1. Construct catch variable. 1179f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 2. __cxa_begin_catch 1180f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 3. Enter __cxa_end_catch cleanup 1181f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 4. Enter dtor cleanup 1182f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 1183f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We do this by initializing the exception variable with a 1184f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // "special initializer", InitCatchParam. Delegation sequence: 1185f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - ExitCXXTryStmt opens a RunCleanupsScope 1186f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitLocalBlockVarDecl creates the variable and debug info 1187f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - InitCatchParam initializes the variable from the exception 1188f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - CallBeginCatch calls __cxa_begin_catch 1189f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - CallBeginCatch enters the __cxa_end_catch cleanup 1190f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitLocalBlockVarDecl enters the variable destructor cleanup 1191f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitCXXTryStmt emits the code for the catch body 1192f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitCXXTryStmt close the RunCleanupsScope 1193f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1194f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall VarDecl *CatchParam = S->getExceptionDecl(); 1195f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!CatchParam) { 1196f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn"); 11978e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallBeginCatch(CGF, Exn, true); 1198f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1199f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1200f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1201f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Emit the local. 1202f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EmitLocalBlockVarDecl(*CatchParam, &InitCatchParam); 1203f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1204f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1205fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCallnamespace { 1206fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall struct CallRethrow : EHScopeStack::LazyCleanup { 1207fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 1208fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall CGF.EmitCallOrInvoke(getReThrowFn(CGF), 0, 0); 1209fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall } 1210fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall }; 1211fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall} 1212fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall 121359a7000a79118e4c140885ccbb2ac6a686a73092John McCallvoid CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 1214f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NumHandlers = S.getNumHandlers(); 1215f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); 1216f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(CatchScope.getNumHandlers() == NumHandlers); 1217f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1218f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Copy the handler blocks off before we pop the EH stack. Emitting 1219f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the handlers might scribble on this memory. 1220f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers); 1221f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall memcpy(Handlers.data(), CatchScope.begin(), 1222f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NumHandlers * sizeof(EHCatchScope::Handler)); 1223f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHStack.popCatch(); 1224f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1225f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The fall-through block. 1226f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *ContBB = createBasicBlock("try.cont"); 1227f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1228f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We just emitted the body of the try; jump to the continue block. 1229f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HaveInsertPoint()) 1230f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateBr(ContBB); 1231f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 123259a7000a79118e4c140885ccbb2ac6a686a73092John McCall // Determine if we need an implicit rethrow for all these catch handlers. 123359a7000a79118e4c140885ccbb2ac6a686a73092John McCall bool ImplicitRethrow = false; 123459a7000a79118e4c140885ccbb2ac6a686a73092John McCall if (IsFnTryBlock) 123559a7000a79118e4c140885ccbb2ac6a686a73092John McCall ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || 123659a7000a79118e4c140885ccbb2ac6a686a73092John McCall isa<CXXConstructorDecl>(CurCodeDecl); 123759a7000a79118e4c140885ccbb2ac6a686a73092John McCall 1238f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0; I != NumHandlers; ++I) { 1239f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *CatchBlock = Handlers[I].Block; 1240f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(CatchBlock); 1241f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1242f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Catch the exception if this isn't a catch-all. 1243f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const CXXCatchStmt *C = S.getHandler(I); 1244f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1245f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a cleanup scope, including the catch variable and the 1246f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // end-catch. 1247f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall RunCleanupsScope CatchScope(*this); 1248f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1249f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Initialize the catch variable and set up the cleanups. 1250f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BeginCatch(*this, C); 1251f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 125259a7000a79118e4c140885ccbb2ac6a686a73092John McCall // If there's an implicit rethrow, push a normal "cleanup" to call 1253fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall // _cxa_rethrow. This needs to happen before __cxa_end_catch is 1254fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall // called, and so it is pushed after BeginCatch. 1255fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall if (ImplicitRethrow) 1256fcd5c0c62ef3d86ecd991753bb43c88c861470e7John McCall EHStack.pushLazyCleanup<CallRethrow>(NormalCleanup); 125759a7000a79118e4c140885ccbb2ac6a686a73092John McCall 1258f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Perform the body of the catch. 1259f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitStmt(C->getHandlerBlock()); 1260f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1261f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Fall out through the catch cleanups. 1262f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope.ForceCleanup(); 1263f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1264f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Branch out of the try. 1265f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HaveInsertPoint()) 1266f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateBr(ContBB); 1267f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 12682bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1269f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(ContBB); 1270f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1271f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1272f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Enters a finally block for an implementation using zero-cost 1273f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// exceptions. This is mostly general, but hard-codes some 1274f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// language/ABI-specific behavior in the catch-all sections. 1275f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallCodeGenFunction::FinallyInfo 1276f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallCodeGenFunction::EnterFinallyBlock(const Stmt *Body, 1277f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Constant *BeginCatchFn, 1278f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Constant *EndCatchFn, 1279f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Constant *RethrowFn) { 1280f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert((BeginCatchFn != 0) == (EndCatchFn != 0) && 1281f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "begin/end catch functions not paired"); 1282f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(RethrowFn && "rethrow function is required"); 1283f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1284f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The rethrow function has one of the following two types: 1285f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void (*)() 1286f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void (*)(void*) 1287f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // In the latter case we need to pass it the exception object. 1288f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // But we can't use the exception slot because the @finally might 1289f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // have a landing pad (which would overwrite the exception slot). 1290f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const llvm::FunctionType *RethrowFnTy = 1291f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall cast<llvm::FunctionType>( 1292f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall cast<llvm::PointerType>(RethrowFn->getType()) 1293f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->getElementType()); 1294f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *SavedExnVar = 0; 1295f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (RethrowFnTy->getNumParams()) 1296f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall SavedExnVar = CreateTempAlloca(Builder.getInt8PtrTy(), "finally.exn"); 1297f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1298f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // A finally block is a statement which must be executed on any edge 1299f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // out of a given scope. Unlike a cleanup, the finally block may 1300f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // contain arbitrary control flow leading out of itself. In 1301f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // addition, finally blocks should always be executed, even if there 1302f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // are no catch handlers higher on the stack. Therefore, we 1303f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // surround the protected scope with a combination of a normal 1304f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // cleanup (to catch attempts to break out of the block via normal 1305f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // control flow) and an EH catch-all (semantically "outside" any try 1306f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // statement to which the finally block might have been attached). 1307f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The finally block itself is generated in the context of a cleanup 1308f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // which conditionally leaves the catch-all. 1309f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1310f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall FinallyInfo Info; 1311f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1312f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Jump destination for performing the finally block on an exception 1313f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // edge. We'll never actually reach this block, so unreachable is 1314f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // fine. 1315f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall JumpDest RethrowDest = getJumpDestInCurrentScope(getUnreachableBlock()); 1316f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1317f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Whether the finally block is being executed for EH purposes. 1318f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::AllocaInst *ForEHVar = CreateTempAlloca(CGF.Builder.getInt1Ty(), 1319f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "finally.for-eh"); 1320f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext())); 1321f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1322f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a normal cleanup which will perform the @finally block. 1323f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall { 1324da65ea86482bc116906edfb9ba1d7124f76cc867John McCall CodeGenFunction::CleanupBlock Cleanup(*this, NormalCleanup); 1325f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1326f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a cleanup to call the end-catch function if one was provided. 1327f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EndCatchFn) { 1328da65ea86482bc116906edfb9ba1d7124f76cc867John McCall CodeGenFunction::CleanupBlock FinallyExitCleanup(CGF, NormalAndEHCleanup); 1329f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1330f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *EndCatchBB = createBasicBlock("finally.endcatch"); 1331f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *CleanupContBB = createBasicBlock("finally.cleanup.cont"); 1332f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1333f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ShouldEndCatch = 1334f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateLoad(ForEHVar, "finally.endcatch"); 1335f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB); 1336f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(EndCatchBB); 13378e3f86193995c47ee0d229e4336c3382410f09f5John McCall EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw 1338f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(CleanupContBB); 1339f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1340f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1341f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Emit the finally block. 1342f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitStmt(Body); 1343f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1344f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If the end of the finally is reachable, check whether this was 1345f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // for EH. If so, rethrow. 1346f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HaveInsertPoint()) { 1347f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *RethrowBB = createBasicBlock("finally.rethrow"); 1348f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *ContBB = createBasicBlock("finally.cont"); 1349f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1350f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ShouldRethrow = 1351f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateLoad(ForEHVar, "finally.shouldthrow"); 1352f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB); 1353f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1354f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(RethrowBB); 1355f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (SavedExnVar) { 1356f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Args[] = { Builder.CreateLoad(SavedExnVar) }; 1357f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitCallOrInvoke(RethrowFn, Args, Args+1); 1358f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 1359f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitCallOrInvoke(RethrowFn, 0, 0); 1360f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1361f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateUnreachable(); 1362f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1363f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(ContBB); 1364f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1365f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1366f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Leave the end-catch cleanup. As an optimization, pretend that 1367f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the fallthrough path was inaccessible; we've dynamically proven 1368f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // that we're not in the EH case along that path. 1369f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EndCatchFn) { 1370f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1371f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall PopCleanupBlock(); 1372f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1373f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1374f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1375f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Now make sure we actually have an insertion point or the 1376f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // cleanup gods will hate us. 1377f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EnsureInsertPoint(); 1378f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1379f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1380f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a catch-all scope. 1381f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall"); 1382f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); 1383f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.SetInsertPoint(CatchAllBB); 1384f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1385f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If there's a begin-catch function, call it. 1386f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (BeginCatchFn) { 1387f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(BeginCatchFn, Builder.CreateLoad(getExceptionSlot())) 1388f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->setDoesNotThrow(); 1389f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1390f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1391f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we need to remember the exception pointer to rethrow later, do so. 1392f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (SavedExnVar) { 1393f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *SavedExn = Builder.CreateLoad(getExceptionSlot()); 1394f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateStore(SavedExn, SavedExnVar); 1395f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1396f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1397f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the finally block that we're in EH. 1398f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateStore(llvm::ConstantInt::getTrue(getLLVMContext()), ForEHVar); 1399f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1400f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Thread a jump through the finally cleanup. 1401f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBranchThroughCleanup(RethrowDest); 1402f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1403f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1404f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1405f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope *CatchScope = EHStack.pushCatch(1); 1406f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope->setCatchAllHandler(0, CatchAllBB); 1407f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1408f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return Info; 1409f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1410f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1411f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid CodeGenFunction::ExitFinallyBlock(FinallyInfo &Info) { 1412f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Leave the finally catch-all. 1413f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope &Catch = cast<EHCatchScope>(*EHStack.begin()); 1414f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *CatchAllBB = Catch.getHandler(0).Block; 1415f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHStack.popCatch(); 1416f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1417f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // And leave the normal cleanup. 1418f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall PopCleanupBlock(); 1419f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1420f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1421f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(CatchAllBB, true); 1422f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1423f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1424f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1425f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1426f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { 1427f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (TerminateLandingPad) 1428f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return TerminateLandingPad; 1429f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1430f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1431f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1432f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // This will get inserted at the end of the function. 1433f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall TerminateLandingPad = createBasicBlock("terminate.lpad"); 1434f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.SetInsertPoint(TerminateLandingPad); 1435f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1436f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the backend that this is a landing pad. 1437f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *Exn = 1438f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); 1439f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Exn->setDoesNotThrow(); 1440f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1441f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the backend what the exception table should be: 1442f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // nothing but a catch-all. 1443f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Args[3] = { Exn, getPersonalityFn(*this), 1444f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall getCatchAllValue(*this) }; 1445f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), 1446f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Args, Args+3, "eh.selector") 1447f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ->setDoesNotThrow(); 1448f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1449f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); 1450f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall TerminateCall->setDoesNotReturn(); 1451f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall TerminateCall->setDoesNotThrow(); 1452d88ea5687968640ada2bc5a10211cbeb68a671ecMike Stump CGF.Builder.CreateUnreachable(); 1453d88ea5687968640ada2bc5a10211cbeb68a671ecMike Stump 1454f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Restore the saved insertion state. 1455f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1456891f80ec2fb2d1730b769467d602689e1080845bJohn McCall 1457f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return TerminateLandingPad; 1458d88ea5687968640ada2bc5a10211cbeb68a671ecMike Stump} 14599b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 14609b39c51ae3c547568ac42325f94b4197618f6b18Mike Stumpllvm::BasicBlock *CodeGenFunction::getTerminateHandler() { 1461182f383db1782af752ecaf607fdff72a8542088bMike Stump if (TerminateHandler) 1462182f383db1782af752ecaf607fdff72a8542088bMike Stump return TerminateHandler; 1463182f383db1782af752ecaf607fdff72a8542088bMike Stump 1464f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 14659b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 1466f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Set up the terminate handler. This block is inserted at the very 1467f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // end of the function by FinishFunction. 1468182f383db1782af752ecaf607fdff72a8542088bMike Stump TerminateHandler = createBasicBlock("terminate.handler"); 1469f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.SetInsertPoint(TerminateHandler); 1470f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); 14719b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump TerminateCall->setDoesNotReturn(); 14729b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump TerminateCall->setDoesNotThrow(); 14739b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump Builder.CreateUnreachable(); 14749b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 14753d3ec1c099ec8bfac3aa1fb0126fe515b7c7fa05John McCall // Restore the saved insertion state. 1476f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 147776958099828bac6ebd45abef9f76934b3e99e397Mike Stump 14789b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump return TerminateHandler; 14799b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump} 1480f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1481f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallCodeGenFunction::CleanupBlock::CleanupBlock(CodeGenFunction &CGF, 1482f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CleanupKind Kind) 1483f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall : CGF(CGF), SavedIP(CGF.Builder.saveIP()), NormalCleanupExitBB(0) { 1484f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *EntryBB = CGF.createBasicBlock("cleanup"); 1485f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.SetInsertPoint(EntryBB); 1486f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1487f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall switch (Kind) { 1488f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case NormalAndEHCleanup: 1489f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupEntryBB = EHCleanupEntryBB = EntryBB; 1490f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall break; 1491f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1492f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case NormalCleanup: 1493f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupEntryBB = EntryBB; 1494f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCleanupEntryBB = 0; 1495f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall break; 1496f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1497f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHCleanup: 1498f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupEntryBB = 0; 1499f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCleanupEntryBB = EntryBB; 1500f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.pushTerminate(); 1501f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall break; 1502f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1503f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1504f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1505f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallvoid CodeGenFunction::CleanupBlock::beginEHCleanup() { 1506f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHCleanupEntryBB == 0 && "already started an EH cleanup"); 1507f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupExitBB = CGF.Builder.GetInsertBlock(); 1508f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(NormalCleanupExitBB && "end of normal cleanup is unreachable"); 1509f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1510f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCleanupEntryBB = CGF.createBasicBlock("eh.cleanup"); 1511f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.SetInsertPoint(EHCleanupEntryBB); 1512f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.pushTerminate(); 1513f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1514f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1515f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallCodeGenFunction::CleanupBlock::~CleanupBlock() { 1516f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *EHCleanupExitBB = 0; 1517f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1518f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we're currently writing the EH cleanup... 1519f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EHCleanupEntryBB) { 1520f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Set the EH cleanup exit block. 1521f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCleanupExitBB = CGF.Builder.GetInsertBlock(); 1522f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHCleanupExitBB && "end of EH cleanup is unreachable"); 1523f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1524f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we're actually writing both at once, set the normal exit, too. 1525f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (EHCleanupEntryBB == NormalCleanupEntryBB) 1526f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupExitBB = EHCleanupExitBB; 1527f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1528f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, we must have pushed a terminate handler. 1529f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 1530f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.popTerminate(); 1531f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1532f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, just set the normal cleanup exit block. 1533f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 1534f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NormalCleanupExitBB = CGF.Builder.GetInsertBlock(); 1535f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(NormalCleanupExitBB && "end of normal cleanup is unreachable"); 1536f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1537f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1538f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.pushCleanup(NormalCleanupEntryBB, NormalCleanupExitBB, 1539f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCleanupEntryBB, EHCleanupExitBB); 1540f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1541f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.restoreIP(SavedIP); 1542f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1543f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1544da65ea86482bc116906edfb9ba1d7124f76cc867John McCallvoid EHScopeStack::LazyCleanup::_anchor() {} 1545