# HG changeset patch # User ChristianK # Date 1204986127 -3600 # Node ID 8f704cb9969bab9b5bf35d258eb05c411036fe18 # Parent a27941d00351ec0738c7a139e8933d5fff7d3e77 [svn r150] fixes #16 and #17, implements GotoCaseStatement diff -r a27941d00351 -r 8f704cb9969b dmd/scope.c --- a/dmd/scope.c Sat Jan 26 17:13:22 2008 +0100 +++ b/dmd/scope.c Sat Mar 08 15:22:07 2008 +0100 @@ -53,6 +53,7 @@ this->parent = NULL; this->sw = NULL; this->tf = NULL; + this->tfOfTry = NULL; this->sbreak = NULL; this->scontinue = NULL; this->fes = NULL; @@ -89,6 +90,7 @@ this->sd = NULL; this->sw = enclosing->sw; this->tf = enclosing->tf; + this->tfOfTry = enclosing->tfOfTry; this->sbreak = enclosing->sbreak; this->scontinue = enclosing->scontinue; this->fes = enclosing->fes; diff -r a27941d00351 -r 8f704cb9969b dmd/scope.h --- a/dmd/scope.h Sat Jan 26 17:13:22 2008 +0100 +++ b/dmd/scope.h Sat Mar 08 15:22:07 2008 +0100 @@ -44,7 +44,8 @@ Dsymbol *parent; // parent to use LabelStatement *slabel; // enclosing labelled statement SwitchStatement *sw; // enclosing switch statement - TryFinallyStatement *tf; // enclosing try finally statement + TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block + TryFinallyStatement *tfOfTry; // enclosing try finally statement; set inside its try block Statement *sbreak; // enclosing statement that supports "break" Statement *scontinue; // enclosing statement that supports "continue" ForeachStatement *fes; // if nested function for ForeachStatement, this is it diff -r a27941d00351 -r 8f704cb9969b dmd/statement.c --- a/dmd/statement.c Sat Jan 26 17:13:22 2008 +0100 +++ b/dmd/statement.c Sat Mar 08 15:22:07 2008 +0100 @@ -561,6 +561,7 @@ : Statement(loc) { statements = s; + enclosingtry = NULL; } Statement *UnrolledLoopStatement::syntaxCopy() @@ -582,6 +583,8 @@ { //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc); + enclosingtry = sc->tfOfTry; + sc->noctor++; Scope *scd = sc->push(); scd->sbreak = this; @@ -771,6 +774,7 @@ { condition = c; body = b; + enclosingtry = NULL; } Statement *WhileStatement::syntaxCopy() @@ -805,6 +809,8 @@ } #endif + enclosingtry = sc->tfOfTry; + condition = condition->semantic(sc); condition = resolveProperties(sc, condition); condition = condition->optimize(WANTvalue); @@ -870,6 +876,7 @@ { body = b; condition = c; + enclosingtry = NULL; } Statement *DoStatement::syntaxCopy() @@ -881,6 +888,8 @@ Statement *DoStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; + sc->noctor++; if (body) body = body->semanticScope(sc, this, this); @@ -943,6 +952,7 @@ this->condition = condition; this->increment = increment; this->body = body; + this->enclosingtry = NULL; } Statement *ForStatement::syntaxCopy() @@ -962,6 +972,8 @@ Statement *ForStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; + ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc->scopesym; sc = sc->push(sym); @@ -1074,6 +1086,7 @@ this->arguments = arguments; this->aggr = aggr; this->body = body; + this->enclosingtry = NULL; this->key = NULL; this->value = NULL; @@ -1102,6 +1115,8 @@ Type *tn = NULL; Type *tnv = NULL; + enclosingtry = sc->tfOfTry; + func = sc->func; if (func->fes) func = func->fes->func; @@ -1956,7 +1971,7 @@ cases = NULL; hasNoDefault = 0; // LLVMDC - defaultBB = NULL; + enclosingtry = NULL; } Statement *SwitchStatement::syntaxCopy() @@ -1970,6 +1985,9 @@ { //printf("SwitchStatement::semantic(%p)\n", this); assert(!cases); // ensure semantic() is only run once + + enclosingtry = sc->tfOfTry; + condition = condition->semantic(sc); condition = resolveProperties(sc, condition); if (condition->type->isString()) @@ -2107,6 +2125,7 @@ this->exp = exp; this->statement = s; cblock = NULL; + bodyBB = NULL; } Statement *CaseStatement::syntaxCopy() @@ -2203,6 +2222,7 @@ #if IN_GCC + cblock = NULL; #endif + bodyBB = NULL; } Statement *DefaultStatement::syntaxCopy() @@ -2254,6 +2274,7 @@ : Statement(loc) { sw = NULL; + enclosingtry = NULL; } Statement *GotoDefaultStatement::syntaxCopy() @@ -2264,6 +2285,7 @@ Statement *GotoDefaultStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; sw = sc->sw; if (!sw) error("goto default not in switch statement"); @@ -2287,6 +2309,8 @@ { cs = NULL; this->exp = exp; + enclosingtry = NULL; + sw = NULL; } Statement *GotoCaseStatement::syntaxCopy() @@ -2298,6 +2322,7 @@ Statement *GotoCaseStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; if (exp) exp = exp->semantic(sc); @@ -2305,6 +2330,7 @@ error("goto case not in switch statement"); else { + sw = sc->sw; sc->sw->gotoCases.push(this); if (exp) { @@ -2355,6 +2381,7 @@ : Statement(loc) { this->exp = exp; + this->enclosingtry = NULL; } Statement *ReturnStatement::syntaxCopy() @@ -2369,6 +2396,7 @@ Statement *ReturnStatement::semantic(Scope *sc) { //printf("ReturnStatement::semantic() %s\n", toChars()); + this->enclosingtry = sc->tfOfTry; FuncDeclaration *fd = sc->parent->isFuncDeclaration(); Scope *scx = sc; @@ -2629,6 +2657,7 @@ : Statement(loc) { this->ident = ident; + this->enclosingtry = NULL; } Statement *BreakStatement::syntaxCopy() @@ -2639,6 +2668,7 @@ Statement *BreakStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; // If: // break Identifier; if (ident) @@ -2678,6 +2708,8 @@ error("label '%s' has no break", ident->toChars()); if (ls->tf != sc->tf) error("cannot break out of finally block"); + + this->target = ls; return this; } } @@ -2719,6 +2751,7 @@ : Statement(loc) { this->ident = ident; + this->enclosingtry = NULL; } Statement *ContinueStatement::syntaxCopy() @@ -2729,6 +2762,7 @@ Statement *ContinueStatement::semantic(Scope *sc) { + enclosingtry = sc->tfOfTry; //printf("ContinueStatement::semantic() %p\n", this); if (ident) { @@ -2777,6 +2811,8 @@ error("label '%s' has no continue", ident->toChars()); if (ls->tf != sc->tf) error("cannot continue out of finally block"); + + this->target = ls; return this; } } @@ -3159,6 +3195,7 @@ { this->body = body; this->finalbody = finalbody; + this->enclosingtry = NULL; } Statement *TryFinallyStatement::syntaxCopy() @@ -3171,7 +3208,12 @@ Statement *TryFinallyStatement::semantic(Scope *sc) { //printf("TryFinallyStatement::semantic()\n"); + + enclosingtry = sc->tfOfTry; + sc->tfOfTry = this; body = body->semantic(sc); + sc->tfOfTry = enclosingtry; + sc = sc->push(); sc->tf = this; sc->sbreak = NULL; @@ -3405,6 +3447,7 @@ this->ident = ident; this->label = NULL; this->tf = NULL; + this->enclosingtry = NULL; } Statement *GotoStatement::syntaxCopy() @@ -3418,6 +3461,7 @@ //printf("GotoStatement::semantic()\n"); tf = sc->tf; + enclosingtry = sc->tfOfTry; label = fd->searchLabel(ident); if (!label->statement && sc->fes) { @@ -3461,6 +3505,7 @@ this->ident = ident; this->statement = statement; this->tf = NULL; + this->enclosingtry = NULL; this->lblock = NULL; this->isReturnLabel = 0; this->llvmBB = NULL; @@ -3483,6 +3528,7 @@ else ls->statement = this; tf = sc->tf; + enclosingtry = sc->tfOfTry; sc = sc->push(); sc->scopesym = sc->enclosing->scopesym; sc->callSuper |= CSXlabel; diff -r a27941d00351 -r 8f704cb9969b dmd/statement.h --- a/dmd/statement.h Sat Jan 26 17:13:22 2008 +0100 +++ b/dmd/statement.h Sat Mar 08 15:22:07 2008 +0100 @@ -44,9 +44,11 @@ struct GotoStatement; struct ScopeStatement; struct TryCatchStatement; +struct TryFinallyStatement; struct HdrGenState; struct InterState; struct CaseStatement; +struct LabelStatement; enum TOK; @@ -191,6 +193,7 @@ struct UnrolledLoopStatement : Statement { Statements *statements; + TryFinallyStatement *enclosingtry; UnrolledLoopStatement(Loc loc, Statements *statements); Statement *syntaxCopy(); @@ -235,6 +238,7 @@ { Expression *condition; Statement *body; + TryFinallyStatement *enclosingtry; WhileStatement(Loc loc, Expression *c, Statement *b); Statement *syntaxCopy(); @@ -256,6 +260,7 @@ { Statement *body; Expression *condition; + TryFinallyStatement *enclosingtry; DoStatement(Loc loc, Statement *b, Expression *c); Statement *syntaxCopy(); @@ -279,6 +284,7 @@ Expression *condition; Expression *increment; Statement *body; + TryFinallyStatement *enclosingtry; ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); Statement *syntaxCopy(); @@ -303,6 +309,7 @@ Arguments *arguments; // array of Argument*'s Expression *aggr; Statement *body; + TryFinallyStatement *enclosingtry; VarDeclaration *key; VarDeclaration *value; @@ -399,6 +406,7 @@ Expression *condition; Statement *body; DefaultStatement *sdefault; + TryFinallyStatement *enclosingtry; Array gotoCases; // array of unresolved GotoCaseStatement's Array *cases; // array of CaseStatement's @@ -416,9 +424,6 @@ Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); - - // LLVMDC - llvm::BasicBlock* defaultBB; }; struct CaseStatement : Statement @@ -443,6 +448,9 @@ void toIR(IRState *irs); CaseStatement* isCaseStatement() { return this; } + + // LLVMDC + llvm::BasicBlock* bodyBB; }; struct DefaultStatement : Statement @@ -464,11 +472,15 @@ Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); + + // LLVMDC + llvm::BasicBlock* bodyBB; }; struct GotoDefaultStatement : Statement { SwitchStatement *sw; + TryFinallyStatement *enclosingtry; GotoDefaultStatement(Loc loc); Statement *syntaxCopy(); @@ -484,6 +496,8 @@ { Expression *exp; // NULL, or which case to goto CaseStatement *cs; // case statement it resolves to + TryFinallyStatement *enclosingtry; + SwitchStatement *sw; GotoCaseStatement(Loc loc, Expression *exp); Statement *syntaxCopy(); @@ -507,6 +521,7 @@ struct ReturnStatement : Statement { Expression *exp; + TryFinallyStatement *enclosingtry; ReturnStatement(Loc loc, Expression *exp); Statement *syntaxCopy(); @@ -527,6 +542,7 @@ struct BreakStatement : Statement { Identifier *ident; + TryFinallyStatement *enclosingtry; BreakStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -536,11 +552,15 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); + + // LLVMDC: only set if ident is set: label statement to jump to + LabelStatement *target; }; struct ContinueStatement : Statement { Identifier *ident; + TryFinallyStatement *enclosingtry; ContinueStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -550,6 +570,9 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); + + // LLVMDC: only set if ident is set: label statement to jump to + LabelStatement *target; }; struct SynchronizedStatement : Statement @@ -629,6 +652,7 @@ { Statement *body; Statement *finalbody; + TryFinallyStatement *enclosingtry; TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody); Statement *syntaxCopy(); @@ -695,6 +719,7 @@ Identifier *ident; LabelDsymbol *label; TryFinallyStatement *tf; + TryFinallyStatement *enclosingtry; GotoStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -712,6 +737,7 @@ Identifier *ident; Statement *statement; TryFinallyStatement *tf; + TryFinallyStatement *enclosingtry; block *lblock; // back end int isReturnLabel; diff -r a27941d00351 -r 8f704cb9969b gen/irstate.cpp --- a/gen/irstate.cpp Sat Jan 26 17:13:22 2008 +0100 +++ b/gen/irstate.cpp Sat Mar 08 15:22:07 2008 +0100 @@ -31,6 +31,20 @@ } ////////////////////////////////////////////////////////////////////////////////////////// +IRLoopScope::IRLoopScope() +{ +} + +IRLoopScope::IRLoopScope(Statement* s, TryFinallyStatement* enclosingtry, llvm::BasicBlock* b, llvm::BasicBlock* e) +{ + begin = b; + end = e; + builder.SetInsertPoint(b); + this->s = s; + this->enclosingtry = enclosingtry; +} + +////////////////////////////////////////////////////////////////////////////////////////// IRState::IRState() { dmodule = 0; diff -r a27941d00351 -r 8f704cb9969b gen/irstate.h --- a/gen/irstate.h Sat Jan 26 17:13:22 2008 +0100 +++ b/gen/irstate.h Sat Mar 08 15:22:07 2008 +0100 @@ -23,6 +23,7 @@ struct Module; struct TypeStruct; struct BaseClass; +struct TryFinallyStatement; // represents a scope struct IRScope @@ -35,6 +36,18 @@ IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e); }; +// scope for loops +struct IRLoopScope : IRScope +{ + // generating statement + Statement* s; + // the try of a TryFinally that encloses the loop + TryFinallyStatement* enclosingtry; + + IRLoopScope(); + IRLoopScope(Statement* s, TryFinallyStatement* enclosingtry, llvm::BasicBlock* b, llvm::BasicBlock* e); +}; + struct IRBuilderHelper { IRState* state; @@ -95,7 +108,8 @@ // loop blocks typedef std::vector BBVec; - BBVec loopbbs; + typedef std::vector LoopScopeVec; + LoopScopeVec loopbbs; // 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 diff -r a27941d00351 -r 8f704cb9969b gen/statements.cpp --- a/gen/statements.cpp Sat Jan 26 17:13:22 2008 +0100 +++ b/gen/statements.cpp Sat Mar 08 15:22:07 2008 +0100 @@ -45,6 +45,28 @@ ////////////////////////////////////////////////////////////////////////////// +// 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 emit_finallyblocks(IRState* p, TryFinallyStatement* start, TryFinallyStatement* end) +{ + // verify that end encloses start + TryFinallyStatement* endfinally = start; + while(endfinally != NULL && endfinally != end) { + endfinally = endfinally->enclosingtry; + } + assert(endfinally == end); + + // emit code for finallys between start and end + TryFinallyStatement* tf = start; + while(tf != end) { + tf->finalbody->toIR(p); + tf = tf->enclosingtry; + } +} + +////////////////////////////////////////////////////////////////////////////// + void ReturnStatement::toIR(IRState* p) { Logger::println("ReturnStatement::toIR(): %s", loc.toChars()); @@ -68,14 +90,11 @@ if (!e->inPlace()) DtoAssign(rvar, e); - IrFunction::FinallyVec& fin = f->finallys; - if (fin.empty()) { - if (global.params.symdebug) DtoDwarfFuncEnd(f->decl); - new llvm::ReturnInst(p->scopebb()); - } - else { - new llvm::BranchInst(fin.back().retbb, p->scopebb()); - } + emit_finallyblocks(p, enclosingtry, NULL); + + if (global.params.symdebug) DtoDwarfFuncEnd(f->decl); + new llvm::ReturnInst(p->scopebb()); + } else { if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); @@ -84,31 +103,19 @@ delete e; Logger::cout() << "return value is '" <<*v << "'\n"; - IrFunction::FinallyVec& fin = p->func()->finallys; - if (fin.empty()) { - if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); - new llvm::ReturnInst(v, p->scopebb()); - } - else { - if (!p->func()->finallyretval) - p->func()->finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); - llvm::Value* rettmp = p->func()->finallyretval; - new llvm::StoreInst(v,rettmp,p->scopebb()); - new llvm::BranchInst(fin.back().retbb, p->scopebb()); - } + emit_finallyblocks(p, enclosingtry, NULL); + + if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); + new llvm::ReturnInst(v, p->scopebb()); } } else { if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { - IrFunction::FinallyVec& fin = p->func()->finallys; - if (fin.empty()) { - if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); - new llvm::ReturnInst(p->scopebb()); - } - else { - new llvm::BranchInst(fin.back().retbb, p->scopebb()); - } + emit_finallyblocks(p, enclosingtry, NULL); + + if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); + new llvm::ReturnInst(p->scopebb()); } else { assert(0); // why should this ever happen? @@ -247,7 +254,7 @@ gIR->scope() = IRScope(whilebodybb,endbb); // while body code - p->loopbbs.push_back(IRScope(whilebb,endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,whilebb,endbb)); body->toIR(p); p->loopbbs.pop_back(); @@ -279,7 +286,7 @@ gIR->scope() = IRScope(dowhilebb,endbb); // do-while body code - p->loopbbs.push_back(IRScope(dowhilebb,endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,dowhilebb,endbb)); body->toIR(p); p->loopbbs.pop_back(); @@ -317,7 +324,7 @@ assert(!gIR->scopereturned()); new llvm::BranchInst(forbb, gIR->scopebb()); - p->loopbbs.push_back(IRScope(forincbb,endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,forincbb,endbb)); // replace current scope gIR->scope() = IRScope(forbb,forbodybb); @@ -367,9 +374,27 @@ if (ident != 0) { Logger::println("ident = %s", ident->toChars()); + + emit_finallyblocks(p, enclosingtry, target->enclosingtry); + + // get the loop statement the label refers to + Statement* targetLoopStatement = target->statement; + ScopeStatement* tmp; + while(tmp = targetLoopStatement->isScopeStatement()) + targetLoopStatement = tmp->statement; + + // find the right break block and jump there + IRState::LoopScopeVec::reverse_iterator it; + for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) { + if(it->s == targetLoopStatement) { + new llvm::BranchInst(it->end, gIR->scopebb()); + return; + } + } assert(0); } else { + emit_finallyblocks(p, enclosingtry, gIR->loopbbs.back().enclosingtry); new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebb()); } } @@ -383,9 +408,27 @@ if (ident != 0) { Logger::println("ident = %s", ident->toChars()); + + emit_finallyblocks(p, enclosingtry, target->enclosingtry); + + // get the loop statement the label refers to + Statement* targetLoopStatement = target->statement; + ScopeStatement* tmp; + while(tmp = targetLoopStatement->isScopeStatement()) + targetLoopStatement = tmp->statement; + + // find the right continue block and jump there + IRState::LoopScopeVec::reverse_iterator it; + for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) { + if(it->s == targetLoopStatement) { + new llvm::BranchInst(it->begin, gIR->scopebb()); + return; + } + } assert(0); } else { + emit_finallyblocks(p, enclosingtry, gIR->loopbbs.back().enclosingtry); new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebb()); } } @@ -413,7 +456,6 @@ llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); - llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend); llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); // pass the previous BB into this @@ -422,8 +464,6 @@ // do the try block p->scope() = IRScope(trybb,finallybb); - gIR->func()->finallys.push_back(IrFinally(finallybb,finallyretbb)); - IrFinally& fin = p->func()->finallys.back(); assert(body); body->toIR(p); @@ -433,7 +473,7 @@ new llvm::BranchInst(finallybb, p->scopebb()); // do finally block - p->scope() = IRScope(finallybb,finallyretbb); + p->scope() = IRScope(finallybb,endbb); assert(finalbody); finalbody->toIR(p); @@ -442,40 +482,7 @@ new llvm::BranchInst(endbb, p->scopebb()); } - // do finally block (return path) - p->scope() = IRScope(finallyretbb,endbb); - assert(finalbody); - finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed - - // terminate finally (return path) - size_t nfin = p->func()->finallys.size(); - if (nfin > 1) { - IrFinally& ofin = p->func()->finallys[nfin-2]; - p->ir->CreateBr(ofin.retbb); - } - // no outer - else - { - if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); - llvm::Value* retval = p->func()->finallyretval; - if (retval) { - retval = p->ir->CreateLoad(retval,"tmp"); - p->ir->CreateRet(retval); - } - else { - FuncDeclaration* fd = p->func()->decl; - if (fd->isMain()) { - assert(fd->type->next->ty == Tvoid); - p->ir->CreateRet(DtoConstInt(0)); - } - else { - p->ir->CreateRetVoid(); - } - } - } - // rewrite the scope - p->func()->finallys.pop_back(); p->scope() = IRScope(endbb,oldend); } @@ -603,6 +610,7 @@ std::string lblname("case"); llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend); + cs->bodyBB = bb; std::vector tmp; CaseStatement* last; @@ -670,7 +678,7 @@ llvm::BasicBlock* defbb = 0; if (!hasNoDefault) { defbb = new llvm::BasicBlock("default", p->topfunc(), oldend); - defaultBB = defbb; + sdefault->bodyBB = defbb; } // end (break point) @@ -705,8 +713,7 @@ { llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first; p->scope() = IRScope(vcases[i].first,nextbb); - - p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,p->scopebb(),endbb)); vbodies[i]->toIR(p); p->loopbbs.pop_back(); @@ -721,7 +728,7 @@ if (defbb) { p->scope() = IRScope(defbb,endbb); - p->loopbbs.push_back(IRScope(defbb,endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,p->scopebb(),endbb)); Logger::println("doing default statement"); sdefault->statement->toIR(p); p->loopbbs.pop_back(); @@ -756,7 +763,7 @@ llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend); p->scope() = IRScope(p->scopebb(),endbb); - p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,p->scopebb(),endbb)); for (int i=0; idim; ++i) { @@ -914,7 +921,7 @@ } // emit body - p->loopbbs.push_back(IRScope(nextbb,endbb)); + p->loopbbs.push_back(IRLoopScope(this,enclosingtry,nextbb,endbb)); body->toIR(p); p->loopbbs.pop_back(); @@ -973,6 +980,20 @@ if (label->statement->llvmBB == NULL) label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc()); assert(!p->scopereturned()); + + // find finallys between goto and label + TryFinallyStatement* endfinally = enclosingtry; + while(endfinally != NULL && endfinally != label->statement->enclosingtry) { + endfinally = endfinally->enclosingtry; + } + + // error if didn't find tf statement of label + if(endfinally != label->statement->enclosingtry) + error("cannot goto into try block", loc.toChars()); + + // emit code for finallys between goto and label + emit_finallyblocks(p, enclosingtry, endfinally); + new llvm::BranchInst(label->statement->llvmBB, p->scopebb()); p->scope() = IRScope(bb,oldend); } @@ -988,8 +1009,30 @@ llvm::BasicBlock* bb = new llvm::BasicBlock("aftergotodefault", p->topfunc(), oldend); assert(!p->scopereturned()); - assert(sw->defaultBB); - new llvm::BranchInst(sw->defaultBB, p->scopebb()); + assert(sw->sdefault->bodyBB); + + emit_finallyblocks(p, enclosingtry, sw->enclosingtry); + + new llvm::BranchInst(sw->sdefault->bodyBB, p->scopebb()); + p->scope() = IRScope(bb,oldend); +} + +////////////////////////////////////////////////////////////////////////////// + +void GotoCaseStatement::toIR(IRState* p) +{ + Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars()); + LOG_SCOPE; + + llvm::BasicBlock* oldend = gIR->scopeend(); + llvm::BasicBlock* bb = new llvm::BasicBlock("aftergotocase", p->topfunc(), oldend); + + assert(!p->scopereturned()); + assert(cs->bodyBB); + + emit_finallyblocks(p, enclosingtry, sw->enclosingtry); + + new llvm::BranchInst(cs->bodyBB, p->scopebb()); p->scope() = IRScope(bb,oldend); } @@ -1097,7 +1140,7 @@ //STUBST(VolatileStatement); //STUBST(LabelStatement); //STUBST(ThrowStatement); -STUBST(GotoCaseStatement); +//STUBST(GotoCaseStatement); //STUBST(GotoDefaultStatement); //STUBST(GotoStatement); //STUBST(UnrolledLoopStatement); diff -r a27941d00351 -r 8f704cb9969b ir/irfunction.cpp --- a/ir/irfunction.cpp Sat Jan 26 17:13:22 2008 +0100 +++ b/ir/irfunction.cpp Sat Mar 08 15:22:07 2008 +0100 @@ -1,18 +1,6 @@ #include "gen/tollvm.h" #include "ir/irfunction.h" -IrFinally::IrFinally() -{ - bb = 0; - retbb = 0; -} - -IrFinally::IrFinally(llvm::BasicBlock* b, llvm::BasicBlock* rb) -{ - bb = b; - retbb = rb; -} - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -26,7 +14,6 @@ type = (TypeFunction*)t; func = NULL; allocapoint = NULL; - finallyretval = NULL; queued = false; defined = false; diff -r a27941d00351 -r 8f704cb9969b ir/irfunction.h --- a/ir/irfunction.h Sat Jan 26 17:13:22 2008 +0100 +++ b/ir/irfunction.h Sat Mar 08 15:22:07 2008 +0100 @@ -5,16 +5,6 @@ #include -// represents a finally block -struct IrFinally -{ - llvm::BasicBlock* bb; - llvm::BasicBlock* retbb; - - IrFinally(); - IrFinally(llvm::BasicBlock* b, llvm::BasicBlock* rb); -}; - // represents a function struct IrFunction : IrBase { @@ -23,11 +13,6 @@ FuncDeclaration* decl; TypeFunction* type; - // finally blocks - typedef std::vector FinallyVec; - FinallyVec finallys; - llvm::Value* finallyretval; - bool queued; bool defined; llvm::Value* retArg;