mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +03:00
Move temporaries-related state from ToElemVisitor to FuncGen.
This commit is contained in:
parent
2304b52acb
commit
cf52b53888
5 changed files with 85 additions and 98 deletions
|
@ -21,7 +21,6 @@
|
|||
#include "ir/iraggr.h"
|
||||
#include "ir/irvar.h"
|
||||
#include "gen/dibuilder.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
@ -214,11 +213,11 @@ llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const
|
|||
FuncGen& funcGen = *func()->gen;
|
||||
LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee);
|
||||
|
||||
const bool haveTemporaries = haveTemporariesToDestruct();
|
||||
const bool hasTemporaries = funcGen.hasTemporariesToDestruct();
|
||||
// intrinsics don't support invoking and 'nounwind' functions don't need it.
|
||||
const bool doesNotThrow = (fn && (fn->isIntrinsic() || fn->doesNotThrow()));
|
||||
|
||||
if (doesNotThrow || (!haveTemporaries && funcGen.landingPad == NULL))
|
||||
if (doesNotThrow || (!hasTemporaries && funcGen.landingPad == NULL))
|
||||
{
|
||||
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
|
||||
if (fn)
|
||||
|
@ -226,16 +225,16 @@ llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const
|
|||
return call;
|
||||
}
|
||||
|
||||
if (haveTemporaries)
|
||||
prepareToDestructAllTemporariesOnThrow();
|
||||
if (hasTemporaries)
|
||||
funcGen.prepareToDestructAllTemporariesOnThrow(this);
|
||||
|
||||
llvm::BasicBlock* oldend = scopeend();
|
||||
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(gIR->context(), "postinvoke", topfunc(), oldend);
|
||||
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(context(), "postinvoke", topfunc(), oldend);
|
||||
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, funcGen.landingPad, args, Name);
|
||||
if (fn)
|
||||
invoke->setAttributes(fn->getAttributes());
|
||||
|
||||
if (haveTemporaries)
|
||||
if (hasTemporaries)
|
||||
funcGen.landingPadInfo.pop();
|
||||
|
||||
scope() = IRScope(postinvoke, oldend);
|
||||
|
|
|
@ -239,7 +239,4 @@ DValue *toElem(Expression *e, bool tryGetLvalue);
|
|||
DValue *toElemDtor(Expression *e);
|
||||
LLConstant *toConstElem(Expression *e, IRState *p);
|
||||
|
||||
bool haveTemporariesToDestruct();
|
||||
void prepareToDestructAllTemporariesOnThrow();
|
||||
|
||||
#endif
|
||||
|
|
91
gen/toir.cpp
91
gen/toir.cpp
|
@ -265,67 +265,16 @@ DValue* toElem(Expression* e, bool tryGetLvalue)
|
|||
|
||||
class ToElemVisitor : public Visitor
|
||||
{
|
||||
// stack of declared temporaries which have yet to be destructed
|
||||
// static because toElem() calls are re-entrant
|
||||
static VarDeclarations temporariesWithDtor;
|
||||
static Array<ToElemVisitor*> visitors;
|
||||
|
||||
IRState *p;
|
||||
DValue *result;
|
||||
//DValue *lvalue;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void destructTemporaries(int numToKeep)
|
||||
{
|
||||
if (temporariesWithDtor.empty())
|
||||
return;
|
||||
|
||||
// pop one temporary after the other from the temporariesWithDtor stack
|
||||
// and evaluate its destructor expression
|
||||
// so when an exception occurs in a destructor expression, all older
|
||||
// temporaries (excl. the one which threw in its destructor) will be
|
||||
// destructed in a landing pad
|
||||
for (int i = temporariesWithDtor.size() - 1; i >= numToKeep; --i)
|
||||
{
|
||||
VarDeclaration* vd = temporariesWithDtor.pop();
|
||||
toElem(vd->edtor);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
ToElemVisitor(IRState *p_) : p(p_), result(NULL)
|
||||
{
|
||||
visitors.push(this);
|
||||
}
|
||||
|
||||
~ToElemVisitor()
|
||||
{
|
||||
if (visitors.size() == 1) // outer-most toElem() call only
|
||||
destructTemporaries(0);
|
||||
visitors.pop();
|
||||
}
|
||||
ToElemVisitor(IRState *p_) : p(p_), result(NULL) { p->func()->gen->pushToElemScope(); }
|
||||
~ToElemVisitor() { p->func()->gen->popToElemScope(); }
|
||||
|
||||
DValue *getResult() { return result; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool hasTemporariesToDestruct() { return !temporariesWithDtor.empty(); }
|
||||
|
||||
static void destructAllTemporariesAndRestoreStack()
|
||||
{
|
||||
if (temporariesWithDtor.empty())
|
||||
return;
|
||||
|
||||
VarDeclarations original = temporariesWithDtor;
|
||||
destructTemporaries(0);
|
||||
temporariesWithDtor = original;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Import all functions from class Visitor
|
||||
using Visitor::visit;
|
||||
|
||||
|
@ -345,7 +294,7 @@ public:
|
|||
{
|
||||
VarDeclaration* vd = varValue->var;
|
||||
if (!vd->isDataseg() && vd->edtor && !vd->noscope)
|
||||
temporariesWithDtor.push(vd);
|
||||
p->func()->gen->pushTemporaryToDestruct(vd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3183,9 +3132,6 @@ public:
|
|||
STUB(PowAssignExp)
|
||||
};
|
||||
|
||||
VarDeclarations ToElemVisitor::temporariesWithDtor;
|
||||
Array<ToElemVisitor*> ToElemVisitor::visitors;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue *toElem(Expression *e)
|
||||
|
@ -3200,37 +3146,6 @@ DValue *toElemDtor(Expression *e)
|
|||
return toElem(e);
|
||||
}
|
||||
|
||||
bool haveTemporariesToDestruct()
|
||||
{
|
||||
return ToElemVisitor::hasTemporariesToDestruct();
|
||||
}
|
||||
|
||||
void prepareToDestructAllTemporariesOnThrow()
|
||||
{
|
||||
if (!haveTemporariesToDestruct())
|
||||
return;
|
||||
|
||||
class CallDestructors : public IRLandingPadCatchFinallyInfo
|
||||
{
|
||||
public:
|
||||
void toIR(LLValue* /*eh_ptr*/ = NULL)
|
||||
{
|
||||
ToElemVisitor::destructAllTemporariesAndRestoreStack();
|
||||
}
|
||||
};
|
||||
|
||||
CallDestructors* callDestructors = new CallDestructors(); // leaks
|
||||
|
||||
// create landing pad
|
||||
llvm::BasicBlock* landingpadbb = llvm::BasicBlock::Create(gIR->context(),
|
||||
"temporariesLandingPad", gIR->topfunc(), gIR->scopeend());
|
||||
|
||||
// set up the landing pad
|
||||
IRLandingPad& pad = gIR->func()->gen->landingPadInfo;
|
||||
pad.addFinally(callDestructors);
|
||||
pad.push(landingpadbb);
|
||||
}
|
||||
|
||||
// FIXME: Implement & place in right module
|
||||
Symbol *toModuleAssert(Module *m)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gen/llvm.h"
|
||||
#include "gen/llvmhelpers.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/tollvm.h"
|
||||
#include "ir/irdsymbol.h"
|
||||
#include "ir/irfunction.h"
|
||||
|
@ -17,6 +19,7 @@ FuncGen::FuncGen()
|
|||
{
|
||||
landingPad = NULL;
|
||||
nextUnique.push(0);
|
||||
toElemScopeCounter = 0;
|
||||
}
|
||||
|
||||
std::string FuncGen::getScopedLabelName(const char* ident)
|
||||
|
@ -44,6 +47,64 @@ void FuncGen::popLabelScope()
|
|||
nextUnique.pop();
|
||||
}
|
||||
|
||||
void FuncGen::pushToElemScope() { ++toElemScopeCounter; }
|
||||
void FuncGen::popToElemScope()
|
||||
{
|
||||
assert(toElemScopeCounter > 0);
|
||||
if (toElemScopeCounter == 1) // popping outer-most toElem() scope?
|
||||
destructAllTemporaries();
|
||||
--toElemScopeCounter;
|
||||
}
|
||||
|
||||
void FuncGen::pushTemporaryToDestruct(VarDeclaration* vd) { temporariesToDestruct.push(vd); }
|
||||
bool FuncGen::hasTemporariesToDestruct() { return !temporariesToDestruct.empty(); }
|
||||
|
||||
void FuncGen::destructAllTemporaries()
|
||||
{
|
||||
// pop one temporary after the other from the temporariesToDestruct stack
|
||||
// and evaluate its destructor expression
|
||||
// so when an exception occurs in a destructor expression, all older
|
||||
// temporaries (excl. the one which threw in its destructor) will be
|
||||
// destructed in a landing pad
|
||||
while (!temporariesToDestruct.empty())
|
||||
{
|
||||
VarDeclaration* vd = temporariesToDestruct.pop();
|
||||
toElem(vd->edtor);
|
||||
}
|
||||
}
|
||||
|
||||
void FuncGen::destructAllTemporariesAndRestoreStack()
|
||||
{
|
||||
VarDeclarations original = temporariesToDestruct;
|
||||
destructAllTemporaries();
|
||||
temporariesToDestruct = original;
|
||||
}
|
||||
|
||||
void FuncGen::prepareToDestructAllTemporariesOnThrow(IRState* irState)
|
||||
{
|
||||
class CallDestructors : public IRLandingPadCatchFinallyInfo
|
||||
{
|
||||
public:
|
||||
FuncGen& funcGen;
|
||||
CallDestructors(FuncGen& funcGen) : funcGen(funcGen) {}
|
||||
void toIR(LLValue*)
|
||||
{
|
||||
funcGen.destructAllTemporariesAndRestoreStack();
|
||||
}
|
||||
};
|
||||
|
||||
CallDestructors* callDestructors = new CallDestructors(*this); // will leak
|
||||
|
||||
// create landing pad
|
||||
llvm::BasicBlock* landingpadbb = llvm::BasicBlock::Create(irState->context(),
|
||||
"temporariesLandingPad", irState->topfunc(), irState->scopeend());
|
||||
|
||||
// set up the landing pad
|
||||
landingPadInfo.addFinally(callDestructors);
|
||||
landingPadInfo.push(landingpadbb);
|
||||
}
|
||||
|
||||
|
||||
IrFunction::IrFunction(FuncDeclaration* fd)
|
||||
{
|
||||
decl = fd;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
class Statement;
|
||||
struct EnclosingTryFinally;
|
||||
struct IRState;
|
||||
|
||||
// scope statements that can be target of jumps
|
||||
// includes loops, switch, case, labels
|
||||
|
@ -81,6 +82,17 @@ struct FuncGen
|
|||
IRLandingPad landingPadInfo;
|
||||
llvm::BasicBlock* landingPad;
|
||||
|
||||
void pushToElemScope();
|
||||
void popToElemScope();
|
||||
|
||||
void pushTemporaryToDestruct(VarDeclaration* vd);
|
||||
bool hasTemporariesToDestruct();
|
||||
void destructAllTemporaries();
|
||||
void destructAllTemporariesAndRestoreStack();
|
||||
// pushes a landing pad which needs to be popped after the
|
||||
// following invoke instruction
|
||||
void prepareToDestructAllTemporariesOnThrow(IRState* irState);
|
||||
|
||||
private:
|
||||
// prefix for labels and gotos
|
||||
// used for allowing labels to be emitted twice
|
||||
|
@ -88,6 +100,9 @@ private:
|
|||
|
||||
// next unique id stack
|
||||
std::stack<int> nextUnique;
|
||||
|
||||
int toElemScopeCounter;
|
||||
VarDeclarations temporariesToDestruct;
|
||||
};
|
||||
|
||||
// represents a function
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue