From 71023952d43b570ef7ebd9586a5a12527b56a990 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Wed, 10 Jul 2013 12:38:15 +0400 Subject: [PATCH] Issue #426 part 1. Wrap destructor calls of temporary variables in a try/finally expression. --- gen/toir.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index bb3fc730..adba8ff6 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -38,6 +38,7 @@ #include "gen/warnings.h" #include "ir/irtypeclass.h" #include "ir/irtypestruct.h" +#include "ir/irlandingpad.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include @@ -64,22 +65,55 @@ void Expression::cacheLvalue(IRState* irs) * Evaluate Expression, then call destructors on any temporaries in it. */ -DValue *Expression::toElemDtor(IRState *irs) +DValue *Expression::toElemDtor(IRState *p) { Logger::println("Expression::toElemDtor(): %s", toChars()); LOG_SCOPE - size_t starti = irs->varsInScope().size(); - DValue *val = toElem(irs); - size_t endi = irs->varsInScope().size(); + class CallDestructors : public IRLandingPadCatchFinallyInfo { + public: + std::vector edtors; - // Add destructors - while (endi-- > starti) - { + void toIR(LLValue */*eh_ptr*/ = 0) + { + std::vector::const_reverse_iterator itr, end = edtors.rend(); + for (itr = edtors.rbegin(); itr != end; ++itr) + (*itr)->toElem(gIR); + } + }; + + // 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); + + // set up the landing pad + IRLandingPad& pad = gIR->func()->gen->landingPadInfo; + pad.addFinally(callDestructors); + pad.push(landingpadbb); + + // evaluate expression + size_t starti = p->varsInScope().size(); + 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(); - vd->edtor->toElem(gIR); + callDestructors->edtors.push_back(vd->edtor); } + + // 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; }