| ... | ... | @@ -325,7 +325,7 @@ pub fn genDecl(o: *Object) !void { |
| 325 | 325 | const func: *Module.Fn = func_payload.data; |
| 326 | 326 | try o.indent_writer.insertNewline(); |
| 327 | 327 | try o.dg.renderFunctionSignature(o.writer(), is_global); |
| 328 | | |
| 328 | |
| 329 | 329 | try o.writer().writeByte(' '); |
| 330 | 330 | try genBody(o, func.body); |
| 331 | 331 | |
| ... | ... | @@ -586,28 +586,44 @@ fn genDbgStmt(o: *Object, inst: *Inst.NoOp) !CValue { |
| 586 | 586 | fn genBlock(o: *Object, inst: *Inst.Block) !CValue { |
| 587 | 587 | const block_id: usize = o.next_block_index; |
| 588 | 588 | o.next_block_index += 1; |
| 589 | | // abuse codegen.msv to store the block's id |
| 590 | | inst.codegen.mcv.a = block_id; |
| 589 | const writer = o.writer(); |
| 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 | 602 | try genBody(o, inst.body); |
| 592 | 603 | try o.indent_writer.insertNewline(); |
| 593 | 604 | // 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; |
| 605 | try writer.print("zig_block_{d}:;\n", .{block_id}); |
| 606 | return result; |
| 599 | 607 | } |
| 600 | 608 | |
| 601 | 609 | fn 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", .{}); |
| 610 | const result = @bitCast(CValue, inst.block.codegen.mcv); |
| 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 | 622 | return genBrVoid(o, inst.block); |
| 607 | 623 | } |
| 608 | 624 | |
| 609 | 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 | 627 | return CValue.none; |
| 612 | 628 | } |
| 613 | 629 | |