aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2021-01-10 17:36:01 +0100
committerAndrew Kelley <andrew@ziglang.org>2021-01-10 17:47:34 -0800
commite1d8073d2fc0df6fbc5ce983312e3da374a9889b (patch)
tree11d8c5aa24c3c09dfec529c2d9f150511623c7b9
parent2117489e05ddf7cc4653feecbf47b3637276d6b6 (diff)
downloadzig-e1d8073d2fc0df6fbc5ce983312e3da374a9889b.tar.gz
zig-e1d8073d2fc0df6fbc5ce983312e3da374a9889b.zip
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.
-rw-r--r--src/codegen/llvm.zig12
-rw-r--r--src/zir.zig21
-rw-r--r--test/stage2/llvm.zig21
3 files changed, 52 insertions, 2 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index d6515f9ec6..5d753c41cb 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -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), "");
}
diff --git a/src/zir.zig b/src/zir.zig
index 4aee20991c..8d99218b3d 100644
--- a/src/zir.zig
+++ b/src/zir.zig
@@ -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,
=> {
diff --git a/test/stage2/llvm.zig b/test/stage2/llvm.zig
index eecea3d1f0..69622714a7 100644
--- a/test/stage2/llvm.zig
+++ b/test/stage2/llvm.zig
@@ -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;
+ \\}
+ , "");
+ }
}