diff --git a/dmd2/expression.h b/dmd2/expression.h index 53ae8de3..35dd9d10 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -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); diff --git a/gen/irstate.h b/gen/irstate.h index 5461cd6d..86954657 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -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 varsInScope; +#endif }; struct IRBuilderHelper @@ -134,6 +139,7 @@ struct IRState // basic block scopes std::vector scopes; IRScope& scope(); + std::vector &varsInScope() { return scope().varsInScope; } llvm::BasicBlock* scopebb(); llvm::BasicBlock* scopeend(); bool scopereturned(); diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 2acd46d6..68118008 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -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()); diff --git a/gen/statements.cpp b/gen/statements.cpp index 76226af9..d8db4e70 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -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); } diff --git a/gen/toir.cpp b/gen/toir.cpp index de890077..8dc0e1ef 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -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());