| author | |
| committer | |
| log | e1d8073d2fc0df6fbc5ce983312e3da374a9889b |
| tree | 11d8c5aa24c3c09dfec529c2d9f150511623c7b9 |
| parent | 2117489e05ddf7cc4653feecbf47b3637276d6b6 |
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 { |
| 396 | 396 | .condbr => try self.genCondBr(inst.castTag(.condbr).?), |
| 397 | 397 | .intcast => try self.genIntCast(inst.castTag(.intcast).?), |
| 398 | 398 | .load => try self.genLoad(inst.castTag(.load).?), |
| 399 | .loop => try self.genLoop(inst.castTag(.loop).?), | |
| 399 | 400 | .not => try self.genNot(inst.castTag(.not).?), |
| 400 | 401 | .ret => try self.genRet(inst.castTag(.ret).?), |
| 401 | 402 | .retvoid => self.genRetVoid(inst.castTag(.retvoid).?), |
| ... | ... | @@ -559,6 +560,17 @@ pub const LLVMIRModule = struct { |
| 559 | 560 | return null; |
| 560 | 561 | } |
| 561 | 562 | |
| 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 | ||
| 562 | 574 | fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value { |
| 563 | 575 | return self.builder.buildNot(try self.resolveInst(inst.operand), ""); |
| 564 | 576 | } |
src/zir.zig+19-2| ... | ... | @@ -2011,11 +2011,15 @@ const DumpTzir = struct { |
| 2011 | 2011 | try dtz.fetchInstsAndResolveConsts(condbr.else_body); |
| 2012 | 2012 | }, |
| 2013 | 2013 | |
| 2014 | .loop => { | |
| 2015 | const loop = inst.castTag(.loop).?; | |
| 2016 | try dtz.fetchInstsAndResolveConsts(loop.body); | |
| 2017 | }, | |
| 2018 | ||
| 2014 | 2019 | // TODO fill out this debug printing |
| 2015 | 2020 | .assembly, |
| 2016 | 2021 | .call, |
| 2017 | 2022 | .constant, |
| 2018 | .loop, | |
| 2019 | 2023 | .varptr, |
| 2020 | 2024 | .switchbr, |
| 2021 | 2025 | => {}, |
| ... | ... | @@ -2229,11 +2233,24 @@ const DumpTzir = struct { |
| 2229 | 2233 | try writer.writeAll(")\n"); |
| 2230 | 2234 | }, |
| 2231 | 2235 | |
| 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 | ||
| 2232 | 2250 | // TODO fill out this debug printing |
| 2233 | 2251 | .assembly, |
| 2234 | 2252 | .call, |
| 2235 | 2253 | .constant, |
| 2236 | .loop, | |
| 2237 | 2254 | .varptr, |
| 2238 | 2255 | .switchbr, |
| 2239 | 2256 | => { |
test/stage2/llvm.zig+21| ... | ... | @@ -111,4 +111,25 @@ pub fn addCases(ctx: *TestContext) !void { |
| 111 | 111 | \\} |
| 112 | 112 | , ""); |
| 113 | 113 | } |
| 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 | } | |
| 114 | 135 | } |