diff --git a/gen/statements.cpp b/gen/statements.cpp index 56b14267..6e8f878f 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -889,24 +889,66 @@ void UnrolledLoopStatement::toIR(IRState* p) 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(); - 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)); + // create a block for each statement + size_t nstmt = statements->dim; + LLSmallVector blocks(nstmt, NULL); - for (int i=0; idim; ++i) + for (size_t i=0; idata[i]; - s->toIR(p); + blocks[i] = llvm::BasicBlock::Create("unrolledstmt", p->topfunc(), oldend); } - p->loopbbs.pop_back(); + // create end block + llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend); - llvm::BranchInst::Create(endbb, p->scopebb()); + // enter first stmt + if (!p->scopereturned()) + p->ir->CreateBr(blocks[0]); + + // do statements + Statement** stmts = (Statement**)statements->data; + + for (int i=0; iscope() = 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); + } + + // finish scope + if (!p->scopereturned()) + p->ir->CreateBr(endbb); p->scope() = IRScope(endbb,oldend); }