mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
[svn r340] Rework exception handling to work with nested tryfinally and trycatch.
This commit is contained in:
@@ -172,10 +172,6 @@ struct IRState
|
||||
llvm::BasicBlock* scopeend();
|
||||
bool scopereturned();
|
||||
|
||||
// landing pads for try statements
|
||||
typedef std::vector<llvm::BasicBlock*> BBVec;
|
||||
BBVec landingPads;
|
||||
|
||||
// create a call or invoke, depending on the landing pad info
|
||||
// the template function is defined further down in this file
|
||||
template <typename InputIterator>
|
||||
@@ -229,15 +225,16 @@ struct IRState
|
||||
template <typename InputIterator>
|
||||
CallOrInvoke* IRState::CreateCallOrInvoke(LLValue* Callee, InputIterator ArgBegin, InputIterator ArgEnd, const char* Name)
|
||||
{
|
||||
if(landingPads.empty())
|
||||
return new CallOrInvoke_Call(ir->CreateCall(Callee, ArgBegin, ArgEnd, Name));
|
||||
else
|
||||
llvm::BasicBlock* pad;
|
||||
if(pad = func()->landingPad.get())
|
||||
{
|
||||
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create("postinvoke", topfunc(), scopeend());
|
||||
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, *landingPads.rbegin(), ArgBegin, ArgEnd, Name);
|
||||
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, pad, ArgBegin, ArgEnd, Name);
|
||||
scope() = IRScope(postinvoke, scopeend());
|
||||
return new CallOrInvoke_Invoke(invoke);
|
||||
}
|
||||
else
|
||||
return new CallOrInvoke_Call(ir->CreateCall(Callee, ArgBegin, ArgEnd, Name));
|
||||
}
|
||||
|
||||
#endif // LLVMDC_GEN_IRSTATE_H
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "gen/dvalue.h"
|
||||
|
||||
#include "ir/irfunction.h"
|
||||
#include "ir/irlandingpad.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -497,19 +498,25 @@ void TryFinallyStatement::toIR(IRState* p)
|
||||
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
|
||||
assert(!gIR->scopereturned());
|
||||
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 @@ void TryFinallyStatement::toIR(IRState* p)
|
||||
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 @@ void TryFinallyStatement::toIR(IRState* p)
|
||||
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);
|
||||
}
|
||||
@@ -592,11 +566,24 @@ void TryCatchStatement::toIR(IRState* p)
|
||||
assert(!gIR->scopereturned());
|
||||
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 @@ void TryCatchStatement::toIR(IRState* p)
|
||||
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);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LLVMDC_IR_IRFUNCTION_H
|
||||
|
||||
#include "ir/ir.h"
|
||||
#include "ir/irlandingpad.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -25,6 +26,9 @@ struct IrFunction : IrBase
|
||||
llvm::AllocaInst* srcfileArg;
|
||||
llvm::AllocaInst* msgArg;
|
||||
|
||||
// landing pads for try statements
|
||||
IRLandingPad landingPad;
|
||||
|
||||
IrFunction(FuncDeclaration* fd);
|
||||
};
|
||||
|
||||
|
||||
186
ir/irlandingpad.cpp
Normal file
186
ir/irlandingpad.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#include "gen/llvm.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/runtime.h"
|
||||
#include "gen/logger.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "ir/irlandingpad.h"
|
||||
|
||||
IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end)
|
||||
: finallyBody(NULL)
|
||||
{
|
||||
target = llvm::BasicBlock::Create("catch", gIR->topfunc(), end);
|
||||
gIR->scope() = IRScope(target,end);
|
||||
|
||||
// assign storage to catch var
|
||||
if(catchstmt->var) {
|
||||
assert(!catchstmt->var->ir.irLocal);
|
||||
catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var);
|
||||
LLValue* catch_var = gIR->func()->landingPad.getExceptionStorage();
|
||||
catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type)));
|
||||
}
|
||||
|
||||
// emit handler
|
||||
assert(catchstmt->handler);
|
||||
catchstmt->handler->toIR(gIR);
|
||||
|
||||
if (!gIR->scopereturned())
|
||||
gIR->ir->CreateBr(end);
|
||||
|
||||
assert(catchstmt->type);
|
||||
catchType = catchstmt->type->isClassHandle();
|
||||
DtoForceDeclareDsymbol(catchType);
|
||||
assert(catchType);
|
||||
}
|
||||
|
||||
IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt)
|
||||
: target(NULL), finallyBody(finallystmt), catchType(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
|
||||
{
|
||||
unpushed_infos.push_front(IRLandingPadInfo(catchstmt, end));
|
||||
}
|
||||
|
||||
void IRLandingPad::addFinally(Statement* finallystmt)
|
||||
{
|
||||
unpushed_infos.push_front(IRLandingPadInfo(finallystmt));
|
||||
}
|
||||
|
||||
void IRLandingPad::push(llvm::BasicBlock* inBB)
|
||||
{
|
||||
// store infos such that matches are right to left
|
||||
nInfos.push(infos.size());
|
||||
infos.insert(infos.end(), unpushed_infos.begin(), unpushed_infos.end());
|
||||
unpushed_infos.clear();
|
||||
|
||||
constructLandingPad(inBB);
|
||||
|
||||
// store as invoke target
|
||||
padBBs.push(inBB);
|
||||
}
|
||||
|
||||
void IRLandingPad::pop()
|
||||
{
|
||||
padBBs.pop();
|
||||
|
||||
size_t n = nInfos.top();
|
||||
infos.resize(n);
|
||||
nInfos.pop();
|
||||
}
|
||||
|
||||
llvm::BasicBlock* IRLandingPad::get()
|
||||
{
|
||||
if(padBBs.size() == 0)
|
||||
return NULL;
|
||||
else
|
||||
return padBBs.top();
|
||||
}
|
||||
|
||||
void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
|
||||
{
|
||||
// save and rewrite scope
|
||||
IRScope savedscope = gIR->scope();
|
||||
gIR->scope() = IRScope(inBB,savedscope.end);
|
||||
|
||||
// eh_ptr = llvm.eh.exception();
|
||||
llvm::Function* eh_exception_fn = GET_INTRINSIC_DECL(eh_exception);
|
||||
LLValue* eh_ptr = gIR->ir->CreateCall(eh_exception_fn);
|
||||
|
||||
// build selector arguments
|
||||
LLSmallVector<LLValue*, 6> selectorargs;
|
||||
selectorargs.push_back(eh_ptr);
|
||||
|
||||
llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
|
||||
LLValue* personality_fn_arg = gIR->ir->CreateBitCast(personality_fn, getPtrToType(LLType::Int8Ty));
|
||||
selectorargs.push_back(personality_fn_arg);
|
||||
|
||||
bool hasFinally = false;
|
||||
// associate increasing ints with each unique classdecl encountered
|
||||
std::map<ClassDeclaration*, int> catchToInt;
|
||||
std::deque<IRLandingPadInfo>::reverse_iterator it = infos.rbegin(), end = infos.rend();
|
||||
for(size_t i = infos.size() - 1; it != end; ++it, --i)
|
||||
{
|
||||
if(it->finallyBody)
|
||||
hasFinally = true;
|
||||
else
|
||||
{
|
||||
if(catchToInt.find(it->catchType) == catchToInt.end())
|
||||
{
|
||||
int newval = catchToInt.size();
|
||||
catchToInt[it->catchType] = newval;
|
||||
}
|
||||
assert(it->catchType);
|
||||
assert(it->catchType->ir.irStruct);
|
||||
selectorargs.push_back(it->catchType->ir.irStruct->classInfo);
|
||||
}
|
||||
}
|
||||
// if there's a finally, the eh table has to have a 0 action
|
||||
if(hasFinally)
|
||||
selectorargs.push_back(llvm::ConstantInt::get(LLType::Int32Ty, 0));
|
||||
// if there is a catch, store exception object
|
||||
if(catchToInt.size())
|
||||
{
|
||||
const LLType* objectTy = DtoType(ClassDeclaration::object->type);
|
||||
assert(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, <selectorargs>);
|
||||
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);
|
||||
LLValue* eh_sel = gIR->ir->CreateCall(eh_selector_fn, selectorargs.begin(), selectorargs.end());
|
||||
|
||||
// emit finallys and switches that branch to catches until there are no more catches
|
||||
// then simply branch to the finally chain
|
||||
llvm::SwitchInst* switchinst = NULL;
|
||||
for(it = infos.rbegin(); it != end; ++it)
|
||||
{
|
||||
// if it's a finally, emit its code
|
||||
if(it->finallyBody)
|
||||
{
|
||||
if(switchinst)
|
||||
switchinst = NULL;
|
||||
it->finallyBody->toIR(gIR);
|
||||
}
|
||||
// otherwise it's a catch and we'll add a switch case
|
||||
else
|
||||
{
|
||||
if(!switchinst)
|
||||
{
|
||||
switchinst = gIR->ir->CreateSwitch(eh_sel, llvm::BasicBlock::Create("switchdefault", gIR->topfunc(), gIR->scopeend()), infos.size());
|
||||
gIR->scope() = IRScope(switchinst->getDefaultDest(), gIR->scopeend());
|
||||
}
|
||||
// catches matched first get the largest switchval, so do size - unique int
|
||||
llvm::ConstantInt* switchval = llvm::ConstantInt::get(LLType::Int32Ty, catchToInt.size() - catchToInt[it->catchType]);
|
||||
// and make sure we don't add the same switchval twice, may happen with nested trys
|
||||
if(!switchinst->findCaseValue(switchval))
|
||||
switchinst->addCase(switchval, it->target);
|
||||
}
|
||||
}
|
||||
|
||||
// no catch matched and all finallys executed - resume unwind
|
||||
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();
|
||||
|
||||
gIR->scope() = savedscope;
|
||||
}
|
||||
|
||||
LLValue* IRLandingPad::getExceptionStorage()
|
||||
{
|
||||
if(!catch_var)
|
||||
{
|
||||
Logger::println("Making new catch var");
|
||||
const LLType* objectTy = DtoType(ClassDeclaration::object->type);
|
||||
catch_var = new llvm::AllocaInst(objectTy,"catchvar",gIR->topallocapoint());
|
||||
}
|
||||
return catch_var;
|
||||
}
|
||||
70
ir/irlandingpad.h
Normal file
70
ir/irlandingpad.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef LLVMDC_IR_IRLANDINGPADINFO_H
|
||||
#define LLVMDC_IR_IRLANDINGPADINFO_H
|
||||
|
||||
#include "ir/ir.h"
|
||||
#include "statement.h"
|
||||
|
||||
#include <deque>
|
||||
#include <stack>
|
||||
|
||||
struct IRLandingPadInfo
|
||||
{
|
||||
// default constructor for being able to store in a vector
|
||||
IRLandingPadInfo()
|
||||
: target(NULL), finallyBody(NULL), catchType(NULL)
|
||||
{}
|
||||
|
||||
IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end);
|
||||
IRLandingPadInfo(Statement* finallystmt);
|
||||
|
||||
// the target catch bb if this is a catch
|
||||
// or the target finally bb if this is a finally
|
||||
llvm::BasicBlock* target;
|
||||
|
||||
// nonzero if this is a finally
|
||||
Statement* finallyBody;
|
||||
|
||||
// nonzero if this is a catch
|
||||
ClassDeclaration* catchType;
|
||||
};
|
||||
|
||||
struct IRLandingPad
|
||||
{
|
||||
IRLandingPad() : catch_var(NULL) {}
|
||||
|
||||
// builds a new landing pad according to given infos
|
||||
// and the ones on the stack. also stores it as invoke target
|
||||
void push(llvm::BasicBlock* inBB);
|
||||
|
||||
void addCatch(Catch* catchstmt, llvm::BasicBlock* end);
|
||||
void addFinally(Statement* finallystmt);
|
||||
|
||||
// pops the most recently constructed landing pad bb
|
||||
// and its infos
|
||||
void pop();
|
||||
|
||||
// gets the current landing pad
|
||||
llvm::BasicBlock* get();
|
||||
|
||||
// creates or gets storage for exception object
|
||||
LLValue* getExceptionStorage();
|
||||
|
||||
private:
|
||||
// constructs the landing pad from infos
|
||||
void constructLandingPad(llvm::BasicBlock* inBB);
|
||||
|
||||
// information needed to create landing pads
|
||||
std::deque<IRLandingPadInfo> infos;
|
||||
std::deque<IRLandingPadInfo> unpushed_infos;
|
||||
|
||||
// the number of infos we had before the push
|
||||
std::stack<size_t> nInfos;
|
||||
|
||||
// the target for invokes
|
||||
std::stack<llvm::BasicBlock*> padBBs;
|
||||
|
||||
// storage for the catch variable
|
||||
LLValue* catch_var;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import util.console;
|
||||
|
||||
//debug = EH_personality;
|
||||
// debug = EH_personality;
|
||||
|
||||
private extern(C) void abort();
|
||||
private extern(C) int printf(char*, ...);
|
||||
@@ -251,6 +251,7 @@ private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions,
|
||||
|
||||
else if(actions & _Unwind_Action.HANDLER_PHASE)
|
||||
{
|
||||
debug(EH_personality) printf("Setting switch value to: %d!\n", switchval);
|
||||
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
|
||||
_Unwind_SetGR(context, eh_selector_regno, switchval);
|
||||
_Unwind_SetIP(context, landing_pad);
|
||||
@@ -269,6 +270,7 @@ private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions
|
||||
debug(EH_personality) printf("Calling cleanup routine...\n");
|
||||
|
||||
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
|
||||
_Unwind_SetGR(context, eh_selector_regno, 0);
|
||||
_Unwind_SetIP(context, landing_pad);
|
||||
return _Unwind_Reason_Code.INSTALL_CONTEXT;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user