Issue #426 part 2. Generate a try-finally block only if it is required

(i.e. there are actually some destructor calls that are needed to be put into finally)
This commit is contained in:
Alexey Prokhin 2013-07-10 12:45:41 +04:00
parent 71023952d4
commit 1999749415
3 changed files with 57 additions and 43 deletions

View file

@ -72,9 +72,6 @@ struct IRScope
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
const IRScope& operator=(const IRScope& rhs);
// list of variables needing destruction
std::vector<VarDeclaration*> varsInScope;
};
struct IRBuilderHelper
@ -157,7 +154,6 @@ struct IRState
// basic block scopes
std::vector<IRScope> scopes;
IRScope& scope();
std::vector<VarDeclaration*> &varsInScope() { return scope().varsInScope; }
llvm::BasicBlock* scopebb();
llvm::BasicBlock* scopeend();
bool scopereturned();

View file

@ -1055,7 +1055,7 @@ void DtoVarDeclaration(VarDeclaration* vd)
{
vd->ir.irLocal->value = val;
}
goto Lexit;
return;
}
}
}
@ -1087,15 +1087,6 @@ void DtoVarDeclaration(VarDeclaration* vd)
ex->exp->toElem(gIR);
}
}
Lexit:
/* Mark the point of construction of a variable that needs to be destructed.
*/
if (vd->edtor && !vd->noscope)
{
// Put vd on list of things needing destruction
gIR->varsInScope().push_back(vd);
}
}
DValue* DtoDeclarationExp(Dsymbol* declaration)

View file

@ -72,7 +72,11 @@ DValue *Expression::toElemDtor(IRState *p)
class CallDestructors : public IRLandingPadCatchFinallyInfo {
public:
std::vector<Expression*> edtors;
CallDestructors(const std::vector<Expression*> &edtors_)
: edtors(edtors_)
{}
const std::vector<Expression*> &edtors;
void toIR(LLValue */*eh_ptr*/ = 0)
{
@ -80,10 +84,39 @@ DValue *Expression::toElemDtor(IRState *p)
for (itr = edtors.rbegin(); itr != end; ++itr)
(*itr)->toElem(gIR);
}
static int searchVarsWithDesctructors(Expression *exp, void *edtors)
{
if (exp->op == TOKdeclaration) {
DeclarationExp *de = (DeclarationExp*)exp;
if (VarDeclaration *vd = de->declaration->isVarDeclaration()) {
while (vd->aliassym) {
vd = vd->aliassym->isVarDeclaration();
if (!vd)
return 0;
}
if (vd->init) {
if (ExpInitializer *ex = vd->init->isExpInitializer())
ex->exp->apply(&searchVarsWithDesctructors, edtors);
}
if (!vd->isDataseg() && vd->edtor && !vd->noscope)
static_cast<std::vector<Expression*>*>(edtors)->push_back(vd->edtor);
}
}
return 0;
}
};
// find destructors that must be called
std::vector<Expression*> edtors;
apply(&CallDestructors::searchVarsWithDesctructors, &edtors);
if (!edtors.empty()) {
// create finally block that calls destructors on temporaries
CallDestructors *callDestructors = new CallDestructors;
CallDestructors *callDestructors = new CallDestructors(edtors);
// create landing pad
llvm::BasicBlock *oldend = p->scopeend();
@ -94,17 +127,8 @@ DValue *Expression::toElemDtor(IRState *p)
pad.addFinally(callDestructors);
pad.push(landingpadbb);
// evaluate expression
size_t starti = p->varsInScope().size();
// evaluate the expression
DValue *val = toElem(p);
size_t endi = p->varsInScope().size();
// prepare list of the destructors
while (endi-- > starti) {
VarDeclaration *vd = gIR->varsInScope().back();
gIR->varsInScope().pop_back();
callDestructors->edtors.push_back(vd->edtor);
}
// build the landing pad
llvm::BasicBlock *oldbb = p->scopebb();
@ -115,6 +139,9 @@ DValue *Expression::toElemDtor(IRState *p)
callDestructors->toIR();
delete callDestructors;
return val;
} else {
return toElem(p);
}
}
//////////////////////////////////////////////////////////////////////////////////////////