mirror of
https://github.com/ziglang/zig.git
synced 2026-01-28 18:25:26 +00:00
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:
parent
2117489e05
commit
e1d8073d2f
@ -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), "");
|
||||
}
|
||||
|
||||
21
src/zir.zig
21
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,
|
||||
=> {
|
||||
|
||||
@ -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;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user