Mercurial > projects > ldc
diff gen/statements.cpp @ 319:e9c93739bc4c trunk
[svn r340] Rework exception handling to work with nested tryfinally and trycatch.
author | ChristianK |
---|---|
date | Sat, 05 Jul 2008 10:22:56 +0200 |
parents | a9697749e898 |
children | 04e1b4930975 |
line wrap: on
line diff
--- a/gen/statements.cpp Fri Jul 04 09:00:49 2008 +0200 +++ b/gen/statements.cpp Sat Jul 05 10:22:56 2008 +0200 @@ -27,6 +27,7 @@ #include "gen/dvalue.h" #include "ir/irfunction.h" +#include "ir/irlandingpad.h" ////////////////////////////////////////////////////////////////////////////// @@ -497,8 +498,7 @@ llvm::BasicBlock* trybb = llvm::BasicBlock::Create("try", p->topfunc(), oldend); llvm::BasicBlock* finallybb = llvm::BasicBlock::Create("finally", p->topfunc(), oldend); // the landing pad for statements in the try block - // only reached via eh-unwinding, a call to resume unwinding is appended - llvm::BasicBlock* unwindfinallybb = llvm::BasicBlock::Create("unwindfinally", p->topfunc(), oldend); + llvm::BasicBlock* landingpadbb = llvm::BasicBlock::Create("landingpad", p->topfunc(), oldend); llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endtryfinally", p->topfunc(), oldend); // pass the previous BB into this @@ -506,10 +506,17 @@ llvm::BranchInst::Create(trybb, p->scopebb()); // + // set up the landing pad + // + p->scope() = IRScope(landingpadbb, endbb); + + gIR->func()->landingPad.addFinally(finalbody); + gIR->func()->landingPad.push(landingpadbb); + + // // do the try block // p->scope() = IRScope(trybb,finallybb); - p->landingPads.push_back(unwindfinallybb); assert(body); body->toIR(p); @@ -518,12 +525,12 @@ if (!p->scopereturned()) llvm::BranchInst::Create(finallybb, p->scopebb()); - p->landingPads.pop_back(); + gIR->func()->landingPad.pop(); // // do finally block // - p->scope() = IRScope(finallybb,unwindfinallybb); + p->scope() = IRScope(finallybb,landingpadbb); assert(finalbody); finalbody->toIR(p); @@ -533,39 +540,6 @@ llvm::BranchInst::Create(endbb, p->scopebb()); } - // - // do landing pad - // - p->scope() = IRScope(unwindfinallybb,endbb); - - // eh_ptr = llvm.eh.exception(); - llvm::Function* eh_exception_fn = GET_INTRINSIC_DECL(eh_exception); - LLValue* eh_ptr = gIR->ir->CreateCall(eh_exception_fn); - - // eh_sel = llvm.eh.selector(eh_ptr, cast(byte*)&_d_eh_personality, 0); - llvm::Function* eh_selector_fn; - if (global.params.is64bit) - eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i64); - else - eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i32); - llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality"); - LLValue* personality_fn_arg = gIR->ir->CreateBitCast(personality_fn, getPtrToType(LLType::Int8Ty)); - LLValue* eh_sel = gIR->ir->CreateCall3(eh_selector_fn, eh_ptr, personality_fn_arg, llvm::ConstantInt::get(LLType::Int32Ty, 0)); - - // emit finally code - finalbody->toIR(p); - - // finally code may not be terminated! - if (gIR->scopereturned()) { - error("finally blocks may not be terminated", loc.toChars()); - fatal(); - } - - llvm::Function* unwind_resume_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_resume_unwind"); - gIR->ir->CreateCall(unwind_resume_fn, eh_ptr); - - gIR->ir->CreateUnreachable(); - // rewrite the scope p->scope() = IRScope(endbb,oldend); } @@ -593,10 +567,23 @@ llvm::BranchInst::Create(trybb, p->scopebb()); // + // do catches and the landing pad + // + assert(catches); + gIR->scope() = IRScope(landingpadbb, endbb); + + for (int i = 0; i < catches->dim; i++) + { + Catch *c = (Catch *)catches->data[i]; + gIR->func()->landingPad.addCatch(c, endbb); + } + + gIR->func()->landingPad.push(landingpadbb); + + // // do the try block // p->scope() = IRScope(trybb,landingpadbb); - p->landingPads.push_back(landingpadbb); assert(body); body->toIR(p); @@ -604,94 +591,7 @@ if (!gIR->scopereturned()) llvm::BranchInst::Create(endbb, p->scopebb()); - p->landingPads.pop_back(); - - // - // do catches - // - assert(catches); - - // get storage for exception var - const LLType* objectTy = DtoType(ClassDeclaration::object->type); - llvm::AllocaInst* catch_var = new llvm::AllocaInst(objectTy,"catchvar",p->topallocapoint()); - - // for further reference in landing pad - LLSmallVector<llvm::BasicBlock*,4> catch_bbs; - - for (int i = 0; i < catches->dim; i++) - { - Catch *c = (Catch *)catches->data[i]; - - llvm::BasicBlock* catchbb = llvm::BasicBlock::Create("catch", p->topfunc(), oldend); - catch_bbs.push_back(catchbb); - p->scope() = IRScope(catchbb,oldend); - - // assign storage to catch var - if(c->var) { - assert(!c->var->ir.irLocal); - c->var->ir.irLocal = new IrLocal(c->var); - c->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(c->var->type))); - } - - // emit handler - assert(c->handler); - c->handler->toIR(p); - - if (!gIR->scopereturned()) - llvm::BranchInst::Create(endbb, p->scopebb()); - } - - // - // do landing pad - // - p->scope() = IRScope(landingpadbb,endbb); - - // eh_ptr = llvm.eh.exception(); - llvm::Function* eh_exception_fn = GET_INTRINSIC_DECL(eh_exception); - LLValue* eh_ptr = gIR->ir->CreateCall(eh_exception_fn); - - // store eh_ptr in catch_var - gIR->ir->CreateStore(gIR->ir->CreateBitCast(eh_ptr, objectTy), catch_var); - - // eh_sel = llvm.eh.selector(eh_ptr, cast(byte*)&_d_eh_personality, <classinfos>); - llvm::Function* eh_selector_fn; - if (global.params.is64bit) - eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i64); - else - eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i32); - - LLSmallVector<LLValue*,4> args; - args.push_back(eh_ptr); - llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality"); - args.push_back(gIR->ir->CreateBitCast(personality_fn, getPtrToType(LLType::Int8Ty))); - for (int i = 0; i < catches->dim; i++) - { - Catch *c = (Catch *)catches->data[i]; - assert(c->type); - ClassDeclaration* cdecl = c->type->isClassHandle(); - assert(cdecl); - assert(cdecl->ir.irStruct); - args.push_back(cdecl->ir.irStruct->classInfo); - } - - LLValue* eh_sel = gIR->ir->CreateCall(eh_selector_fn, args.begin(), args.end()); - - // switch on eh_sel and branch to correct case - - // setup default target - llvm::BasicBlock* defaulttarget = llvm::BasicBlock::Create("default", p->topfunc(), oldend); - //TODO: Error handling? - new llvm::UnreachableInst(defaulttarget); - - llvm::SwitchInst* sw = p->ir->CreateSwitch(eh_sel, defaulttarget, catch_bbs.size()); - - // add all catches as cases - for(unsigned int c = 0; c < catch_bbs.size(); ++c) - { - llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), oldend); - llvm::BranchInst::Create(catch_bbs[c], casebb); - sw->addCase(llvm::ConstantInt::get(LLType::Int32Ty, c+1), casebb); - } + gIR->func()->landingPad.pop(); // rewrite the scope p->scope() = IRScope(endbb,oldend);