authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2021-01-10 17:36:01+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-10 17:47:34-08:00
loge1d8073d2fc0df6fbc5ce983312e3da374a9889b
tree11d8c5aa24c3c09dfec529c2d9f150511623c7b9
parent2117489e05ddf7cc4653feecbf47b3637276d6b6

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.

3 files changed, 52 insertions(+), 2 deletions(-)

src/codegen/llvm.zig+12
......@@ -396,6 +396,7 @@ pub const LLVMIRModule = struct {
396396 .condbr => try self.genCondBr(inst.castTag(.condbr).?),
397397 .intcast => try self.genIntCast(inst.castTag(.intcast).?),
398398 .load => try self.genLoad(inst.castTag(.load).?),
399 .loop => try self.genLoop(inst.castTag(.loop).?),
399400 .not => try self.genNot(inst.castTag(.not).?),
400401 .ret => try self.genRet(inst.castTag(.ret).?),
401402 .retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
......@@ -559,6 +560,17 @@ pub const LLVMIRModule = struct {
559560 return null;
560561 }
561562
563 fn genLoop(self: *LLVMIRModule, inst: *Inst.Loop) !?*const llvm.Value {
564 const loop_block = self.context.appendBasicBlock(self.llvm_func, "Loop");
565 _ = self.builder.buildBr(loop_block);
566
567 self.builder.positionBuilderAtEnd(loop_block);
568 try self.genBody(inst.body);
569
570 _ = self.builder.buildBr(loop_block);
571 return null;
572 }
573
562574 fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
563575 return self.builder.buildNot(try self.resolveInst(inst.operand), "");
564576 }
src/zir.zig+19-2
......@@ -2011,11 +2011,15 @@ const DumpTzir = struct {
20112011 try dtz.fetchInstsAndResolveConsts(condbr.else_body);
20122012 },
20132013
2014 .loop => {
2015 const loop = inst.castTag(.loop).?;
2016 try dtz.fetchInstsAndResolveConsts(loop.body);
2017 },
2018
20142019 // TODO fill out this debug printing
20152020 .assembly,
20162021 .call,
20172022 .constant,
2018 .loop,
20192023 .varptr,
20202024 .switchbr,
20212025 => {},
......@@ -2229,11 +2233,24 @@ const DumpTzir = struct {
22292233 try writer.writeAll(")\n");
22302234 },
22312235
2236 .loop => {
2237 const loop = inst.castTag(.loop).?;
2238
2239 try writer.writeAll("\n");
2240
2241 const old_indent = dtz.indent;
2242 dtz.indent += 2;
2243 try dtz.dumpBody(loop.body, writer);
2244 dtz.indent = old_indent;
2245
2246 try writer.writeByteNTimes(' ', dtz.indent);
2247 try writer.writeAll(")\n");
2248 },
2249
22322250 // TODO fill out this debug printing
22332251 .assembly,
22342252 .call,
22352253 .constant,
2236 .loop,
22372254 .varptr,
22382255 .switchbr,
22392256 => {
test/stage2/llvm.zig+21
......@@ -111,4 +111,25 @@ pub fn addCases(ctx: *TestContext) !void {
111111 \\}
112112 , "");
113113 }
114
115 {
116 var case = ctx.exeUsingLlvmBackend("while loops", linux_x64);
117
118 case.addCompareOutput(
119 \\fn assert(ok: bool) void {
120 \\ if (!ok) unreachable;
121 \\}
122 \\
123 \\export fn main() c_int {
124 \\ var sum: u32 = 0;
125 \\ var i: u32 = 0;
126 \\ while (i < 5) : (i += 1) {
127 \\ sum += i;
128 \\ }
129 \\ assert(sum == 10);
130 \\ assert(i == 5);
131 \\ return 0;
132 \\}
133 , "");
134 }
114135}