Mercurial > projects > ldc
changeset 774:9688da40cd4d
Fixed problem with continue/break in unrolled loop statements.
author | tomas@myhost |
---|---|
date | Wed, 19 Nov 2008 14:40:24 +0100 |
parents | 5696a7167b21 |
children | 0375841e3175 |
files | gen/statements.cpp |
diffstat | 1 files changed, 50 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/statements.cpp Tue Nov 18 18:07:57 2008 +0100 +++ b/gen/statements.cpp Wed Nov 19 14:40:24 2008 +0100 @@ -889,24 +889,66 @@ Logger::println("UnrolledLoopStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; + // if no statements, there's nothing to do + if (!statements || !statements->dim) + return; + if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); + // DMD doesn't fold stuff like continue/break, and since this isn't really a loop + // we have to keep track of each statement and jump to next the next/end on continue/break + llvm::BasicBlock* oldend = gIR->scopeend(); + + // create a block for each statement + size_t nstmt = statements->dim; + LLSmallVector<llvm::BasicBlock*, 4> blocks(nstmt, NULL); + + for (size_t i=0; i<nstmt; i++) + { + blocks[i] = llvm::BasicBlock::Create("unrolledstmt", p->topfunc(), oldend); + } + + // create end block llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend); - p->scope() = IRScope(p->scopebb(),endbb); - p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb)); + // enter first stmt + if (!p->scopereturned()) + p->ir->CreateBr(blocks[0]); + + // do statements + Statement** stmts = (Statement**)statements->data; + + for (int i=0; i<nstmt; i++) + { + Statement* s = stmts[i]; + + // get blocks + llvm::BasicBlock* thisbb = blocks[i]; + llvm::BasicBlock* nextbb = (i+1 == nstmt) ? endbb : blocks[i+1]; - for (int i=0; i<statements->dim; ++i) - { - Statement* s = (Statement*)statements->data[i]; + // update scope + p->scope() = IRScope(thisbb,nextbb); + + // push loop scope + // continue goes to next statement, break goes to end + p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb)); + + // do statement s->toIR(p); + + // pop loop scope + p->loopbbs.pop_back(); + + // next stmt + if (!p->scopereturned()) + p->ir->CreateBr(nextbb); } - p->loopbbs.pop_back(); - - llvm::BranchInst::Create(endbb, p->scopebb()); + // finish scope + if (!p->scopereturned()) + p->ir->CreateBr(endbb); p->scope() = IRScope(endbb,oldend); }