Call desctructors on temporary variables

This commit is contained in:
Alexey Prokhin
2011-07-19 19:20:42 +04:00
parent 3c7490e446
commit 2cc34c4005
5 changed files with 64 additions and 22 deletions

View File

@@ -203,6 +203,7 @@ struct Expression : Object
#if IN_LLVM
virtual DValue* toElem(IRState* irs);
DValue *toElemDtor(IRState *irs);
virtual llvm::Constant *toConstElem(IRState *irs);
virtual void cacheLvalue(IRState* irs);

View File

@@ -52,6 +52,11 @@ struct IRScope
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
const IRScope& operator=(const IRScope& rhs);
#if DMDV2
// list of variables needing destruction
std::vector<VarDeclaration*> varsInScope;
#endif
};
struct IRBuilderHelper
@@ -134,6 +139,7 @@ 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

@@ -1037,6 +1037,16 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
if (!vd->isRef())
DtoInitializer(vd->ir.irLocal->value, vd->init); // TODO: Remove altogether?
#if DMDV2
/* 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);
}
#endif
}
return new DVarValue(vd->type, vd, vd->ir.getIrValue());

View File

@@ -92,7 +92,7 @@ void ReturnStatement::toIR(IRState* p)
// get return pointer
DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
DValue* e = exp->toElem(p);
DValue* e = exp->toElemDtor(p);
// store return value
DtoAssign(loc, rvar, e);
@@ -118,7 +118,7 @@ void ReturnStatement::toIR(IRState* p)
else
{
LLValue* v;
DValue* dval = exp->toElem(p);
DValue* dval = exp->toElemDtor(p);
#if DMDV2
// call postblit if necessary
@@ -219,10 +219,10 @@ void ExpStatement::toIR(IRState* p)
// a cast(void) around the expression is allowed, but doesn't require any code
if(exp->op == TOKcast && exp->type == Type::tvoid) {
CastExp* cexp = (CastExp*)exp;
e = cexp->e1->toElem(p);
e = cexp->e1->toElemDtor(p);
}
else
e = exp->toElem(p);
e = exp->toElemDtor(p);
delete e;
}
/*elem* e = exp->toElem(p);
@@ -246,7 +246,7 @@ void IfStatement::toIR(IRState* p)
if (match)
DtoRawVarDeclaration(match);
DValue* cond_e = condition->toElem(p);
DValue* cond_e = condition->toElemDtor(p);
LLValue* cond_val = cond_e->getRVal();
llvm::BasicBlock* oldend = gIR->scopeend();
@@ -347,7 +347,7 @@ void WhileStatement::toIR(IRState* p)
gIR->scope() = IRScope(whilebb,endbb);
// create the condition
DValue* cond_e = condition->toElem(p);
DValue* cond_e = condition->toElemDtor(p);
LLValue* cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
delete cond_e;
@@ -407,7 +407,7 @@ void DoStatement::toIR(IRState* p)
gIR->scope() = IRScope(condbb,endbb);
// create the condition
DValue* cond_e = condition->toElem(p);
DValue* cond_e = condition->toElemDtor(p);
LLValue* cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
delete cond_e;
@@ -454,7 +454,7 @@ void ForStatement::toIR(IRState* p)
LLValue* cond_val;
if (condition)
{
DValue* cond_e = condition->toElem(p);
DValue* cond_e = condition->toElemDtor(p);
cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
delete cond_e;
}
@@ -481,7 +481,7 @@ void ForStatement::toIR(IRState* p)
// increment
if (increment) {
DValue* inc = increment->toElem(p);
DValue* inc = increment->toElemDtor(p);
delete inc;
}
@@ -776,7 +776,7 @@ void ThrowStatement::toIR(IRState* p)
#endif
assert(exp);
DValue* e = exp->toElem(p);
DValue* e = exp->toElemDtor(p);
#ifndef DISABLE_DEBUG_INFO
if (global.params.symdebug) DtoDwarfFuncEnd(gIR->func()->decl);
@@ -842,7 +842,7 @@ static LLValue* call_string_switch_runtime(llvm::Value* table, Expression* e)
}
assert(table->getType() == fn->getFunctionType()->getParamType(0));
DValue* val = e->toElem(gIR);
DValue* val = e->toElemDtor(gIR);
LLValue* llval = val->getRVal();
assert(llval->getType() == fn->getFunctionType()->getParamType(1));
@@ -883,7 +883,7 @@ void SwitchStatement::toIR(IRState* p)
if (cs->exp->op == TOKvar)
vd = ((VarExp*)cs->exp)->var->isVarDeclaration();
if (vd && !vd->init) {
cs->llvmIdx = cs->exp->toElem(p)->getRVal();
cs->llvmIdx = cs->exp->toElemDtor(p)->getRVal();
useSwitchInst = false;
}
}
@@ -965,7 +965,7 @@ void SwitchStatement::toIR(IRState* p)
LLValue* condVal;
// integral switch
if (condition->type->isintegral()) {
DValue* cond = condition->toElem(p);
DValue* cond = condition->toElemDtor(p);
condVal = cond->getRVal();
}
// string switch
@@ -983,7 +983,7 @@ void SwitchStatement::toIR(IRState* p)
}
else
{ // we can't use switch, so we will use a bunch of br instructions instead
DValue* cond = condition->toElem(p);
DValue* cond = condition->toElemDtor(p);
LLValue *condVal = cond->getRVal();
llvm::BasicBlock* nextbb = llvm::BasicBlock::Create(gIR->context(), "checkcase", p->topfunc(), oldend);
@@ -1177,7 +1177,7 @@ void ForeachStatement::toIR(IRState* p)
}
// what to iterate
DValue* aggrval = aggr->toElem(p);
DValue* aggrval = aggr->toElemDtor(p);
// get length and pointer
LLValue* niters = DtoArrayLen(aggrval);
@@ -1281,9 +1281,9 @@ void ForeachRangeStatement::toIR(IRState* p)
// evaluate lwr/upr
assert(lwr->type->isintegral());
LLValue* lower = lwr->toElem(p)->getRVal();
LLValue* lower = lwr->toElemDtor(p)->getRVal();
assert(upr->type->isintegral());
LLValue* upper = upr->toElem(p)->getRVal();
LLValue* upper = upr->toElemDtor(p)->getRVal();
// handle key
assert(key->type->isintegral());
@@ -1506,7 +1506,7 @@ void WithStatement::toIR(IRState* p)
// with(..) can either be used with expressions or with symbols
// wthis == null indicates the symbol form
if (wthis) {
DValue* e = exp->toElem(p);
DValue* e = exp->toElemDtor(p);
LLValue* mem = DtoRawVarDeclaration(wthis);
DtoStore(e->getRVal(), mem);
}

View File

@@ -56,6 +56,31 @@ void Expression::cacheLvalue(IRState* irs)
fatal();
}
/*******************************************
* Evaluate Expression, then call destructors on any temporaries in it.
*/
DValue *Expression::toElemDtor(IRState *irs)
{
#if DMDV2
Logger::println("Expression::toElemDtor(): %s", toChars());
size_t starti = irs->varsInScope().size();
DValue *val = toElem(irs);
size_t endi = irs->varsInScope().size();
// Add destructors
while (endi-- > starti)
{
VarDeclaration *vd = gIR->varsInScope().back();
gIR->varsInScope().pop_back();
vd->edtor->toElem(gIR);
}
return val;
#else
return toElem(irs);
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* DeclarationExp::toElem(IRState* p)
@@ -2045,7 +2070,7 @@ DValue* AndAndExp::toElem(IRState* p)
llvm::BranchInst::Create(andand,andandend,ubool,p->scopebb());
p->scope() = IRScope(andand, andandend);
DValue* v = e2->toElem(p);
DValue* v = e2->toElemDtor(p);
LLValue* vbool = 0;
if (!v->isFunc() && v->getType() != Type::tvoid)
@@ -2092,7 +2117,7 @@ DValue* OrOrExp::toElem(IRState* p)
llvm::BranchInst::Create(ororend,oror,ubool,p->scopebb());
p->scope() = IRScope(oror, ororend);
DValue* v = e2->toElem(p);
DValue* v = e2->toElemDtor(p);
LLValue* vbool = 0;
if (v && !v->isFunc() && v->getType() != Type::tvoid)
@@ -2359,13 +2384,13 @@ DValue* CondExp::toElem(IRState* p)
llvm::BranchInst::Create(condtrue,condfalse,cond_val,p->scopebb());
p->scope() = IRScope(condtrue, condfalse);
DValue* u = e1->toElem(p);
DValue* u = e1->toElemDtor(p);
if (dtype->ty != Tvoid)
DtoAssign(loc, dvv, u);
llvm::BranchInst::Create(condend,p->scopebb());
p->scope() = IRScope(condfalse, condend);
DValue* v = e2->toElem(p);
DValue* v = e2->toElemDtor(p);
if (dtype->ty != Tvoid)
DtoAssign(loc, dvv, v);
llvm::BranchInst::Create(condend,p->scopebb());