mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 00:55:49 +03:00
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
implement the synchronized storage class for functions.
This commit is contained in:
parent
a0d93e699a
commit
671c7791e3
12 changed files with 217 additions and 228 deletions
36
dmd/func.c
36
dmd/func.c
|
@ -682,8 +682,8 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
sc2->explicitProtection = 0;
|
||||
sc2->structalign = 8;
|
||||
sc2->incontract = 0;
|
||||
sc2->tf = NULL;
|
||||
sc2->tfOfTry = NULL;
|
||||
sc2->enclosingFinally = NULL;
|
||||
sc2->enclosingScopeExit = NULL;
|
||||
sc2->noctor = 0;
|
||||
|
||||
// Declare 'this'
|
||||
|
@ -1243,6 +1243,38 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
}
|
||||
|
||||
fbody = new CompoundStatement(0, a);
|
||||
|
||||
// wrap body of synchronized functions in a synchronized statement
|
||||
if (isSynchronized())
|
||||
{
|
||||
ClassDeclaration *cd = parent->isClassDeclaration();
|
||||
if (!cd)
|
||||
error("synchronized function %s must be a member of a class", toChars());
|
||||
|
||||
Expression *sync;
|
||||
if (isStatic())
|
||||
{
|
||||
// static member functions synchronize on classinfo
|
||||
// (the expression passed doesn't matter)
|
||||
sync = cd->type->dotExp(sc2, new DollarExp(loc), Id::classinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-static member functions synchronize on this
|
||||
sync = new VarExp(loc, vthis);
|
||||
}
|
||||
|
||||
// is is ok to not rerun semantic on the whole fbody here; only the enclosingScopeExit
|
||||
// value will differ and as it is impossible to goto out of this synchronized statement,
|
||||
// that should not lead to errors
|
||||
SynchronizedStatement* s = new SynchronizedStatement(loc, sync, NULL);
|
||||
s->semantic(sc2);
|
||||
s->body = fbody;
|
||||
|
||||
a = new Statements;
|
||||
a->push(s);
|
||||
fbody = new CompoundStatement(0, a);
|
||||
}
|
||||
}
|
||||
|
||||
sc2->callSuper = 0;
|
||||
|
|
|
@ -52,8 +52,8 @@ Scope::Scope()
|
|||
this->enclosing = NULL;
|
||||
this->parent = NULL;
|
||||
this->sw = NULL;
|
||||
this->tf = NULL;
|
||||
this->tfOfTry = NULL;
|
||||
this->enclosingFinally = NULL;
|
||||
this->enclosingScopeExit = NULL;
|
||||
this->tinst = NULL;
|
||||
this->sbreak = NULL;
|
||||
this->scontinue = NULL;
|
||||
|
@ -91,8 +91,8 @@ Scope::Scope(Scope *enclosing)
|
|||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->sw = enclosing->sw;
|
||||
this->tf = enclosing->tf;
|
||||
this->tfOfTry = enclosing->tfOfTry;
|
||||
this->enclosingFinally = enclosing->enclosingFinally;
|
||||
this->enclosingScopeExit = enclosing->enclosingScopeExit;
|
||||
this->tinst = enclosing->tinst;
|
||||
this->sbreak = enclosing->sbreak;
|
||||
this->scontinue = enclosing->scontinue;
|
||||
|
|
|
@ -46,8 +46,8 @@ struct Scope
|
|||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block
|
||||
EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
|
||||
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
|
||||
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
|
|
|
@ -582,7 +582,6 @@ UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
|
|||
: Statement(loc)
|
||||
{
|
||||
statements = s;
|
||||
enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *UnrolledLoopStatement::syntaxCopy()
|
||||
|
@ -604,8 +603,6 @@ Statement *UnrolledLoopStatement::semantic(Scope *sc)
|
|||
{
|
||||
//printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
|
||||
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
sc->noctor++;
|
||||
Scope *scd = sc->push();
|
||||
scd->sbreak = this;
|
||||
|
@ -795,7 +792,6 @@ WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
|
|||
{
|
||||
condition = c;
|
||||
body = b;
|
||||
enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *WhileStatement::syntaxCopy()
|
||||
|
@ -830,8 +826,6 @@ Statement *WhileStatement::semantic(Scope *sc)
|
|||
}
|
||||
#endif
|
||||
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
condition = condition->semantic(sc);
|
||||
condition = resolveProperties(sc, condition);
|
||||
condition = condition->optimize(WANTvalue);
|
||||
|
@ -919,7 +913,6 @@ DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
|
|||
{
|
||||
body = b;
|
||||
condition = c;
|
||||
enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *DoStatement::syntaxCopy()
|
||||
|
@ -931,8 +924,6 @@ Statement *DoStatement::syntaxCopy()
|
|||
|
||||
Statement *DoStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
sc->noctor++;
|
||||
if (body)
|
||||
body = body->semanticScope(sc, this, this);
|
||||
|
@ -1010,7 +1001,6 @@ ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expr
|
|||
this->condition = condition;
|
||||
this->increment = increment;
|
||||
this->body = body;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *ForStatement::syntaxCopy()
|
||||
|
@ -1030,8 +1020,6 @@ Statement *ForStatement::syntaxCopy()
|
|||
|
||||
Statement *ForStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
ScopeDsymbol *sym = new ScopeDsymbol();
|
||||
sym->parent = sc->scopesym;
|
||||
sc = sc->push(sym);
|
||||
|
@ -1169,7 +1157,6 @@ ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
|
|||
this->arguments = arguments;
|
||||
this->aggr = aggr;
|
||||
this->body = body;
|
||||
this->enclosinghandler = NULL;
|
||||
|
||||
this->key = NULL;
|
||||
this->value = NULL;
|
||||
|
@ -1197,8 +1184,6 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||
Type *tn = NULL;
|
||||
Type *tnv = NULL;
|
||||
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
func = sc->func;
|
||||
if (func->fes)
|
||||
func = func->fes->func;
|
||||
|
@ -2253,8 +2238,6 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
|
|||
sdefault = NULL;
|
||||
cases = NULL;
|
||||
hasNoDefault = 0;
|
||||
// LDC
|
||||
enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *SwitchStatement::syntaxCopy()
|
||||
|
@ -2269,8 +2252,6 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
|||
//printf("SwitchStatement::semantic(%p)\n", this);
|
||||
assert(!cases); // ensure semantic() is only run once
|
||||
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
condition = condition->semantic(sc);
|
||||
condition = resolveProperties(sc, condition);
|
||||
if (condition->type->isString())
|
||||
|
@ -2571,7 +2552,6 @@ GotoDefaultStatement::GotoDefaultStatement(Loc loc)
|
|||
: Statement(loc)
|
||||
{
|
||||
sw = NULL;
|
||||
enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *GotoDefaultStatement::syntaxCopy()
|
||||
|
@ -2582,7 +2562,6 @@ Statement *GotoDefaultStatement::syntaxCopy()
|
|||
|
||||
Statement *GotoDefaultStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
sw = sc->sw;
|
||||
if (!sw)
|
||||
error("goto default not in switch statement");
|
||||
|
@ -2606,7 +2585,6 @@ GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
|
|||
{
|
||||
cs = NULL;
|
||||
this->exp = exp;
|
||||
enclosinghandler = NULL;
|
||||
sw = NULL;
|
||||
}
|
||||
|
||||
|
@ -2619,7 +2597,6 @@ Statement *GotoCaseStatement::syntaxCopy()
|
|||
|
||||
Statement *GotoCaseStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
if (exp)
|
||||
exp = exp->semantic(sc);
|
||||
|
||||
|
@ -2678,7 +2655,6 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
|
|||
: Statement(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *ReturnStatement::syntaxCopy()
|
||||
|
@ -2693,7 +2669,6 @@ Statement *ReturnStatement::syntaxCopy()
|
|||
Statement *ReturnStatement::semantic(Scope *sc)
|
||||
{
|
||||
//printf("ReturnStatement::semantic() %s\n", toChars());
|
||||
this->enclosinghandler = sc->tfOfTry;
|
||||
|
||||
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
|
||||
Scope *scx = sc;
|
||||
|
@ -2730,7 +2705,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||
|
||||
if (sc->incontract || scx->incontract)
|
||||
error("return statements cannot be in contracts");
|
||||
if (sc->tf || scx->tf)
|
||||
if (sc->enclosingFinally || scx->enclosingFinally)
|
||||
error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
|
||||
|
||||
if (fd->isCtorDeclaration())
|
||||
|
@ -2955,7 +2930,6 @@ BreakStatement::BreakStatement(Loc loc, Identifier *ident)
|
|||
: Statement(loc)
|
||||
{
|
||||
this->ident = ident;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *BreakStatement::syntaxCopy()
|
||||
|
@ -2967,7 +2941,6 @@ Statement *BreakStatement::syntaxCopy()
|
|||
Statement *BreakStatement::semantic(Scope *sc)
|
||||
{
|
||||
//printf("BreakStatement::semantic()\n");
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
// If:
|
||||
// break Identifier;
|
||||
if (ident)
|
||||
|
@ -3005,7 +2978,7 @@ Statement *BreakStatement::semantic(Scope *sc)
|
|||
|
||||
if (!s->hasBreak())
|
||||
error("label '%s' has no break", ident->toChars());
|
||||
if (ls->tf != sc->tf)
|
||||
if (ls->enclosingFinally != sc->enclosingFinally)
|
||||
error("cannot break out of finally block");
|
||||
|
||||
this->target = ls;
|
||||
|
@ -3051,7 +3024,6 @@ ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
|
|||
: Statement(loc)
|
||||
{
|
||||
this->ident = ident;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *ContinueStatement::syntaxCopy()
|
||||
|
@ -3062,7 +3034,6 @@ Statement *ContinueStatement::syntaxCopy()
|
|||
|
||||
Statement *ContinueStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
//printf("ContinueStatement::semantic() %p\n", this);
|
||||
if (ident)
|
||||
{
|
||||
|
@ -3109,7 +3080,7 @@ Statement *ContinueStatement::semantic(Scope *sc)
|
|||
|
||||
if (!s->hasContinue())
|
||||
error("label '%s' has no continue", ident->toChars());
|
||||
if (ls->tf != sc->tf)
|
||||
if (ls->enclosingFinally != sc->enclosingFinally)
|
||||
error("cannot continue out of finally block");
|
||||
|
||||
this->target = ls;
|
||||
|
@ -3156,7 +3127,6 @@ SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement
|
|||
this->exp = exp;
|
||||
this->body = body;
|
||||
this->esync = NULL;
|
||||
this->enclosinghandler = NULL;
|
||||
// LDC
|
||||
this->llsync = NULL;
|
||||
}
|
||||
|
@ -3167,7 +3137,6 @@ SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *bo
|
|||
this->exp = NULL;
|
||||
this->body = body;
|
||||
this->esync = esync;
|
||||
this->enclosinghandler = NULL;
|
||||
// LDC
|
||||
this->llsync = NULL;
|
||||
}
|
||||
|
@ -3199,10 +3168,10 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||
}
|
||||
if (body)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
sc->tfOfTry = new EnclosingSynchro(this);
|
||||
body = body->semantic(sc);
|
||||
sc->tfOfTry = enclosinghandler;
|
||||
Statement* oldScopeExit = sc->enclosingScopeExit;
|
||||
sc->enclosingScopeExit = this;
|
||||
body = body->semantic(sc);
|
||||
sc->enclosingScopeExit = oldScopeExit;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -3455,7 +3424,7 @@ void Catch::semantic(Scope *sc)
|
|||
//printf("Catch::semantic(%s)\n", ident->toChars());
|
||||
|
||||
#ifndef IN_GCC
|
||||
if (sc->tf)
|
||||
if (sc->enclosingFinally)
|
||||
{
|
||||
/* This is because the _d_local_unwind() gets the stack munged
|
||||
* up on this. The workaround is to place any try-catches into
|
||||
|
@ -3516,7 +3485,6 @@ TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *fi
|
|||
{
|
||||
this->body = body;
|
||||
this->finalbody = finalbody;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *TryFinallyStatement::syntaxCopy()
|
||||
|
@ -3530,13 +3498,13 @@ Statement *TryFinallyStatement::semantic(Scope *sc)
|
|||
{
|
||||
//printf("TryFinallyStatement::semantic()\n");
|
||||
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
sc->tfOfTry = new EnclosingTryFinally(this);
|
||||
Statement* oldScopeExit = sc->enclosingScopeExit;
|
||||
sc->enclosingScopeExit = this;
|
||||
body = body->semantic(sc);
|
||||
sc->tfOfTry = enclosinghandler;
|
||||
sc->enclosingScopeExit = oldScopeExit;
|
||||
|
||||
sc = sc->push();
|
||||
sc->tf = this;
|
||||
sc->enclosingFinally = this;
|
||||
sc->sbreak = NULL;
|
||||
sc->scontinue = NULL; // no break or continue out of finally block
|
||||
finalbody = finalbody->semantic(sc);
|
||||
|
@ -3711,7 +3679,6 @@ VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
|
|||
: Statement(loc)
|
||||
{
|
||||
this->statement = statement;
|
||||
this->enclosinghandler = NULL;
|
||||
}
|
||||
|
||||
Statement *VolatileStatement::syntaxCopy()
|
||||
|
@ -3725,10 +3692,10 @@ Statement *VolatileStatement::semantic(Scope *sc)
|
|||
{
|
||||
if (statement)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
sc->tfOfTry = new EnclosingVolatile(this);
|
||||
statement = statement->semantic(sc);
|
||||
sc->tfOfTry = enclosinghandler;
|
||||
Statement* oldScopeExit = sc->enclosingScopeExit;
|
||||
sc->enclosingScopeExit = this;
|
||||
statement = statement->semantic(sc);
|
||||
sc->enclosingScopeExit = oldScopeExit;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -3775,8 +3742,8 @@ GotoStatement::GotoStatement(Loc loc, Identifier *ident)
|
|||
{
|
||||
this->ident = ident;
|
||||
this->label = NULL;
|
||||
this->tf = NULL;
|
||||
this->enclosinghandler = NULL;
|
||||
this->enclosingFinally = NULL;
|
||||
this->enclosingScopeExit = NULL;
|
||||
}
|
||||
|
||||
Statement *GotoStatement::syntaxCopy()
|
||||
|
@ -3789,8 +3756,9 @@ Statement *GotoStatement::semantic(Scope *sc)
|
|||
{ FuncDeclaration *fd = sc->parent->isFuncDeclaration();
|
||||
|
||||
//printf("GotoStatement::semantic()\n");
|
||||
tf = sc->tf;
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
enclosingFinally = sc->enclosingFinally;
|
||||
enclosingScopeExit = sc->enclosingScopeExit;
|
||||
|
||||
label = fd->searchLabel(ident);
|
||||
if (!label->statement && sc->fes)
|
||||
{
|
||||
|
@ -3808,7 +3776,7 @@ Statement *GotoStatement::semantic(Scope *sc)
|
|||
sc->fes->gotos.push(s); // 'look at this later' list
|
||||
return s;
|
||||
}
|
||||
if (label->statement && label->statement->tf != sc->tf)
|
||||
if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally)
|
||||
error("cannot goto in or out of finally block");
|
||||
return this;
|
||||
}
|
||||
|
@ -3834,8 +3802,8 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
|
|||
{
|
||||
this->ident = ident;
|
||||
this->statement = statement;
|
||||
this->tf = NULL;
|
||||
this->enclosinghandler = NULL;
|
||||
this->enclosingFinally = NULL;
|
||||
this->enclosingScopeExit = NULL;
|
||||
this->lblock = NULL;
|
||||
this->isReturnLabel = 0;
|
||||
this->asmLabel = false;
|
||||
|
@ -3857,8 +3825,10 @@ Statement *LabelStatement::semantic(Scope *sc)
|
|||
error("Label '%s' already defined", ls->toChars());
|
||||
else
|
||||
ls->statement = this;
|
||||
tf = sc->tf;
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
|
||||
enclosingFinally = sc->enclosingFinally;
|
||||
enclosingScopeExit = sc->enclosingScopeExit;
|
||||
|
||||
sc = sc->push();
|
||||
sc->scopesym = sc->enclosing->scopesym;
|
||||
sc->callSuper |= CSXlabel;
|
||||
|
|
|
@ -94,35 +94,6 @@ enum BE
|
|||
BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
|
||||
};
|
||||
|
||||
// LDC this is used for tracking try-finally, synchronized and volatile scopes
|
||||
// definitions in gen/llvmhelpers.cpp
|
||||
struct EnclosingHandler : Object
|
||||
{
|
||||
virtual void emitCode(IRState* p) = 0;
|
||||
virtual EnclosingHandler* getEnclosing() = 0;
|
||||
};
|
||||
struct EnclosingTryFinally : EnclosingHandler
|
||||
{
|
||||
TryFinallyStatement* tf;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {}
|
||||
};
|
||||
struct EnclosingVolatile : EnclosingHandler
|
||||
{
|
||||
VolatileStatement* v;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
|
||||
};
|
||||
struct EnclosingSynchro : EnclosingHandler
|
||||
{
|
||||
SynchronizedStatement* s;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingHandler* getEnclosing();
|
||||
EnclosingSynchro(SynchronizedStatement* _tf) : s(_tf) {}
|
||||
};
|
||||
|
||||
struct Statement : Object
|
||||
{
|
||||
Loc loc;
|
||||
|
@ -255,7 +226,6 @@ struct CompoundStatement : Statement
|
|||
struct UnrolledLoopStatement : Statement
|
||||
{
|
||||
Statements *statements;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
UnrolledLoopStatement(Loc loc, Statements *statements);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -300,7 +270,6 @@ struct WhileStatement : Statement
|
|||
{
|
||||
Expression *condition;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
WhileStatement(Loc loc, Expression *c, Statement *b);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -322,7 +291,6 @@ struct DoStatement : Statement
|
|||
{
|
||||
Statement *body;
|
||||
Expression *condition;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
DoStatement(Loc loc, Statement *b, Expression *c);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -346,7 +314,6 @@ struct ForStatement : Statement
|
|||
Expression *condition;
|
||||
Expression *increment;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -371,7 +338,6 @@ struct ForeachStatement : Statement
|
|||
Arguments *arguments; // array of Argument*'s
|
||||
Expression *aggr;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
VarDeclaration *key;
|
||||
VarDeclaration *value;
|
||||
|
@ -499,7 +465,6 @@ struct SwitchStatement : Statement
|
|||
Statement *body;
|
||||
|
||||
DefaultStatement *sdefault;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
Array gotoCases; // array of unresolved GotoCaseStatement's
|
||||
Array *cases; // array of CaseStatement's
|
||||
|
@ -574,7 +539,6 @@ struct DefaultStatement : Statement
|
|||
struct GotoDefaultStatement : Statement
|
||||
{
|
||||
SwitchStatement *sw;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
GotoDefaultStatement(Loc loc);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -590,7 +554,6 @@ struct GotoCaseStatement : Statement
|
|||
{
|
||||
Expression *exp; // NULL, or which case to goto
|
||||
CaseStatement *cs; // case statement it resolves to
|
||||
EnclosingHandler* enclosinghandler;
|
||||
SwitchStatement *sw;
|
||||
|
||||
GotoCaseStatement(Loc loc, Expression *exp);
|
||||
|
@ -615,7 +578,6 @@ struct SwitchErrorStatement : Statement
|
|||
struct ReturnStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ReturnStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -636,7 +598,6 @@ struct ReturnStatement : Statement
|
|||
struct BreakStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
BreakStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -654,7 +615,6 @@ struct BreakStatement : Statement
|
|||
struct ContinueStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
ContinueStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -673,7 +633,6 @@ struct SynchronizedStatement : Statement
|
|||
{
|
||||
Expression *exp;
|
||||
Statement *body;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -749,7 +708,6 @@ struct TryFinallyStatement : Statement
|
|||
{
|
||||
Statement *body;
|
||||
Statement *finalbody;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -799,7 +757,6 @@ struct ThrowStatement : Statement
|
|||
struct VolatileStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
|
||||
VolatileStatement(Loc loc, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -817,8 +774,8 @@ struct GotoStatement : Statement
|
|||
{
|
||||
Identifier *ident;
|
||||
LabelDsymbol *label;
|
||||
TryFinallyStatement *tf;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
TryFinallyStatement *enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
|
||||
GotoStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
|
@ -835,8 +792,8 @@ struct LabelStatement : Statement
|
|||
{
|
||||
Identifier *ident;
|
||||
Statement *statement;
|
||||
TryFinallyStatement *tf;
|
||||
EnclosingHandler* enclosinghandler;
|
||||
TryFinallyStatement *enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
block *lblock; // back end
|
||||
int isReturnLabel;
|
||||
|
||||
|
@ -895,8 +852,8 @@ struct AsmStatement : Statement
|
|||
|
||||
struct AsmBlockStatement : CompoundStatement
|
||||
{
|
||||
EnclosingHandler* enclosinghandler;
|
||||
TryFinallyStatement* tf;
|
||||
TryFinallyStatement* enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
|
||||
AsmBlockStatement(Loc loc, Statements *s);
|
||||
Statements *flatten(Scope *sc);
|
||||
|
|
|
@ -444,8 +444,8 @@ assert(0);
|
|||
AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s)
|
||||
: CompoundStatement(loc, s)
|
||||
{
|
||||
enclosinghandler = NULL;
|
||||
tf = NULL;
|
||||
enclosingFinally = NULL;
|
||||
enclosingScopeExit = NULL;
|
||||
|
||||
abiret = NULL;
|
||||
}
|
||||
|
@ -772,7 +772,7 @@ void AsmBlockStatement::toIR(IRState* p)
|
|||
sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->second), casebb);
|
||||
|
||||
p->scope() = IRScope(casebb,bb);
|
||||
DtoGoto(&loc, it->first, enclosinghandler, tf);
|
||||
DtoGoto(loc, it->first);
|
||||
}
|
||||
|
||||
p->scope() = IRScope(bb,oldend);
|
||||
|
@ -803,8 +803,8 @@ Statement *AsmBlockStatement::syntaxCopy()
|
|||
// necessary for in-asm branches
|
||||
Statement *AsmBlockStatement::semantic(Scope *sc)
|
||||
{
|
||||
enclosinghandler = sc->tfOfTry;
|
||||
tf = sc->tf;
|
||||
enclosingFinally = sc->enclosingFinally;
|
||||
enclosingScopeExit = sc->enclosingScopeExit;
|
||||
|
||||
return CompoundStatement::semantic(sc);
|
||||
}
|
||||
|
|
|
@ -34,18 +34,16 @@ IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
|
|||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRLoopScope::IRLoopScope()
|
||||
IRTargetScope::IRTargetScope()
|
||||
{
|
||||
}
|
||||
|
||||
IRLoopScope::IRLoopScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* b, llvm::BasicBlock* e, bool isSwitch)
|
||||
IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget)
|
||||
{
|
||||
begin = b;
|
||||
end = e;
|
||||
//builder.SetInsertPoint(b);
|
||||
this->s = s;
|
||||
this->enclosinghandler = enclosinghandler;
|
||||
this->isSwitch = isSwitch;
|
||||
this->breakTarget = breakTarget;
|
||||
this->continueTarget = continueTarget;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -51,19 +51,21 @@ struct IRScope
|
|||
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
|
||||
};
|
||||
|
||||
// scope for loops
|
||||
struct IRLoopScope : IRScope
|
||||
// scope statements that can be target of jumps
|
||||
// includes loops, switch, case, labels
|
||||
struct IRTargetScope
|
||||
{
|
||||
// generating statement
|
||||
Statement* s;
|
||||
|
||||
// the try of a TryFinally that encloses the loop
|
||||
EnclosingHandler* enclosinghandler;
|
||||
// if it is a switch, we are a possible target for break
|
||||
// but not for continue
|
||||
bool isSwitch;
|
||||
|
||||
llvm::BasicBlock* breakTarget;
|
||||
llvm::BasicBlock* continueTarget;
|
||||
|
||||
IRLoopScope();
|
||||
IRLoopScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* b, llvm::BasicBlock* e, bool isSwitch = false);
|
||||
IRTargetScope();
|
||||
IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget);
|
||||
};
|
||||
|
||||
struct IRBuilderHelper
|
||||
|
@ -158,8 +160,8 @@ struct IRState
|
|||
llvm::CallSite CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name="");
|
||||
|
||||
// loop blocks
|
||||
typedef std::vector<IRLoopScope> LoopScopeVec;
|
||||
LoopScopeVec loopbbs;
|
||||
typedef std::vector<IRTargetScope> TargetScopeVec;
|
||||
TargetScopeVec targetScopes;
|
||||
|
||||
// this holds the array being indexed or sliced so $ will work
|
||||
// might be a better way but it works. problem is I only get a
|
||||
|
|
|
@ -110,7 +110,7 @@ llvm::AllocaInst* DtoAlloca(const LLType* lltype, LLValue* arraysize, const std:
|
|||
// ASSERT HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
void DtoAssert(Module* M, Loc* loc, DValue* msg)
|
||||
void DtoAssert(Module* M, Loc loc, DValue* msg)
|
||||
{
|
||||
std::vector<LLValue*> args;
|
||||
|
||||
|
@ -133,7 +133,7 @@ void DtoAssert(Module* M, Loc* loc, DValue* msg)
|
|||
args.push_back(DtoLoad(M->ir.irModule->fileName));
|
||||
|
||||
// line param
|
||||
LLConstant* c = DtoConstUint(loc->linnum);
|
||||
LLConstant* c = DtoConstUint(loc.linnum);
|
||||
args.push_back(c);
|
||||
|
||||
// call
|
||||
|
@ -172,19 +172,19 @@ LabelStatement* DtoLabelStatement(Identifier* ident)
|
|||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GOTO HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, TryFinallyStatement* sourcetf)
|
||||
void DtoGoto(Loc loc, Identifier* target)
|
||||
{
|
||||
assert(!gIR->scopereturned());
|
||||
|
||||
LabelStatement* lblstmt = DtoLabelStatement(target);
|
||||
if(!lblstmt) {
|
||||
error(*loc, "the label %s does not exist", target->toChars());
|
||||
error(loc, "the label %s does not exist", target->toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
// if the target label is inside inline asm, error
|
||||
if(lblstmt->asmLabel) {
|
||||
error(*loc, "cannot goto to label %s inside an inline asm block", target->toChars());
|
||||
error(loc, "cannot goto to label %s inside an inline asm block", target->toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
|
@ -194,25 +194,16 @@ void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, T
|
|||
if (targetBB == NULL)
|
||||
targetBB = llvm::BasicBlock::Create("label_" + labelname, gIR->topfunc());
|
||||
|
||||
// find finallys between goto and label
|
||||
EnclosingHandler* endfinally = enclosinghandler;
|
||||
while(endfinally != NULL && endfinally != lblstmt->enclosinghandler) {
|
||||
endfinally = endfinally->getEnclosing();
|
||||
}
|
||||
|
||||
// error if didn't find tf statement of label
|
||||
if(endfinally != lblstmt->enclosinghandler)
|
||||
error(*loc, "cannot goto into try block");
|
||||
// emit code for finallys between goto and label
|
||||
DtoEnclosingHandlers(loc, lblstmt);
|
||||
|
||||
// goto into finally blocks is forbidden by the spec
|
||||
// though it should not be problematic to implement
|
||||
// but should work fine
|
||||
/*
|
||||
if(lblstmt->tf != sourcetf) {
|
||||
error(*loc, "spec disallows goto into finally block");
|
||||
error(loc, "spec disallows goto into finally block");
|
||||
fatal();
|
||||
}
|
||||
|
||||
// emit code for finallys between goto and label
|
||||
DtoEnclosingHandlers(enclosinghandler, endfinally);
|
||||
}*/
|
||||
|
||||
llvm::BranchInst::Create(targetBB, gIR->scopebb());
|
||||
}
|
||||
|
@ -225,16 +216,11 @@ void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, T
|
|||
void EnclosingSynchro::emitCode(IRState * p)
|
||||
{
|
||||
if (s->exp)
|
||||
DtoLeaveMonitor(s->llsync);
|
||||
DtoLeaveMonitor(s->exp->toElem(p)->getRVal());
|
||||
else
|
||||
DtoLeaveCritical(s->llsync);
|
||||
}
|
||||
|
||||
EnclosingHandler* EnclosingSynchro::getEnclosing()
|
||||
{
|
||||
return s->enclosinghandler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EnclosingVolatile::emitCode(IRState * p)
|
||||
|
@ -243,11 +229,6 @@ void EnclosingVolatile::emitCode(IRState * p)
|
|||
DtoMemoryBarrier(false, false, true, false);
|
||||
}
|
||||
|
||||
EnclosingHandler* EnclosingVolatile::getEnclosing()
|
||||
{
|
||||
return v->enclosinghandler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EnclosingTryFinally::emitCode(IRState * p)
|
||||
|
@ -256,34 +237,43 @@ void EnclosingTryFinally::emitCode(IRState * p)
|
|||
tf->finalbody->toIR(p);
|
||||
}
|
||||
|
||||
EnclosingHandler* EnclosingTryFinally::getEnclosing()
|
||||
{
|
||||
return tf->enclosinghandler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end)
|
||||
void DtoEnclosingHandlers(Loc loc, Statement* target)
|
||||
{
|
||||
// verify that end encloses start
|
||||
EnclosingHandler* endfinally = start;
|
||||
while(endfinally != NULL && endfinally != end) {
|
||||
endfinally = endfinally->getEnclosing();
|
||||
}
|
||||
assert(endfinally == end);
|
||||
// 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 = dynamic_cast<LabelStatement*>(target);
|
||||
if (lblstmt)
|
||||
target = lblstmt->enclosingScopeExit;
|
||||
|
||||
// figure out up until what handler we need to emit
|
||||
IRState::TargetScopeVec::reverse_iterator targetit;
|
||||
for (targetit = gIR->targetScopes.rbegin(); targetit != gIR->targetScopes.rend(); ++targetit) {
|
||||
if (targetit->s == target) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target && targetit == gIR->targetScopes.rend()) {
|
||||
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 finallys between start and end
|
||||
// emit code for enclosing handlers
|
||||
//
|
||||
|
||||
// since the labelstatements possibly inside are private
|
||||
// and might already exist push a label scope
|
||||
gIR->func()->pushUniqueLabelScope("enclosing");
|
||||
EnclosingHandler* tf = start;
|
||||
while(tf != end) {
|
||||
tf->emitCode(gIR);
|
||||
tf = tf->getEnclosing();
|
||||
IRState::TargetScopeVec::reverse_iterator it;
|
||||
for (it = gIR->targetScopes.rbegin(); it != targetit; ++it) {
|
||||
if (it->enclosinghandler)
|
||||
it->enclosinghandler->emitCode(gIR);
|
||||
}
|
||||
gIR->func()->popLabelScope();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,31 @@
|
|||
#include "gen/llvm.h"
|
||||
#include "statement.h"
|
||||
|
||||
// this is used for tracking try-finally, synchronized and volatile scopes
|
||||
struct EnclosingHandler
|
||||
{
|
||||
virtual void emitCode(IRState* p) = 0;
|
||||
};
|
||||
struct EnclosingTryFinally : EnclosingHandler
|
||||
{
|
||||
TryFinallyStatement* tf;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {}
|
||||
};
|
||||
struct EnclosingVolatile : EnclosingHandler
|
||||
{
|
||||
VolatileStatement* v;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
|
||||
};
|
||||
struct EnclosingSynchro : EnclosingHandler
|
||||
{
|
||||
SynchronizedStatement* s;
|
||||
void emitCode(IRState* p);
|
||||
EnclosingSynchro(SynchronizedStatement* _tf) : s(_tf) {}
|
||||
};
|
||||
|
||||
|
||||
// dynamic memory helpers
|
||||
LLValue* DtoNew(Type* newtype);
|
||||
void DtoDeleteMemory(LLValue* ptr);
|
||||
|
@ -16,17 +41,16 @@ llvm::AllocaInst* DtoAlloca(const LLType* lltype, const std::string& name = "");
|
|||
llvm::AllocaInst* DtoAlloca(const LLType* lltype, LLValue* arraysize, const std::string& name = "");
|
||||
|
||||
// assertion generator
|
||||
void DtoAssert(Module* M, Loc* loc, DValue* msg);
|
||||
void DtoAssert(Module* M, Loc loc, DValue* msg);
|
||||
|
||||
// return the LabelStatement from the current function with the given identifier or NULL if not found
|
||||
LabelStatement* DtoLabelStatement(Identifier* ident);
|
||||
// emit goto
|
||||
void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosingtryfinally, TryFinallyStatement* sourcetf);
|
||||
void DtoGoto(Loc loc, Identifier* target);
|
||||
|
||||
// generates IR for finally blocks between the 'start' and 'end' statements
|
||||
// will begin with the finally block belonging to 'start' and does not include
|
||||
// the finally block of 'end'
|
||||
void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end);
|
||||
// Generates IR for enclosing handlers between the current state and
|
||||
// the scope created by the 'target' statement.
|
||||
void DtoEnclosingHandlers(Loc loc, Statement* target);
|
||||
|
||||
// enters a critical section
|
||||
void DtoEnterCritical(LLValue* g);
|
||||
|
|
|
@ -76,7 +76,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
DtoAssign(loc, rvar, e);
|
||||
|
||||
// emit scopes
|
||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||
DtoEnclosingHandlers(loc, NULL);
|
||||
|
||||
// emit dbg end function
|
||||
if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
|
||||
|
@ -122,7 +122,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
Logger::cout() << "return value after cast: " << *v << '\n';
|
||||
}
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||
DtoEnclosingHandlers(loc, NULL);
|
||||
|
||||
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
|
||||
llvm::ReturnInst::Create(v, p->scopebb());
|
||||
|
@ -132,7 +132,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
else
|
||||
{
|
||||
assert(p->topfunc()->getReturnType() == LLType::VoidTy);
|
||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||
DtoEnclosingHandlers(loc, NULL);
|
||||
|
||||
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
|
||||
llvm::ReturnInst::Create(p->scopebb());
|
||||
|
@ -296,9 +296,9 @@ void WhileStatement::toIR(IRState* p)
|
|||
gIR->scope() = IRScope(whilebodybb,endbb);
|
||||
|
||||
// while body code
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,whilebb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,whilebb,endbb));
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// loop
|
||||
if (!gIR->scopereturned())
|
||||
|
@ -332,9 +332,9 @@ void DoStatement::toIR(IRState* p)
|
|||
gIR->scope() = IRScope(dowhilebb,condbb);
|
||||
|
||||
// do-while body code
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,condbb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,condbb,endbb));
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// branch to condition block
|
||||
llvm::BranchInst::Create(condbb, gIR->scopebb());
|
||||
|
@ -377,7 +377,7 @@ void ForStatement::toIR(IRState* p)
|
|||
assert(!gIR->scopereturned());
|
||||
llvm::BranchInst::Create(forbb, gIR->scopebb());
|
||||
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,forincbb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,forincbb,endbb));
|
||||
|
||||
// replace current scope
|
||||
gIR->scope() = IRScope(forbb,forbodybb);
|
||||
|
@ -420,7 +420,7 @@ void ForStatement::toIR(IRState* p)
|
|||
if (!gIR->scopereturned())
|
||||
llvm::BranchInst::Create(forbb, gIR->scopebb());
|
||||
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// rewrite the scope
|
||||
gIR->scope() = IRScope(endbb,oldend);
|
||||
|
@ -444,7 +444,7 @@ void BreakStatement::toIR(IRState* p)
|
|||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler);
|
||||
DtoEnclosingHandlers(loc, target);
|
||||
|
||||
// get the loop statement the label refers to
|
||||
Statement* targetLoopStatement = target->statement;
|
||||
|
@ -454,10 +454,10 @@ void BreakStatement::toIR(IRState* p)
|
|||
|
||||
// find the right break block and jump there
|
||||
bool found = false;
|
||||
IRState::LoopScopeVec::reverse_iterator it;
|
||||
for(it = p->loopbbs.rbegin(); it != p->loopbbs.rend(); ++it) {
|
||||
IRState::TargetScopeVec::reverse_iterator it;
|
||||
for(it = p->targetScopes.rbegin(); it != p->targetScopes.rend(); ++it) {
|
||||
if(it->s == targetLoopStatement) {
|
||||
llvm::BranchInst::Create(it->end, p->scopebb());
|
||||
llvm::BranchInst::Create(it->breakTarget, p->scopebb());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -465,8 +465,15 @@ void BreakStatement::toIR(IRState* p)
|
|||
assert(found);
|
||||
}
|
||||
else {
|
||||
DtoEnclosingHandlers(enclosinghandler, p->loopbbs.back().enclosinghandler);
|
||||
llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb());
|
||||
// find closest scope with a break target
|
||||
IRState::TargetScopeVec::reverse_iterator it;
|
||||
for(it = gIR->targetScopes.rbegin(); it != gIR->targetScopes.rend(); ++it) {
|
||||
if(it->breakTarget) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DtoEnclosingHandlers(loc, it->s);
|
||||
llvm::BranchInst::Create(it->breakTarget, gIR->scopebb());
|
||||
}
|
||||
|
||||
// the break terminated this basicblock, start a new one
|
||||
|
@ -488,7 +495,7 @@ void ContinueStatement::toIR(IRState* p)
|
|||
if (ident != 0) {
|
||||
Logger::println("ident = %s", ident->toChars());
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler);
|
||||
DtoEnclosingHandlers(loc, target);
|
||||
|
||||
// get the loop statement the label refers to
|
||||
Statement* targetLoopStatement = target->statement;
|
||||
|
@ -498,10 +505,10 @@ void ContinueStatement::toIR(IRState* p)
|
|||
|
||||
// find the right continue block and jump there
|
||||
bool found = false;
|
||||
IRState::LoopScopeVec::reverse_iterator it;
|
||||
for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) {
|
||||
IRState::TargetScopeVec::reverse_iterator it;
|
||||
for(it = gIR->targetScopes.rbegin(); it != gIR->targetScopes.rend(); ++it) {
|
||||
if(it->s == targetLoopStatement) {
|
||||
llvm::BranchInst::Create(it->begin, gIR->scopebb());
|
||||
llvm::BranchInst::Create(it->continueTarget, gIR->scopebb());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -509,15 +516,15 @@ void ContinueStatement::toIR(IRState* p)
|
|||
assert(found);
|
||||
}
|
||||
else {
|
||||
// can't 'continue' within switch, so omit them
|
||||
IRState::LoopScopeVec::reverse_iterator it;
|
||||
for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) {
|
||||
if(!it->isSwitch) {
|
||||
// find closest scope with a continue target
|
||||
IRState::TargetScopeVec::reverse_iterator it;
|
||||
for(it = gIR->targetScopes.rbegin(); it != gIR->targetScopes.rend(); ++it) {
|
||||
if(it->continueTarget) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DtoEnclosingHandlers(enclosinghandler, it->enclosinghandler);
|
||||
llvm::BranchInst::Create(it->begin, gIR->scopebb());
|
||||
DtoEnclosingHandlers(loc, it->s);
|
||||
llvm::BranchInst::Create(it->continueTarget, gIR->scopebb());
|
||||
}
|
||||
|
||||
// the continue terminated this basicblock, start a new one
|
||||
|
@ -586,7 +593,9 @@ void TryFinallyStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(trybb,finallybb);
|
||||
|
||||
assert(body);
|
||||
p->targetScopes.push_back(IRTargetScope(this,new EnclosingTryFinally(this),NULL,NULL));
|
||||
body->toIR(p);
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// terminate try BB
|
||||
if (!p->scopereturned())
|
||||
|
@ -842,9 +851,9 @@ void SwitchStatement::toIR(IRState* p)
|
|||
assert(body);
|
||||
|
||||
p->scope() = IRScope(bodybb, endbb);
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb,true));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,NULL,endbb));
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
if (!p->scopereturned())
|
||||
llvm::BranchInst::Create(endbb, p->scopebb());
|
||||
|
@ -963,13 +972,13 @@ void UnrolledLoopStatement::toIR(IRState* p)
|
|||
|
||||
// push loop scope
|
||||
// continue goes to next statement, break goes to end
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
|
||||
|
||||
// do statement
|
||||
s->toIR(p);
|
||||
|
||||
// pop loop scope
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// next stmt
|
||||
if (!p->scopereturned())
|
||||
|
@ -1086,10 +1095,10 @@ void ForeachStatement::toIR(IRState* p)
|
|||
}
|
||||
|
||||
// emit body
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
|
||||
if(body)
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
if (!p->scopereturned())
|
||||
llvm::BranchInst::Create(nextbb, p->scopebb());
|
||||
|
@ -1182,10 +1191,10 @@ void ForeachRangeStatement::toIR(IRState* p)
|
|||
}
|
||||
|
||||
// emit body
|
||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb));
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
|
||||
if (body)
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// jump to next iteration
|
||||
if (!p->scopereturned())
|
||||
|
@ -1251,8 +1260,11 @@ void LabelStatement::toIR(IRState* p)
|
|||
p->scope() = IRScope(labelBB,oldend);
|
||||
}
|
||||
|
||||
if (statement)
|
||||
if (statement) {
|
||||
p->targetScopes.push_back(IRTargetScope(this,NULL,NULL,NULL));
|
||||
statement->toIR(p);
|
||||
p->targetScopes.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1268,7 +1280,7 @@ void GotoStatement::toIR(IRState* p)
|
|||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend);
|
||||
|
||||
DtoGoto(&loc, label->ident, enclosinghandler, tf);
|
||||
DtoGoto(loc, label->ident);
|
||||
|
||||
p->scope() = IRScope(bb,oldend);
|
||||
}
|
||||
|
@ -1289,7 +1301,7 @@ void GotoDefaultStatement::toIR(IRState* p)
|
|||
assert(!p->scopereturned());
|
||||
assert(sw->sdefault->bodyBB);
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler);
|
||||
DtoEnclosingHandlers(loc, sw);
|
||||
|
||||
llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb());
|
||||
p->scope() = IRScope(bb,oldend);
|
||||
|
@ -1314,7 +1326,7 @@ void GotoCaseStatement::toIR(IRState* p)
|
|||
cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend());
|
||||
}
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler);
|
||||
DtoEnclosingHandlers(loc, sw);
|
||||
|
||||
llvm::BranchInst::Create(cs->bodyBB, p->scopebb());
|
||||
p->scope() = IRScope(bb,oldend);
|
||||
|
@ -1373,7 +1385,9 @@ void SynchronizedStatement::toIR(IRState* p)
|
|||
}
|
||||
|
||||
// emit body
|
||||
p->targetScopes.push_back(IRTargetScope(this,new EnclosingSynchro(this),NULL,NULL));
|
||||
body->toIR(p);
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// exit lock
|
||||
// no point in a unreachable unlock, terminating statements must insert this themselves.
|
||||
|
@ -1405,7 +1419,9 @@ void VolatileStatement::toIR(IRState* p)
|
|||
DtoMemoryBarrier(false, true, false, false);
|
||||
|
||||
// do statement
|
||||
p->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL));
|
||||
statement->toIR(p);
|
||||
p->targetScopes.pop_back();
|
||||
|
||||
// no point in a unreachable barrier, terminating statements must insert this themselves.
|
||||
if (statement->blockExit() & BEfallthru)
|
||||
|
|
|
@ -1783,7 +1783,7 @@ DValue* AssertExp::toElem(IRState* p)
|
|||
|
||||
// call assert runtime functions
|
||||
p->scope() = IRScope(assertbb,endbb);
|
||||
DtoAssert(p->func()->decl->getModule(), &loc, msg ? msg->toElem(p) : NULL);
|
||||
DtoAssert(p->func()->decl->getModule(), loc, msg ? msg->toElem(p) : NULL);
|
||||
|
||||
// rewrite the scope
|
||||
p->scope() = IRScope(endbb,oldend);
|
||||
|
@ -1958,7 +1958,7 @@ DValue* HaltExp::toElem(IRState* p)
|
|||
// FIXME: DMD inserts a trap here... we probably should as well !?!
|
||||
|
||||
#if 1
|
||||
DtoAssert(p->func()->decl->getModule(), &loc, NULL);
|
||||
DtoAssert(p->func()->decl->getModule(), loc, NULL);
|
||||
#else
|
||||
// call the new (?) trap intrinsic
|
||||
p->ir->CreateCall(GET_INTRINSIC_DECL(trap),"");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue