| author | |
| committer | |
| log | 3a516433b0cf94e8aa67819acc49c03e0b72f296 |
| tree | 38987d39742575658f31fe9b1b2fee4c355350df |
| parent | abb37a7cb8d4bfae2da6d2cb9e9e6305ef6e52c4 |
3 files changed, 138 insertions(+), 57 deletions(-)
src/arch/x86_64/CodeGen.zig+68-1| ... | @@ -8,6 +8,7 @@ const link = @import("../../link.zig"); | ... | @@ -8,6 +8,7 @@ const link = @import("../../link.zig"); |
| 8 | const log = std.log.scoped(.codegen); | 8 | const log = std.log.scoped(.codegen); |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const mem = std.mem; | 10 | const mem = std.mem; |
| 11 | const print_air = @import("../../print_air.zig"); | ||
| 11 | const trace = @import("../../tracy.zig").trace; | 12 | const trace = @import("../../tracy.zig").trace; |
| 12 | 13 | ||
| 13 | const Air = @import("../../Air.zig"); | 14 | const Air = @import("../../Air.zig"); |
| ... | @@ -20,6 +21,7 @@ const ErrorMsg = Module.ErrorMsg; | ... | @@ -20,6 +21,7 @@ const ErrorMsg = Module.ErrorMsg; |
| 20 | const Result = codegen.Result; | 21 | const Result = codegen.Result; |
| 21 | const Emit = @import("Emit.zig"); | 22 | const Emit = @import("Emit.zig"); |
| 22 | const Liveness = @import("../../Liveness.zig"); | 23 | const Liveness = @import("../../Liveness.zig"); |
| 24 | const Lower = @import("Lower.zig"); | ||
| 23 | const Mir = @import("Mir.zig"); | 25 | const Mir = @import("Mir.zig"); |
| 24 | const Module = @import("../../Module.zig"); | 26 | const Module = @import("../../Module.zig"); |
| 25 | const Target = std.Target; | 27 | const Target = std.Target; |
| ... | @@ -44,6 +46,8 @@ const sse = abi.RegisterClass.sse; | ... | @@ -44,6 +46,8 @@ const sse = abi.RegisterClass.sse; |
| 44 | 46 | ||
| 45 | const InnerError = CodeGenError || error{OutOfRegisters}; | 47 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 46 | 48 | ||
| 49 | const debug_wip_mir = false; | ||
| 50 | |||
| 47 | gpa: Allocator, | 51 | gpa: Allocator, |
| 48 | air: Air, | 52 | air: Air, |
| 49 | liveness: Liveness, | 53 | liveness: Liveness, |
| ... | @@ -103,8 +107,12 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init, | ... | @@ -103,8 +107,12 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init, |
| 103 | /// For mir debug info, maps a mir index to a air index | 107 | /// For mir debug info, maps a mir index to a air index |
| 104 | mir_to_air_map: if (builtin.mode == .Debug) std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index) else void, | 108 | mir_to_air_map: if (builtin.mode == .Debug) std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index) else void, |
| 105 | 109 | ||
| 110 | debug_wip_mir_inst: @TypeOf(debug_wip_mir_inst_init) = debug_wip_mir_inst_init, | ||
| 111 | |||
| 106 | const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; | 112 | const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; |
| 107 | 113 | ||
| 114 | const debug_wip_mir_inst_init = if (debug_wip_mir) @as(Mir.Inst.Index, 0) else {}; | ||
| 115 | |||
| 108 | pub const MCValue = union(enum) { | 116 | pub const MCValue = union(enum) { |
| 109 | /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc. | 117 | /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc. |
| 110 | /// TODO Look into deleting this tag and using `dead` instead, since every use | 118 | /// TODO Look into deleting this tag and using `dead` instead, since every use |
| ... | @@ -267,6 +275,12 @@ pub fn generate( | ... | @@ -267,6 +275,12 @@ pub fn generate( |
| 267 | assert(fn_owner_decl.has_tv); | 275 | assert(fn_owner_decl.has_tv); |
| 268 | const fn_type = fn_owner_decl.ty; | 276 | const fn_type = fn_owner_decl.ty; |
| 269 | 277 | ||
| 278 | if (debug_wip_mir) { | ||
| 279 | const stderr = std.io.getStdErr().writer(); | ||
| 280 | fn_owner_decl.renderFullyQualifiedName(mod, stderr) catch {}; | ||
| 281 | stderr.writeAll(":\n") catch {}; | ||
| 282 | } | ||
| 283 | |||
| 270 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); | 284 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 271 | try branch_stack.ensureUnusedCapacity(2); | 285 | try branch_stack.ensureUnusedCapacity(2); |
| 272 | // The outermost branch is used for constants only. | 286 | // The outermost branch is used for constants only. |
| ... | @@ -683,6 +697,56 @@ fn asmMemoryRegisterImmediate( | ... | @@ -683,6 +697,56 @@ fn asmMemoryRegisterImmediate( |
| 683 | }); | 697 | }); |
| 684 | } | 698 | } |
| 685 | 699 | ||
| 700 | fn printWipMir(self: *Self, stream: anytype, air_inst: ?Air.Inst.Index) !void { | ||
| 701 | const mod = self.bin_file.options.module.?; | ||
| 702 | if (!debug_wip_mir) return; | ||
| 703 | |||
| 704 | var lower = Lower{ | ||
| 705 | .allocator = self.gpa, | ||
| 706 | .mir = .{ | ||
| 707 | .instructions = self.mir_instructions.slice(), | ||
| 708 | .extra = self.mir_extra.items, | ||
| 709 | }, | ||
| 710 | .target = self.target, | ||
| 711 | .src_loc = self.src_loc, | ||
| 712 | }; | ||
| 713 | var mir_inst = self.debug_wip_mir_inst; | ||
| 714 | var mir_end = @intCast(Mir.Inst.Index, self.mir_instructions.len); | ||
| 715 | defer self.debug_wip_mir_inst = mir_end; | ||
| 716 | while (mir_inst < mir_end) : (mir_inst += 1) { | ||
| 717 | for (lower.lowerMir(lower.mir.instructions.get(mir_inst)) catch |err| switch (err) { | ||
| 718 | error.LowerFail => { | ||
| 719 | defer { | ||
| 720 | lower.err_msg.?.deinit(self.gpa); | ||
| 721 | lower.err_msg = null; | ||
| 722 | } | ||
| 723 | try stream.print("{s}\n", .{lower.err_msg.?.msg}); | ||
| 724 | continue; | ||
| 725 | }, | ||
| 726 | error.InvalidInstruction, error.CannotEncode => |e| { | ||
| 727 | try stream.writeAll(switch (e) { | ||
| 728 | error.InvalidInstruction => "CodeGen failed to find a viable instruction.\n", | ||
| 729 | error.CannotEncode => "CodeGen failed to encode the instruction.\n", | ||
| 730 | }); | ||
| 731 | continue; | ||
| 732 | }, | ||
| 733 | else => |e| return e, | ||
| 734 | }) |lower_inst| { | ||
| 735 | try stream.writeAll(" | "); | ||
| 736 | try lower_inst.fmtPrint(stream); | ||
| 737 | try stream.writeByte('\n'); | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | if (air_inst) |inst| { | ||
| 742 | print_air.writeInst(stream, inst, mod, self.air, self.liveness); | ||
| 743 | } | ||
| 744 | } | ||
| 745 | |||
| 746 | fn dumpWipMir(self: *Self, air_inst: ?Air.Inst.Index) void { | ||
| 747 | self.printWipMir(std.io.getStdErr().writer(), air_inst) catch return; | ||
| 748 | } | ||
| 749 | |||
| 686 | fn gen(self: *Self) InnerError!void { | 750 | fn gen(self: *Self) InnerError!void { |
| 687 | const cc = self.fn_type.fnCallingConvention(); | 751 | const cc = self.fn_type.fnCallingConvention(); |
| 688 | if (cc != .Naked) { | 752 | if (cc != .Naked) { |
| ... | @@ -836,6 +900,8 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -836,6 +900,8 @@ fn gen(self: *Self) InnerError!void { |
| 836 | .ops = undefined, | 900 | .ops = undefined, |
| 837 | .data = .{ .payload = payload }, | 901 | .data = .{ .payload = payload }, |
| 838 | }); | 902 | }); |
| 903 | |||
| 904 | self.dumpWipMir(null); | ||
| 839 | } | 905 | } |
| 840 | 906 | ||
| 841 | fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | 907 | fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| ... | @@ -845,8 +911,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -845,8 +911,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 845 | const old_air_bookkeeping = self.air_bookkeeping; | 911 | const old_air_bookkeeping = self.air_bookkeeping; |
| 846 | try self.ensureProcessDeathCapacity(Liveness.bpi); | 912 | try self.ensureProcessDeathCapacity(Liveness.bpi); |
| 847 | if (builtin.mode == .Debug) { | 913 | if (builtin.mode == .Debug) { |
| 848 | try self.mir_to_air_map.put(@intCast(u32, self.mir_instructions.len), inst); | 914 | try self.mir_to_air_map.put(@intCast(Mir.Inst.Index, self.mir_instructions.len), inst); |
| 849 | } | 915 | } |
| 916 | self.dumpWipMir(inst); | ||
| 850 | 917 | ||
| 851 | switch (air_tags[inst]) { | 918 | switch (air_tags[inst]) { |
| 852 | // zig fmt: off | 919 | // zig fmt: off |
src/arch/x86_64/encoder.zig+22-23| ... | @@ -54,18 +54,17 @@ pub const Instruction = struct { | ... | @@ -54,18 +54,17 @@ pub const Instruction = struct { |
| 54 | }; | 54 | }; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | pub fn fmtPrint(op: Operand, enc_op: Encoding.Op, writer: anytype) !void { | 57 | pub fn fmtPrint(op: Operand, enc_op: Encoding.Op, writer: anytype) @TypeOf(writer).Error!void { |
| 58 | switch (op) { | 58 | switch (op) { |
| 59 | .none => {}, | 59 | .none => {}, |
| 60 | .reg => |reg| try writer.writeAll(@tagName(reg)), | 60 | .reg => |reg| try writer.writeAll(@tagName(reg)), |
| 61 | .mem => |mem| switch (mem) { | 61 | .mem => |mem| switch (mem) { |
| 62 | .rip => |rip| { | 62 | .rip => |rip| { |
| 63 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); | 63 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); |
| 64 | if (rip.disp != 0) { | 64 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ |
| 65 | const sign_bit = if (sign(rip.disp) < 0) "-" else "+"; | 65 | @as(u8, if (rip.disp < 0) '-' else '+'), |
| 66 | const disp_abs = try std.math.absInt(rip.disp); | 66 | std.math.absCast(rip.disp), |
| 67 | try writer.print(" {s} 0x{x}", .{ sign_bit, disp_abs }); | 67 | }); |
| 68 | } | ||
| 69 | try writer.writeByte(']'); | 68 | try writer.writeByte(']'); |
| 70 | }, | 69 | }, |
| 71 | .sib => |sib| { | 70 | .sib => |sib| { |
| ... | @@ -77,27 +76,31 @@ pub const Instruction = struct { | ... | @@ -77,27 +76,31 @@ pub const Instruction = struct { |
| 77 | 76 | ||
| 78 | try writer.writeByte('['); | 77 | try writer.writeByte('['); |
| 79 | 78 | ||
| 79 | var any = false; | ||
| 80 | if (sib.base) |base| { | 80 | if (sib.base) |base| { |
| 81 | try writer.print("{s}", .{@tagName(base)}); | 81 | try writer.print("{s}", .{@tagName(base)}); |
| 82 | any = true; | ||
| 82 | } | 83 | } |
| 83 | if (sib.scale_index) |si| { | 84 | if (sib.scale_index) |si| { |
| 84 | if (sib.base != null) { | 85 | if (any) try writer.writeAll(" + "); |
| 85 | try writer.writeAll(" + "); | ||
| 86 | } | ||
| 87 | try writer.print("{s} * {d}", .{ @tagName(si.index), si.scale }); | 86 | try writer.print("{s} * {d}", .{ @tagName(si.index), si.scale }); |
| 87 | any = true; | ||
| 88 | } | 88 | } |
| 89 | if (sib.disp != 0) { | 89 | if (sib.disp != 0 or !any) { |
| 90 | if (sib.base != null or sib.scale_index != null) { | 90 | if (any) |
| 91 | try writer.writeByte(' '); | 91 | try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) |
| 92 | } | 92 | else if (sib.disp < 0) |
| 93 | try writer.writeByte(if (sign(sib.disp) < 0) '-' else '+'); | 93 | try writer.writeByte('-'); |
| 94 | const disp_abs = try std.math.absInt(sib.disp); | 94 | try writer.print("0x{x}", .{std.math.absCast(sib.disp)}); |
| 95 | try writer.print(" 0x{x}", .{disp_abs}); | 95 | any = true; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | try writer.writeByte(']'); | 98 | try writer.writeByte(']'); |
| 99 | }, | 99 | }, |
| 100 | .moffs => |moffs| try writer.print("{s}:0x{x}", .{ @tagName(moffs.seg), moffs.offset }), | 100 | .moffs => |moffs| try writer.print("{s}:0x{x}", .{ |
| 101 | @tagName(moffs.seg), | ||
| 102 | moffs.offset, | ||
| 103 | }), | ||
| 101 | }, | 104 | }, |
| 102 | .imm => |imm| try writer.print("0x{x}", .{imm.asUnsigned(enc_op.bitSize())}), | 105 | .imm => |imm| try writer.print("0x{x}", .{imm.asUnsigned(enc_op.bitSize())}), |
| 103 | } | 106 | } |
| ... | @@ -127,10 +130,10 @@ pub const Instruction = struct { | ... | @@ -127,10 +130,10 @@ pub const Instruction = struct { |
| 127 | return inst; | 130 | return inst; |
| 128 | } | 131 | } |
| 129 | 132 | ||
| 130 | pub fn fmtPrint(inst: Instruction, writer: anytype) !void { | 133 | pub fn fmtPrint(inst: Instruction, writer: anytype) @TypeOf(writer).Error!void { |
| 131 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); | 134 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); |
| 132 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); | 135 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); |
| 133 | for (inst.ops, inst.encodings.ops, 0..) |op, enc, i| { | 136 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { |
| 134 | if (op == .none) break; | 137 | if (op == .none) break; |
| 135 | if (i > 0) try writer.writeByte(','); | 138 | if (i > 0) try writer.writeByte(','); |
| 136 | try writer.writeByte(' '); | 139 | try writer.writeByte(' '); |
| ... | @@ -390,10 +393,6 @@ pub const Instruction = struct { | ... | @@ -390,10 +393,6 @@ pub const Instruction = struct { |
| 390 | } | 393 | } |
| 391 | }; | 394 | }; |
| 392 | 395 | ||
| 393 | inline fn sign(i: anytype) @TypeOf(i) { | ||
| 394 | return @as(@TypeOf(i), @boolToInt(i > 0)) - @boolToInt(i < 0); | ||
| 395 | } | ||
| 396 | |||
| 397 | pub const LegacyPrefixes = packed struct { | 396 | pub const LegacyPrefixes = packed struct { |
| 398 | /// LOCK | 397 | /// LOCK |
| 399 | prefix_f0: bool = false, | 398 | prefix_f0: bool = false, |
src/print_air.zig+48-33| ... | @@ -8,7 +8,7 @@ const Type = @import("type.zig").Type; | ... | @@ -8,7 +8,7 @@ const Type = @import("type.zig").Type; |
| 8 | const Air = @import("Air.zig"); | 8 | const Air = @import("Air.zig"); |
| 9 | const Liveness = @import("Liveness.zig"); | 9 | const Liveness = @import("Liveness.zig"); |
| 10 | 10 | ||
| 11 | pub fn dump(module: *Module, air: Air, liveness: Liveness) void { | 11 | pub fn write(stream: anytype, module: *Module, air: Air, liveness: Liveness) void { |
| 12 | const instruction_bytes = air.instructions.len * | 12 | const instruction_bytes = air.instructions.len * |
| 13 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | 13 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include |
| 14 | // the debug safety tag but we want to measure release size. | 14 | // the debug safety tag but we want to measure release size. |
| ... | @@ -23,7 +23,7 @@ pub fn dump(module: *Module, air: Air, liveness: Liveness) void { | ... | @@ -23,7 +23,7 @@ pub fn dump(module: *Module, air: Air, liveness: Liveness) void { |
| 23 | liveness_special_bytes + tomb_bytes; | 23 | liveness_special_bytes + tomb_bytes; |
| 24 | 24 | ||
| 25 | // zig fmt: off | 25 | // zig fmt: off |
| 26 | std.debug.print( | 26 | stream.print( |
| 27 | \\# Total AIR+Liveness bytes: {} | 27 | \\# Total AIR+Liveness bytes: {} |
| 28 | \\# AIR Instructions: {d} ({}) | 28 | \\# AIR Instructions: {d} ({}) |
| 29 | \\# AIR Extra Data: {d} ({}) | 29 | \\# AIR Extra Data: {d} ({}) |
| ... | @@ -40,65 +40,78 @@ pub fn dump(module: *Module, air: Air, liveness: Liveness) void { | ... | @@ -40,65 +40,78 @@ pub fn dump(module: *Module, air: Air, liveness: Liveness) void { |
| 40 | fmtIntSizeBin(tomb_bytes), | 40 | fmtIntSizeBin(tomb_bytes), |
| 41 | liveness.extra.len, fmtIntSizeBin(liveness_extra_bytes), | 41 | liveness.extra.len, fmtIntSizeBin(liveness_extra_bytes), |
| 42 | liveness.special.count(), fmtIntSizeBin(liveness_special_bytes), | 42 | liveness.special.count(), fmtIntSizeBin(liveness_special_bytes), |
| 43 | }); | 43 | }) catch return; |
| 44 | // zig fmt: on | 44 | // zig fmt: on |
| 45 | var arena = std.heap.ArenaAllocator.init(module.gpa); | ||
| 46 | defer arena.deinit(); | ||
| 47 | 45 | ||
| 48 | var writer: Writer = .{ | 46 | var writer: Writer = .{ |
| 49 | .module = module, | 47 | .module = module, |
| 50 | .gpa = module.gpa, | 48 | .gpa = module.gpa, |
| 51 | .arena = arena.allocator(), | ||
| 52 | .air = air, | 49 | .air = air, |
| 53 | .liveness = liveness, | 50 | .liveness = liveness, |
| 54 | .indent = 2, | 51 | .indent = 2, |
| 52 | .skip_body = false, | ||
| 55 | }; | 53 | }; |
| 56 | const stream = std.io.getStdErr().writer(); | ||
| 57 | writer.writeAllConstants(stream) catch return; | 54 | writer.writeAllConstants(stream) catch return; |
| 58 | stream.writeByte('\n') catch return; | 55 | stream.writeByte('\n') catch return; |
| 59 | writer.writeBody(stream, air.getMainBody()) catch return; | 56 | writer.writeBody(stream, air.getMainBody()) catch return; |
| 60 | } | 57 | } |
| 61 | 58 | ||
| 59 | pub fn writeInst( | ||
| 60 | stream: anytype, | ||
| 61 | inst: Air.Inst.Index, | ||
| 62 | module: *Module, | ||
| 63 | air: Air, | ||
| 64 | liveness: Liveness, | ||
| 65 | ) void { | ||
| 66 | var writer: Writer = .{ | ||
| 67 | .module = module, | ||
| 68 | .gpa = module.gpa, | ||
| 69 | .air = air, | ||
| 70 | .liveness = liveness, | ||
| 71 | .indent = 2, | ||
| 72 | .skip_body = true, | ||
| 73 | }; | ||
| 74 | writer.writeInst(stream, inst) catch return; | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn dump(module: *Module, air: Air, liveness: Liveness) void { | ||
| 78 | write(std.io.getStdErr().writer(), module, air, liveness); | ||
| 79 | } | ||
| 80 | |||
| 81 | pub fn dumpInst(inst: Air.Inst.Index, module: *Module, air: Air, liveness: Liveness) void { | ||
| 82 | writeInst(std.io.getStdErr().writer(), inst, module, air, liveness); | ||
| 83 | } | ||
| 84 | |||
| 62 | const Writer = struct { | 85 | const Writer = struct { |
| 63 | module: *Module, | 86 | module: *Module, |
| 64 | gpa: Allocator, | 87 | gpa: Allocator, |
| 65 | arena: Allocator, | ||
| 66 | air: Air, | 88 | air: Air, |
| 67 | liveness: Liveness, | 89 | liveness: Liveness, |
| 68 | indent: usize, | 90 | indent: usize, |
| 91 | skip_body: bool, | ||
| 69 | 92 | ||
| 70 | fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void { | 93 | fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void { |
| 71 | for (w.air.instructions.items(.tag), 0..) |tag, i| { | 94 | for (w.air.instructions.items(.tag), 0..) |tag, i| { |
| 72 | const inst = @intCast(u32, i); | 95 | const inst = @intCast(Air.Inst.Index, i); |
| 73 | switch (tag) { | 96 | switch (tag) { |
| 74 | .constant, .const_ty => { | 97 | .constant, .const_ty => try w.writeInst(s, inst), |
| 75 | try s.writeByteNTimes(' ', w.indent); | ||
| 76 | try s.print("%{d} ", .{inst}); | ||
| 77 | try w.writeInst(s, inst); | ||
| 78 | try s.writeAll(")\n"); | ||
| 79 | }, | ||
| 80 | else => continue, | 98 | else => continue, |
| 81 | } | 99 | } |
| 82 | } | 100 | } |
| 83 | } | 101 | } |
| 84 | 102 | ||
| 85 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { | 103 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { |
| 86 | for (body) |inst| { | 104 | for (body) |inst| try w.writeInst(s, inst); |
| 87 | try s.writeByteNTimes(' ', w.indent); | ||
| 88 | if (w.liveness.isUnused(inst)) { | ||
| 89 | try s.print("%{d}!", .{inst}); | ||
| 90 | } else { | ||
| 91 | try s.print("%{d} ", .{inst}); | ||
| 92 | } | ||
| 93 | try w.writeInst(s, inst); | ||
| 94 | try s.writeAll(")\n"); | ||
| 95 | } | ||
| 96 | } | 105 | } |
| 97 | 106 | ||
| 98 | fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 107 | fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 99 | const tags = w.air.instructions.items(.tag); | 108 | const tag = w.air.instructions.items(.tag)[inst]; |
| 100 | const tag = tags[inst]; | 109 | try s.writeByteNTimes(' ', w.indent); |
| 101 | try s.print("= {s}(", .{@tagName(tags[inst])}); | 110 | try s.print("%{d}{c}= {s}(", .{ |
| 111 | inst, | ||
| 112 | @as(u8, if (w.liveness.isUnused(inst)) '!' else ' '), | ||
| 113 | @tagName(tag), | ||
| 114 | }); | ||
| 102 | switch (tag) { | 115 | switch (tag) { |
| 103 | .add, | 116 | .add, |
| 104 | .addwrap, | 117 | .addwrap, |
| ... | @@ -316,6 +329,7 @@ const Writer = struct { | ... | @@ -316,6 +329,7 @@ const Writer = struct { |
| 316 | 329 | ||
| 317 | .dbg_block_begin, .dbg_block_end => {}, | 330 | .dbg_block_begin, .dbg_block_end => {}, |
| 318 | } | 331 | } |
| 332 | try s.writeAll(")\n"); | ||
| 319 | } | 333 | } |
| 320 | 334 | ||
| 321 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 335 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -372,6 +386,7 @@ const Writer = struct { | ... | @@ -372,6 +386,7 @@ const Writer = struct { |
| 372 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; | 386 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 373 | 387 | ||
| 374 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); | 388 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); |
| 389 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 375 | try s.writeAll(", {\n"); | 390 | try s.writeAll(", {\n"); |
| 376 | const old_indent = w.indent; | 391 | const old_indent = w.indent; |
| 377 | w.indent += 2; | 392 | w.indent += 2; |
| ... | @@ -703,6 +718,7 @@ const Writer = struct { | ... | @@ -703,6 +718,7 @@ const Writer = struct { |
| 703 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; | 718 | const body = w.air.extra[extra.end..][0..extra.data.body_len]; |
| 704 | 719 | ||
| 705 | try w.writeOperand(s, inst, 0, pl_op.operand); | 720 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 721 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 706 | try s.writeAll(", {\n"); | 722 | try s.writeAll(", {\n"); |
| 707 | const old_indent = w.indent; | 723 | const old_indent = w.indent; |
| 708 | w.indent += 2; | 724 | w.indent += 2; |
| ... | @@ -721,6 +737,7 @@ const Writer = struct { | ... | @@ -721,6 +737,7 @@ const Writer = struct { |
| 721 | 737 | ||
| 722 | try s.writeAll(", "); | 738 | try s.writeAll(", "); |
| 723 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); | 739 | try w.writeType(s, w.air.getRefType(ty_pl.ty)); |
| 740 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 724 | try s.writeAll(", {\n"); | 741 | try s.writeAll(", {\n"); |
| 725 | const old_indent = w.indent; | 742 | const old_indent = w.indent; |
| 726 | w.indent += 2; | 743 | w.indent += 2; |
| ... | @@ -738,6 +755,7 @@ const Writer = struct { | ... | @@ -738,6 +755,7 @@ const Writer = struct { |
| 738 | const liveness_condbr = w.liveness.getCondBr(inst); | 755 | const liveness_condbr = w.liveness.getCondBr(inst); |
| 739 | 756 | ||
| 740 | try w.writeOperand(s, inst, 0, pl_op.operand); | 757 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 758 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 741 | try s.writeAll(", {\n"); | 759 | try s.writeAll(", {\n"); |
| 742 | const old_indent = w.indent; | 760 | const old_indent = w.indent; |
| 743 | w.indent += 2; | 761 | w.indent += 2; |
| ... | @@ -900,10 +918,7 @@ const Writer = struct { | ... | @@ -900,10 +918,7 @@ const Writer = struct { |
| 900 | dies: bool, | 918 | dies: bool, |
| 901 | ) @TypeOf(s).Error!void { | 919 | ) @TypeOf(s).Error!void { |
| 902 | _ = w; | 920 | _ = w; |
| 903 | if (dies) { | 921 | try s.print("%{d}", .{inst}); |
| 904 | try s.print("%{d}!", .{inst}); | 922 | if (dies) try s.writeByte('!'); |
| 905 | } else { | ||
| 906 | try s.print("%{d}", .{inst}); | ||
| 907 | } | ||
| 908 | } | 923 | } |
| 909 | }; | 924 | }; |