diff --git a/gen/irstate.h b/gen/irstate.h index 45659988..8ac8efe8 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -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 varsInScope; }; struct IRBuilderHelper @@ -157,7 +154,6 @@ 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 8c01cd7b..9f9cf7a3 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -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) diff --git a/gen/toir.cpp b/gen/toir.cpp index adba8ff6..4abf9c0e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -72,7 +72,11 @@ DValue *Expression::toElemDtor(IRState *p) class CallDestructors : public IRLandingPadCatchFinallyInfo { public: - std::vector edtors; + CallDestructors(const std::vector &edtors_) + : edtors(edtors_) + {} + + const std::vector &edtors; void toIR(LLValue */*eh_ptr*/ = 0) { @@ -80,41 +84,64 @@ 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*>(edtors)->push_back(vd->edtor); + } + } + return 0; + } }; - // create finally block that calls destructors on temporaries - CallDestructors *callDestructors = new CallDestructors; - // create landing pad - llvm::BasicBlock *oldend = p->scopeend(); - llvm::BasicBlock *landingpadbb = llvm::BasicBlock::Create(gIR->context(), "landingpad", p->topfunc(), oldend); + // find destructors that must be called + std::vector edtors; + apply(&CallDestructors::searchVarsWithDesctructors, &edtors); - // set up the landing pad - IRLandingPad& pad = gIR->func()->gen->landingPadInfo; - pad.addFinally(callDestructors); - pad.push(landingpadbb); + if (!edtors.empty()) { + // create finally block that calls destructors on temporaries + CallDestructors *callDestructors = new CallDestructors(edtors); - // evaluate expression - size_t starti = p->varsInScope().size(); - DValue *val = toElem(p); - size_t endi = p->varsInScope().size(); + // create landing pad + llvm::BasicBlock *oldend = p->scopeend(); + llvm::BasicBlock *landingpadbb = llvm::BasicBlock::Create(gIR->context(), "landingpad", p->topfunc(), oldend); - // prepare list of the destructors - while (endi-- > starti) { - VarDeclaration *vd = gIR->varsInScope().back(); - gIR->varsInScope().pop_back(); - callDestructors->edtors.push_back(vd->edtor); + // set up the landing pad + IRLandingPad& pad = gIR->func()->gen->landingPadInfo; + pad.addFinally(callDestructors); + pad.push(landingpadbb); + + // evaluate the expression + DValue *val = toElem(p); + + // build the landing pad + llvm::BasicBlock *oldbb = p->scopebb(); + pad.pop(); + + // call the destructors + gIR->scope() = IRScope(oldbb, oldend); + callDestructors->toIR(); + delete callDestructors; + return val; + } else { + return toElem(p); } - - // build the landing pad - llvm::BasicBlock *oldbb = p->scopebb(); - pad.pop(); - - // call the destructors - gIR->scope() = IRScope(oldbb, oldend); - callDestructors->toIR(); - delete callDestructors; - return val; } //////////////////////////////////////////////////////////////////////////////////////////