| ... | @@ -325,7 +325,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -325,7 +325,7 @@ pub fn genDecl(o: *Object) !void { |
| 325 | const func: *Module.Fn = func_payload.data; | 325 | const func: *Module.Fn = func_payload.data; |
| 326 | try o.indent_writer.insertNewline(); | 326 | try o.indent_writer.insertNewline(); |
| 327 | try o.dg.renderFunctionSignature(o.writer(), is_global); | 327 | try o.dg.renderFunctionSignature(o.writer(), is_global); |
| 328 | | 328 | |
| 329 | try o.writer().writeByte(' '); | 329 | try o.writer().writeByte(' '); |
| 330 | try genBody(o, func.body); | 330 | try genBody(o, func.body); |
| 331 | | 331 | |
| ... | @@ -586,28 +586,44 @@ fn genDbgStmt(o: *Object, inst: *Inst.NoOp) !CValue { | ... | @@ -586,28 +586,44 @@ fn genDbgStmt(o: *Object, inst: *Inst.NoOp) !CValue { |
| 586 | fn genBlock(o: *Object, inst: *Inst.Block) !CValue { | 586 | fn genBlock(o: *Object, inst: *Inst.Block) !CValue { |
| 587 | const block_id: usize = o.next_block_index; | 587 | const block_id: usize = o.next_block_index; |
| 588 | o.next_block_index += 1; | 588 | o.next_block_index += 1; |
| 589 | // abuse codegen.msv to store the block's id | 589 | const writer = o.writer(); |
| 590 | inst.codegen.mcv.a = block_id; | 590 | |
| | 591 | // store the block id in relocs.capacity as it is not used for anything else in the C backend. |
| | 592 | inst.codegen.relocs.capacity = block_id; |
| | 593 | const result = if (inst.base.ty.tag() != .void and !inst.base.isUnused()) blk: { |
| | 594 | // allocate a location for the result |
| | 595 | const local = try o.allocLocal(inst.base.ty, .Mut); |
| | 596 | try writer.writeAll(";\n"); |
| | 597 | break :blk local; |
| | 598 | } else |
| | 599 | CValue{ .none = {} }; |
| | 600 | |
| | 601 | inst.codegen.mcv = @bitCast(@import("../codegen.zig").AnyMCValue, result); |
| 591 | try genBody(o, inst.body); | 602 | try genBody(o, inst.body); |
| 592 | try o.indent_writer.insertNewline(); | 603 | try o.indent_writer.insertNewline(); |
| 593 | // label must be followed by an expression, add an empty one. | 604 | // label must be followed by an expression, add an empty one. |
| 594 | try o.writer().print("zig_block_{d}:;\n", .{block_id}); | 605 | try writer.print("zig_block_{d}:;\n", .{block_id}); |
| 595 | | 606 | return result; |
| 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 | } | 607 | } |
| 600 | | 608 | |
| 601 | fn genBr(o: *Object, inst: *Inst.Br) !CValue { | 609 | fn genBr(o: *Object, inst: *Inst.Br) !CValue { |
| 602 | if (inst.operand.ty.tag() != .void) { | 610 | const result = @bitCast(CValue, inst.block.codegen.mcv); |
| 603 | return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement block return values", .{}); | 611 | const writer = o.writer(); |
| | 612 | |
| | 613 | // If result is .none then the value of the block is unused. |
| | 614 | if (inst.operand.ty.tag() != .void and result != .none) { |
| | 615 | const operand = try o.resolveInst(inst.operand); |
| | 616 | try o.writeCValue(writer, result); |
| | 617 | try writer.writeAll(" = "); |
| | 618 | try o.writeCValue(writer, operand); |
| | 619 | try writer.writeAll(";\n"); |
| 604 | } | 620 | } |
| 605 | | 621 | |
| 606 | return genBrVoid(o, inst.block); | 622 | return genBrVoid(o, inst.block); |
| 607 | } | 623 | } |
| 608 | | 624 | |
| 609 | fn genBrVoid(o: *Object, block: *Inst.Block) !CValue { | 625 | fn genBrVoid(o: *Object, block: *Inst.Block) !CValue { |
| 610 | try o.writer().print("goto zig_block_{d};\n", .{block.codegen.mcv.a}); | 626 | try o.writer().print("goto zig_block_{d};\n", .{block.codegen.relocs.capacity}); |
| 611 | return CValue.none; | 627 | return CValue.none; |
| 612 | } | 628 | } |
| 613 | | 629 | |