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);