stage2: add support for loops in LLVM backend

A simple `while(true) {}` loop generates the following LLVMIR:
```
define i32 @main() {
Entry:
  br label %Loop

Loop:                                 ; preds = %Loop, %Entry
  br label %Loop
}
```

Also implement TZIR printing for loops and add a corresponding test.
This commit is contained in:
Timon Kruiper 2021-01-10 17:36:01 +01:00 committed by Andrew Kelley
parent 2117489e05
commit e1d8073d2f
3 changed files with 52 additions and 2 deletions

View File

@ -396,6 +396,7 @@ pub const LLVMIRModule = struct {
.condbr => try self.genCondBr(inst.castTag(.condbr).?),
.intcast => try self.genIntCast(inst.castTag(.intcast).?),
.load => try self.genLoad(inst.castTag(.load).?),
.loop => try self.genLoop(inst.castTag(.loop).?),
.not => try self.genNot(inst.castTag(.not).?),
.ret => try self.genRet(inst.castTag(.ret).?),
.retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
@ -559,6 +560,17 @@ pub const LLVMIRModule = struct {
return null;
}
fn genLoop(self: *LLVMIRModule, inst: *Inst.Loop) !?*const llvm.Value {
const loop_block = self.context.appendBasicBlock(self.llvm_func, "Loop");
_ = self.builder.buildBr(loop_block);
self.builder.positionBuilderAtEnd(loop_block);
try self.genBody(inst.body);
_ = self.builder.buildBr(loop_block);
return null;
}
fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
return self.builder.buildNot(try self.resolveInst(inst.operand), "");
}

View File

@ -2011,11 +2011,15 @@ const DumpTzir = struct {
try dtz.fetchInstsAndResolveConsts(condbr.else_body);
},
.loop => {
const loop = inst.castTag(.loop).?;
try dtz.fetchInstsAndResolveConsts(loop.body);
},
// TODO fill out this debug printing
.assembly,
.call,
.constant,
.loop,
.varptr,
.switchbr,
=> {},
@ -2229,11 +2233,24 @@ const DumpTzir = struct {
try writer.writeAll(")\n");
},
.loop => {
const loop = inst.castTag(.loop).?;
try writer.writeAll("\n");
const old_indent = dtz.indent;
dtz.indent += 2;
try dtz.dumpBody(loop.body, writer);
dtz.indent = old_indent;
try writer.writeByteNTimes(' ', dtz.indent);
try writer.writeAll(")\n");
},
// TODO fill out this debug printing
.assembly,
.call,
.constant,
.loop,
.varptr,
.switchbr,
=> {

View File

@ -111,4 +111,25 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "");
}
{
var case = ctx.exeUsingLlvmBackend("while loops", linux_x64);
case.addCompareOutput(
\\fn assert(ok: bool) void {
\\ if (!ok) unreachable;
\\}
\\
\\export fn main() c_int {
\\ var sum: u32 = 0;
\\ var i: u32 = 0;
\\ while (i < 5) : (i += 1) {
\\ sum += i;
\\ }
\\ assert(sum == 10);
\\ assert(i == 5);
\\ return 0;
\\}
, "");
}
}