mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 16:43:13 +01:00
Properly implement exception chaining
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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<IRLandingPadScope> savedScopeStack = scopeStack;
|
||||
std::deque<IRLandingPadCatchInfo>::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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Submodule runtime/druntime updated: adaeaf9e7b...a245e8d2f2
Submodule tests/d2/dmd-testsuite updated: 32aa48727a...4616feb476
Reference in New Issue
Block a user