Codegen the try block before the catches and finally

This commit is contained in:
Alexey Prokhin
2012-04-06 15:51:12 +04:00
parent 27fadea1b9
commit 2f60c4dcda
3 changed files with 49 additions and 24 deletions

View File

@@ -8,11 +8,39 @@
#include "gen/todebug.h"
#include "ir/irlandingpad.h"
IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end)
: finallyBody(NULL)
IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt_, llvm::BasicBlock* end_) :
finallyBody(NULL), catchstmt(catchstmt_), end(end_)
{
target = llvm::BasicBlock::Create(gIR->context(), "catch", gIR->topfunc(), end);
gIR->scope() = IRScope(target,end);
assert(catchstmt->type);
catchType = catchstmt->type->toBasetype()->isClassHandle();
assert(catchType);
catchType->codegen(Type::sir);
if(catchstmt->var) {
#if DMDV2
if(!catchstmt->var->nestedrefs.dim) {
#else
if(!catchstmt->var->nestedref) {
#endif
gIR->func()->gen->landingPadInfo.getExceptionStorage();
}
}
}
IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt) :
target(NULL), finallyBody(finallystmt), catchstmt(NULL)
{
}
void IRLandingPadInfo::toIR()
{
if (!catchstmt)
return;
gIR->scope() = IRScope(target, target);
DtoDwarfBlockStart(catchstmt->loc);
// assign storage to catch var
@@ -48,19 +76,9 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end)
if (!gIR->scopereturned())
gIR->ir->CreateBr(end);
assert(catchstmt->type);
catchType = catchstmt->type->toBasetype()->isClassHandle();
assert(catchType);
catchType->codegen(Type::sir);
DtoDwarfBlockEnd();
}
IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt)
: target(NULL), finallyBody(finallystmt), catchType(NULL)
{
}
void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
{
@@ -79,17 +97,22 @@ void IRLandingPad::push(llvm::BasicBlock* inBB)
infos.insert(infos.end(), unpushed_infos.begin(), unpushed_infos.end());
unpushed_infos.clear();
constructLandingPad(inBB);
// store as invoke target
padBBs.push(inBB);
gIR->func()->gen->landingPad = get();
}
void IRLandingPad::pop()
{
llvm::BasicBlock *inBB = padBBs.top();
padBBs.pop();
gIR->func()->gen->landingPad = get();
size_t n = nInfos.top();
for (int i = n, c = infos.size(); i < c; ++i)
infos.at(i).toIR();
constructLandingPad(inBB);
infos.resize(n);
nInfos.pop();
}

View File

@@ -19,8 +19,8 @@ namespace llvm {
struct IRLandingPadInfo
{
// default constructor for being able to store in a vector
IRLandingPadInfo()
: target(NULL), finallyBody(NULL), catchType(NULL)
IRLandingPadInfo() :
target(NULL), finallyBody(NULL), catchstmt(NULL)
{}
// constructor for catch
@@ -29,6 +29,9 @@ struct IRLandingPadInfo
// constructor for finally
IRLandingPadInfo(Statement* finallystmt);
// codegen the catch block
void toIR();
// the target catch bb if this is a catch
// or the target finally bb if this is a finally
llvm::BasicBlock* target;
@@ -37,6 +40,8 @@ struct IRLandingPadInfo
Statement* finallyBody;
// nonzero if this is a catch
Catch* catchstmt;
llvm::BasicBlock* end;
ClassDeclaration* catchType;
};
@@ -47,7 +52,7 @@ struct IRLandingPad
{
IRLandingPad() : catch_var(NULL) {}
// builds a new landing pad according to given infos
// creates 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);
@@ -56,7 +61,8 @@ struct IRLandingPad
// add finally information, will be used in next call to push
void addFinally(Statement* finallystmt);
// pops the most recently constructed landing pad bb
// builds the most recently constructed landing pad
// and the catch blocks, then pops the landing pad bb
// and its infos
void pop();