diff --git a/gen/runtime.cpp b/gen/runtime.cpp index c6e4af34..3f72ace1 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -898,6 +898,14 @@ static void LLVM_D_BuildRuntimeModule() llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } + // void _d_eh_handle_collision(ptr exc_struct, ptr exc_struct) + { + llvm::StringRef fname("_d_eh_handle_collision"); + LLType *types[] = { voidPtrTy, voidPtrTy }; + LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index e7a454ce..a3036f59 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -74,7 +74,6 @@ void IRLandingPadCatchInfo::toIR() DtoDwarfBlockEnd(); } - void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end) { unpushedScope.catches.push_back(IRLandingPadCatchInfo(catchstmt, end)); @@ -114,23 +113,29 @@ llvm::BasicBlock* IRLandingPad::get() return scopeStack.top().target; } +// creates new landing pad +static llvm::LandingPadInst *createLandingPadInst() +{ + llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality"); + LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), + LLType::getInt32Ty(gIR->context()), + NULL); + return gIR->ir->CreateLandingPad(retType, personality_fn, 0, "landing_pad"); +} + void IRLandingPad::constructLandingPad(IRLandingPadScope scope) { // save and rewrite scope IRScope savedIRScope = gIR->scope(); gIR->scope() = IRScope(scope.target, savedIRScope.end); - // personality fn - llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality"); // create landingpad - LLType *retType = LLStructType::get(LLType::getInt8PtrTy(gIR->context()), LLType::getInt32Ty(gIR->context()), NULL); - llvm::LandingPadInst *landingPad = gIR->ir->CreateLandingPad(retType, personality_fn, 0); + llvm::LandingPadInst *landingPad = createLandingPadInst(); LLValue* eh_ptr = DtoExtractValue(landingPad, 0); LLValue* eh_sel = DtoExtractValue(landingPad, 1); // add landingpad clauses, emit finallys and 'if' chain to catch the exception llvm::Function* eh_typeid_for_fn = GET_INTRINSIC_DECL(eh_typeid_for); - bool isFirstCatch = true; std::stack savedScopeStack = scopeStack; std::deque::iterator catchItr, catchItrEnd; @@ -162,7 +167,26 @@ void IRLandingPad::constructLandingPad(IRLandingPadScope scope) } if (scope.finallyBody) { + // create collision landing pad that handles exceptions thrown inside the finally block + llvm::BasicBlock *collision = llvm::BasicBlock::Create(gIR->context(), "eh.collision", gIR->topfunc(), gIR->scopeend()); + llvm::BasicBlock *bb = gIR->scopebb(); + gIR->scope() = IRScope(collision, gIR->scopeend()); + llvm::LandingPadInst *collisionLandingPad = createLandingPadInst(); + LLValue* collision_eh_ptr = DtoExtractValue(collisionLandingPad, 0); + collisionLandingPad->setCleanup(true); + llvm::Function* collision_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_handle_collision"); + gIR->CreateCallOrInvoke2(collision_fn, collision_eh_ptr, eh_ptr); + gIR->ir->CreateUnreachable(); + gIR->scope() = IRScope(bb, gIR->scopeend()); + + // set collision landing pad as unwind target and emit the body of the finally + DtoDwarfBlockStart(scope.finallyBody->loc); + scopeStack.push(IRLandingPadScope(collision)); + gIR->func()->gen->landingPad = collision; scope.finallyBody->toIR(gIR); + scopeStack.pop(); + gIR->func()->gen->landingPad = get(); + DtoDwarfBlockEnd(); landingPad->setCleanup(true); } diff --git a/ir/irlandingpad.h b/ir/irlandingpad.h index bfff6d9b..708bb256 100644 --- a/ir/irlandingpad.h +++ b/ir/irlandingpad.h @@ -25,6 +25,7 @@ namespace llvm { class Value; class BasicBlock; class Function; + class LandingPadInst; } // holds information about a single catch @@ -49,7 +50,7 @@ struct IRLandingPadCatchInfo // holds information about a single try-catch-inally block struct IRLandingPadScope { - IRLandingPadScope() : target(0), finallyBody(0) {} + explicit IRLandingPadScope(llvm::BasicBlock *target_ = NULL) : target(target_), finallyBody(0) {} // the target for invokes llvm::BasicBlock *target; @@ -80,13 +81,13 @@ struct IRLandingPad // and its infos void pop(); - // gets the current landing pad - llvm::BasicBlock* get(); - // creates or gets storage for exception object llvm::Value* getExceptionStorage(); private: + // gets the current landing pad + llvm::BasicBlock* get(); + // constructs the landing pad void constructLandingPad(IRLandingPadScope scope); diff --git a/runtime/druntime b/runtime/druntime index adaeaf9e..a245e8d2 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit adaeaf9e7b3151d2efb710dca3d79cb724bd30bb +Subproject commit a245e8d2f2f8edce0ead880b5e1d0632df1c2bb1 diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 32aa4872..4616feb4 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 32aa48727a4db7a28878e6f13af603aaa3e0e48d +Subproject commit 4616feb476bc977c21a34d8d3652ea3a3a97c343