mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-30 07:00:46 +03:00
The big catch/finally rework, part 1
Never generates any landing pads or invoke instructions right now for simplicity. The code for emitting them will be added back in the next step. The "after..." blocks without any precedessors remain for now, as we need a clean way to suppress any codegen for that block (but not new blocks, which might resolve labels) before tackling that one. Builds druntime/Phobos on OS X x86_64 (albeit without EH, of course).
This commit is contained in:
parent
bfc20df4c8
commit
4236ae9ce5
12 changed files with 861 additions and 1315 deletions
|
@ -227,7 +227,7 @@ LLValue *DtoModuleFileName(Module* M, const Loc& loc)
|
|||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GOTO HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
void DtoGoto(Loc &loc, LabelDsymbol *target, TryFinallyStatement *sourceFinally)
|
||||
void DtoGoto(Loc &loc, LabelDsymbol *target)
|
||||
{
|
||||
assert(!gIR->scopereturned());
|
||||
|
||||
|
@ -238,90 +238,9 @@ void DtoGoto(Loc &loc, LabelDsymbol *target, TryFinallyStatement *sourceFinally)
|
|||
fatal();
|
||||
}
|
||||
|
||||
// find target basic block
|
||||
std::string labelname = gIR->func()->gen->getScopedLabelName(target->ident->toChars());
|
||||
llvm::BasicBlock* &targetBB = gIR->func()->gen->labelToBB[labelname];
|
||||
if (targetBB == NULL)
|
||||
targetBB = llvm::BasicBlock::Create(gIR->context(), "label_" + labelname, gIR->topfunc());
|
||||
|
||||
// emit code for finallys between goto and label
|
||||
DtoEnclosingHandlers(loc, lblstmt);
|
||||
|
||||
// goto into finally blocks is forbidden by the spec
|
||||
// but should work fine
|
||||
if (lblstmt->tf != sourceFinally)
|
||||
{
|
||||
error(loc, "spec disallows goto into or out of finally block");
|
||||
fatal();
|
||||
}
|
||||
|
||||
llvm::BranchInst::Create(targetBB, gIR->scopebb());
|
||||
gIR->func()->scopes->jumpToLabel(loc, target->ident);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TRY-FINALLY
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
void EnclosingTryFinally::emitCode(IRState * p)
|
||||
{
|
||||
if (tf->finalbody)
|
||||
{
|
||||
llvm::BasicBlock* oldpad = p->func()->gen->landingPad;
|
||||
p->func()->gen->landingPad = landingPad;
|
||||
Statement_toIR(tf->finalbody, p);
|
||||
p->func()->gen->landingPad = oldpad;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEnclosingHandlers(Loc& loc, Statement* target)
|
||||
{
|
||||
// labels are a special case: they are not required to enclose the current scope
|
||||
// for them we use the enclosing scope handler as a reference point
|
||||
LabelStatement* lblstmt = target ? target->isLabelStatement() : 0;
|
||||
if (lblstmt)
|
||||
target = lblstmt->enclosingScopeExit;
|
||||
|
||||
// Figure out up until what handler we need to emit. Note that we need to
|
||||
// use use indices instead of iterators in the loop where we actually emit
|
||||
// them, as emitCode() might itself push/pop from the vector if it contains
|
||||
// control flow and and thus invalidate the latter.
|
||||
FuncGen::TargetScopeVec& scopes = gIR->func()->gen->targetScopes;
|
||||
size_t remainingScopes = scopes.size();
|
||||
while (remainingScopes != 0) {
|
||||
if (scopes[remainingScopes - 1].s == target) {
|
||||
break;
|
||||
}
|
||||
--remainingScopes;
|
||||
}
|
||||
|
||||
if (target && !remainingScopes) {
|
||||
if (lblstmt)
|
||||
error(loc, "cannot goto into try, volatile or synchronized statement at %s", target->loc.toChars());
|
||||
else
|
||||
error(loc, "internal error, cannot find jump path to statement at %s", target->loc.toChars());
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// emit code for enclosing handlers
|
||||
//
|
||||
|
||||
// since the labelstatements possibly inside are private
|
||||
// and might already exist push a label scope
|
||||
gIR->func()->gen->pushUniqueLabelScope("enclosing");
|
||||
|
||||
for (size_t i = scopes.size(); i > remainingScopes; --i) {
|
||||
EnclosingTryFinally *tf = scopes[i - 1].enclosinghandler;
|
||||
if (tf) tf->emitCode(gIR);
|
||||
}
|
||||
|
||||
gIR->func()->gen->popLabelScope();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ASSIGNMENT HELPER (store this in that)
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue