From 5b799deeb435e62d453986698403836e004ecfdb Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 23 May 2009 00:23:39 +0200 Subject: [PATCH] Fix #308 by giving finally code emitted by EnclosingTryFinally a different landing pad. --- gen/irstate.h | 4 ++-- gen/llvmhelpers.cpp | 5 +++++ gen/llvmhelpers.h | 4 +++- gen/statements.cpp | 20 ++++++++++++-------- ir/irfunction.cpp | 2 ++ ir/irfunction.h | 3 ++- ir/irlandingpad.cpp | 6 +++--- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/gen/irstate.h b/gen/irstate.h index d9e532ad..f4f7e27a 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -175,8 +175,8 @@ struct IRState template llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, InputIterator ArgBegin, InputIterator ArgEnd, const char* Name) { - llvm::BasicBlock* pad; - if(pad = func()->landingPad.get()) + llvm::BasicBlock* pad = func()->landingPad; + if(pad) { // intrinsics don't support invoking and 'nounwind' functions don't need it. LLFunction* funcval = llvm::dyn_cast(Callee); diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 2edf5ac1..939043f1 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -255,7 +255,12 @@ void EnclosingVolatile::emitCode(IRState * p) void EnclosingTryFinally::emitCode(IRState * p) { if (tf->finalbody) + { + llvm::BasicBlock* oldpad = p->func()->landingPad; + p->func()->landingPad = landingPad; tf->finalbody->toIR(p); + p->func()->landingPad = oldpad; + } } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 391fe820..a62f8cd1 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -15,8 +15,10 @@ struct EnclosingHandler struct EnclosingTryFinally : EnclosingHandler { TryFinallyStatement* tf; + llvm::BasicBlock* landingPad; void emitCode(IRState* p); - EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {} + EnclosingTryFinally(TryFinallyStatement* _tf, llvm::BasicBlock* _pad) + : tf(_tf), landingPad(_pad) {} }; struct EnclosingVolatile : EnclosingHandler { diff --git a/gen/statements.cpp b/gen/statements.cpp index 31bf8a73..bbb4e51b 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -592,8 +592,10 @@ void TryFinallyStatement::toIR(IRState* p) p->scope() = IRScope(landingpadbb, endbb); assert(finalbody); - gIR->func()->landingPad.addFinally(finalbody); - gIR->func()->landingPad.push(landingpadbb); + gIR->func()->targetScopes.push_back(IRTargetScope(this,new EnclosingTryFinally(this,gIR->func()->landingPad),NULL,NULL)); + gIR->func()->landingPadInfo.addFinally(finalbody); + gIR->func()->landingPadInfo.push(landingpadbb); + gIR->func()->landingPad = gIR->func()->landingPadInfo.get(); // // do the try block @@ -601,15 +603,15 @@ void TryFinallyStatement::toIR(IRState* p) p->scope() = IRScope(trybb,finallybb); assert(body); - p->func()->targetScopes.push_back(IRTargetScope(this,new EnclosingTryFinally(this),NULL,NULL)); body->toIR(p); - p->func()->targetScopes.pop_back(); // terminate try BB if (!p->scopereturned()) llvm::BranchInst::Create(finallybb, p->scopebb()); - gIR->func()->landingPad.pop(); + gIR->func()->landingPadInfo.pop(); + gIR->func()->landingPad = gIR->func()->landingPadInfo.get(); + gIR->func()->targetScopes.pop_back(); // // do finally block @@ -658,10 +660,11 @@ void TryCatchStatement::toIR(IRState* p) for (int i = 0; i < catches->dim; i++) { Catch *c = (Catch *)catches->data[i]; - gIR->func()->landingPad.addCatch(c, endbb); + gIR->func()->landingPadInfo.addCatch(c, endbb); } - gIR->func()->landingPad.push(landingpadbb); + gIR->func()->landingPadInfo.push(landingpadbb); + gIR->func()->landingPad = gIR->func()->landingPadInfo.get(); // // do the try block @@ -674,7 +677,8 @@ void TryCatchStatement::toIR(IRState* p) if (!gIR->scopereturned()) llvm::BranchInst::Create(endbb, p->scopebb()); - gIR->func()->landingPad.pop(); + gIR->func()->landingPadInfo.pop(); + gIR->func()->landingPad = gIR->func()->landingPadInfo.get(); // rewrite the scope p->scope() = IRScope(endbb,oldend); diff --git a/ir/irfunction.cpp b/ir/irfunction.cpp index fdadf31f..52197615 100644 --- a/ir/irfunction.cpp +++ b/ir/irfunction.cpp @@ -117,6 +117,8 @@ IrFunction::IrFunction(FuncDeclaration* fd) _arguments = NULL; _argptr = NULL; + landingPad = NULL; + nextUnique.push(0); } diff --git a/ir/irfunction.h b/ir/irfunction.h index 04dfe5ae..619a7084 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -70,7 +70,8 @@ struct IrFunction : IrBase LabelToBBMap labelToBB; // landing pads for try statements - IRLandingPad landingPad; + IRLandingPad landingPadInfo; + llvm::BasicBlock* landingPad; // loop blocks typedef std::vector TargetScopeVec; diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 5c7fab14..d0a6280a 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -24,7 +24,7 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) #endif assert(!catchstmt->var->ir.irLocal); catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var); - LLValue* catch_var = gIR->func()->landingPad.getExceptionStorage(); + LLValue* catch_var = gIR->func()->landingPadInfo.getExceptionStorage(); catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type))); } @@ -32,8 +32,8 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) DtoDeclarationExp(catchstmt->var); // the exception will only be stored in catch_var. copy it over if necessary - if(catchstmt->var->ir.irLocal->value != gIR->func()->landingPad.getExceptionStorage()) { - LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->landingPad.getExceptionStorage()), DtoType(catchstmt->var->type)); + if(catchstmt->var->ir.irLocal->value != gIR->func()->landingPadInfo.getExceptionStorage()) { + LLValue* exc = gIR->ir->CreateBitCast(DtoLoad(gIR->func()->landingPadInfo.getExceptionStorage()), DtoType(catchstmt->var->type)); DtoStore(exc, catchstmt->var->ir.irLocal->value); } }