authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-01-26 21:09:40+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-01 08:47:25+02:00
logbdfe3aeab8310a64cc9c2f5fac194a609aa0f13d
treee85db06e6da871ead6feb649214da512854253bf
parent6ca0ff90b63cea79d8d63519a3c133cfde111884
signaturelock-open Commit is signed but in an unrecognized format.

stage2 cbe: condbr and breaks


2 files changed, 68 insertions(+), 6 deletions(-)

src/codegen/c.zig+50-6
......@@ -41,6 +41,7 @@ pub const Object = struct {
4141 value_map: CValueMap,
4242 next_arg_index: usize = 0,
4343 next_local_index: usize = 0,
44 next_block_index: usize = 0,
4445 indent_writer: std.io.AutoIndentingStream(std.ArrayList(u8).Writer),
4546
4647 fn resolveInst(o: *Object, inst: *Inst) !CValue {
......@@ -255,8 +256,8 @@ pub const DeclGen = struct {
255256 .int_signed, .int_unsigned => {
256257 const info = t.intInfo(dg.module.getTarget());
257258 const sign_prefix = switch (info.signedness) {
258 .signed => "i",
259 .unsigned => "",
259 .signed => "",
260 .unsigned => "u",
260261 };
261262 inline for (.{ 8, 16, 32, 64, 128 }) |nbits| {
262263 if (info.bits <= nbits) {
......@@ -325,6 +326,7 @@ pub fn genDecl(o: *Object) !void {
325326 try o.indent_writer.insertNewline();
326327 try o.dg.renderFunctionSignature(o.writer(), is_global);
327328
329 try o.writer().writeByte(' ');
328330 try genBody(o, func.body);
329331
330332 try o.indent_writer.insertNewline();
......@@ -372,11 +374,11 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
372374pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void {
373375 const writer = o.writer();
374376 if (body.instructions.len == 0) {
375 try writer.writeAll(" {}");
377 try writer.writeAll("{}");
376378 return;
377379 }
378380
379 try writer.writeAll(" {\n");
381 try writer.writeAll("{\n");
380382 o.indent_writer.pushIndent();
381383
382384 for (body.instructions) |inst| {
......@@ -404,6 +406,9 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
404406 .sub => try genBinOp(o, inst.castTag(.sub).?, " - "),
405407 .unreach => try genUnreach(o, inst.castTag(.unreach).?),
406408 .loop => try genLoop(o, inst.castTag(.loop).?),
409 .condbr => try genCondBr(o, inst.castTag(.condbr).?),
410 .br => try genBr(o, inst.castTag(.br).?),
411 .brvoid => try genBrVoid(o, inst.castTag(.brvoid).?.block),
407412 else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
408413 };
409414 switch (result_value) {
......@@ -579,7 +584,31 @@ fn genDbgStmt(o: *Object, inst: *Inst.NoOp) !CValue {
579584}
580585
581586fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
582 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement blocks", .{});
587 const block_id: usize = o.next_block_index;
588 o.next_block_index += 1;
589 // abuse codegen.msv to store the block's id
590 inst.codegen.mcv.a = block_id;
591 try genBody(o, inst.body);
592 try o.indent_writer.insertNewline();
593 // label must be followed by an expression, add an empty one.
594 try o.writer().print("zig_block_{d}:;\n", .{block_id});
595
596 // blocks in C cannot result in values
597 // TODO we need some other way to pass the result of the block
598 return CValue.none;
599}
600
601fn genBr(o: *Object, inst: *Inst.Br) !CValue {
602 if (inst.operand.ty.tag() != .void) {
603 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement block return values", .{});
604 }
605
606 return genBrVoid(o, inst.block);
607}
608
609fn genBrVoid(o: *Object, block: *Inst.Block) !CValue {
610 try o.writer().print("goto zig_block_{d};\n", .{block.codegen.mcv.a});
611 return CValue.none;
583612}
584613
585614fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
......@@ -622,12 +651,27 @@ fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue {
622651}
623652
624653fn genLoop(o: *Object, inst: *Inst.Loop) !CValue {
625 try o.writer().writeAll("while (true)");
654 try o.writer().writeAll("while (true) ");
626655 try genBody(o, inst.body);
627656 try o.indent_writer.insertNewline();
628657 return CValue.none;
629658}
630659
660fn genCondBr(o: *Object, inst: *Inst.CondBr) !CValue {
661 const cond = try o.resolveInst(inst.condition);
662 const writer = o.writer();
663
664 try writer.writeAll("if (");
665 try o.writeCValue(writer, cond);
666 try writer.writeAll(") ");
667 try genBody(o, inst.then_body);
668 try writer.writeAll(" else ");
669 try genBody(o, inst.else_body);
670 try o.indent_writer.insertNewline();
671
672 return CValue.none;
673}
674
631675fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
632676 if (as.base.isUnused() and !as.is_volatile)
633677 return CValue.none;
test/stage2/cbe.zig+18
......@@ -133,6 +133,24 @@ pub fn addCases(ctx: *TestContext) !void {
133133 \\}
134134 \\
135135 , "");
136
137 // Simple while loop
138 case.addCompareOutput(
139 \\export fn main() c_int {
140 \\ var a: c_int = 0;
141 \\ while (a < 5) : (a+=1) {}
142 \\ exit(a - 5);
143 \\}
144 \\
145 \\fn exit(code: usize) noreturn {
146 \\ asm volatile ("syscall"
147 \\ :
148 \\ : [number] "{rax}" (231),
149 \\ [arg1] "{rdi}" (code)
150 \\ );
151 \\ unreachable;
152 \\}
153 , "");
136154 }
137155
138156 {