mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-08-24 15:20:05 +02:00
Fixed problem with continue/break in unrolled loop statements.
This commit is contained in:
@@ -889,24 +889,66 @@ void UnrolledLoopStatement::toIR(IRState* p)
|
|||||||
Logger::println("UnrolledLoopStatement::toIR(): %s", loc.toChars());
|
Logger::println("UnrolledLoopStatement::toIR(): %s", loc.toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// if no statements, there's nothing to do
|
||||||
|
if (!statements || !statements->dim)
|
||||||
|
return;
|
||||||
|
|
||||||
if (global.params.symdebug)
|
if (global.params.symdebug)
|
||||||
DtoDwarfStopPoint(loc.linnum);
|
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* oldend = gIR->scopeend();
|
||||||
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend);
|
|
||||||
|
|
||||||
p->scope() = IRScope(p->scopebb(),endbb);
|
// create a block for each statement
|
||||||
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb));
|
size_t nstmt = statements->dim;
|
||||||
|
LLSmallVector<llvm::BasicBlock*, 4> blocks(nstmt, NULL);
|
||||||
|
|
||||||
for (int i=0; i<statements->dim; ++i)
|
for (size_t i=0; i<nstmt; i++)
|
||||||
{
|
{
|
||||||
Statement* s = (Statement*)statements->data[i];
|
blocks[i] = llvm::BasicBlock::Create("unrolledstmt", p->topfunc(), oldend);
|
||||||
s->toIR(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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; i<nstmt; i++)
|
||||||
|
{
|
||||||
|
Statement* s = stmts[i];
|
||||||
|
|
||||||
|
// get blocks
|
||||||
|
llvm::BasicBlock* thisbb = blocks[i];
|
||||||
|
llvm::BasicBlock* nextbb = (i+1 == nstmt) ? endbb : blocks[i+1];
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish scope
|
||||||
|
if (!p->scopereturned())
|
||||||
|
p->ir->CreateBr(endbb);
|
||||||
p->scope() = IRScope(endbb,oldend);
|
p->scope() = IRScope(endbb,oldend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user