authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-08-29 15:11:01-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-09-18 19:43:26-04:00
logf388b575533b8e36999bc5ee406421feb7e80baa
treeb7739cce97e147a4fb6d8ed0de6ff18805e06bfd
parentf0b1eec8095e442218ff9171e284393102596dc4

plan9: emit line debug info in codegen


4 files changed, 74 insertions(+), 5 deletions(-)

src/Module.zig+3-1
......@@ -3674,7 +3674,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
36743674 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
36753675 },
36763676 .plan9 => {
3677 // TODO implement for plan9
3677 // TODO Look into detecting when this would be unnecessary by storing enough state
3678 // in `Decl` to notice that the line number did not change.
3679 mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
36783680 },
36793681 .c, .wasm, .spirv => {},
36803682 }
src/codegen.zig+40-2
......@@ -48,6 +48,21 @@ pub const DebugInfoOutput = union(enum) {
4848 dbg_info: *std.ArrayList(u8),
4949 dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
5050 },
51 /// the plan9 debuginfo output is a bytecode with 4 opcodes
52 /// assume all numbers/variables are bytes
53 /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
54 /// x when x < 65 -> add x to line offset
55 /// x when x < 129 -> subtract 64 from x and add it to the line offset
56 /// x -> subtract 129 from x, multiply it by the quanta of the instruction size
57 /// (1 on x86_64), and add it to the pc
58 /// after every opcode, add the quanta of the instruction size to the pc
59 plan9: struct {
60 /// the actual opcodes
61 dbg_line: *std.ArrayList(u8),
62 /// what the line count ends on after codegen
63 /// this helps because the linker might have to insert some opcodes to make sure that the line count starts at the right amount for the next decl
64 end_line: *u32,
65 },
5166 none,
5267};
5368
......@@ -913,6 +928,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
913928 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
914929 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
915930 },
931 .plan9 => {},
916932 .none => {},
917933 }
918934 }
......@@ -923,15 +939,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
923939 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
924940 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
925941 },
942 .plan9 => {},
926943 .none => {},
927944 }
928945 }
929946
930947 fn dbgAdvancePCAndLine(self: *Self, line: u32, column: u32) InnerError!void {
948 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
949 const delta_pc = self.code.items.len - self.prev_di_pc;
931950 switch (self.debug_output) {
932951 .dwarf => |dbg_out| {
933 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
934 const delta_pc = self.code.items.len - self.prev_di_pc;
935952 // TODO Look into using the DWARF special opcodes to compress this data.
936953 // It lets you emit single-byte opcodes that add different numbers to
937954 // both the PC and the line number at the same time.
......@@ -944,6 +961,24 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
944961 }
945962 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
946963 },
964 .plan9 => |dbg_out| {
965 // we have already checked the target in the linker to make sure it is compatable
966 const quant = @import("link/Plan9/aout.zig").getPCQuant(self.target.cpu.arch) catch unreachable;
967
968 // increasing the line number
969 if (delta_line > 0 and delta_line < 65) {
970 try dbg_out.dbg_line.append(@intCast(u8, delta_line));
971 } else if (delta_line < 0 and delta_line > -65) {
972 try dbg_out.dbg_line.append(@intCast(u8, -delta_line + 64));
973 } else if (delta_line != 0) {
974 try dbg_out.dbg_line.writer().writeIntBig(i32, delta_line);
975 }
976 // increasing the pc
977 if (delta_pc - quant != 0) {
978 try dbg_out.dbg_line.append(@intCast(u8, delta_pc - quant + 129));
979 }
980 dbg_out.end_line.* = line;
981 },
947982 .none => {},
948983 }
949984 self.prev_di_line = line;
......@@ -1032,6 +1067,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
10321067 }
10331068 try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index));
10341069 },
1070 .plan9 => {},
10351071 .none => {},
10361072 }
10371073 }
......@@ -2457,6 +2493,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
24572493 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
24582494 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
24592495 },
2496 .plan9 => {},
24602497 .none => {},
24612498 }
24622499 },
......@@ -2491,6 +2528,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
24912528 else => {},
24922529 }
24932530 },
2531 .plan9 => {},
24942532 .none => {},
24952533 }
24962534 },
src/link/Plan9.zig+22-2
......@@ -34,6 +34,8 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{},
3434
3535hdr: aout.ExecHdr = undefined,
3636
37magic: u32,
38
3739entry_val: ?u64 = null,
3840
3941got_len: usize = 0,
......@@ -113,6 +115,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 {
113115 },
114116 .sixtyfour_bit = sixtyfour_bit,
115117 .bases = undefined,
118 .magic = try aout.magicFromArch(self.base.options.target.cpu.arch),
116119 };
117120 return self;
118121}
......@@ -127,7 +130,24 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
127130
128131 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
129132 defer code_buffer.deinit();
130 const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ .none = .{} });
133 var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator);
134 defer dbg_line_buffer.deinit();
135 var end_line: u32 = 0;
136
137 const res = try codegen.generateFunction(
138 &self.base,
139 decl.srcLoc(),
140 func,
141 air,
142 liveness,
143 &code_buffer,
144 .{
145 .plan9 = .{
146 .dbg_line = &dbg_line_buffer,
147 .end_line = &end_line,
148 },
149 },
150 );
131151 const code = switch (res) {
132152 .appended => code_buffer.toOwnedSlice(),
133153 .fail => |em| {
......@@ -313,7 +333,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
313333 iovecs_i += 1;
314334 // generate the header
315335 self.hdr = .{
316 .magic = try aout.magicFromArch(self.base.options.target.cpu.arch),
336 .magic = self.magic,
317337 .text = @intCast(u32, text_i),
318338 .data = @intCast(u32, data_i),
319339 .syms = @intCast(u32, sym_buf.items.len),
src/link/Plan9/aout.zig+9
......@@ -112,3 +112,12 @@ pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 {
112112 else => error.ArchNotSupportedByPlan9,
113113 };
114114}
115
116/// gets the quantization of pc for the arch
117pub fn getPCQuant(arch: std.Target.Cpu.Arch) !u8 {
118 return switch (arch) {
119 .i386, .x86_64 => 1,
120 .powerpc, .powerpc64, .mips, .sparc, .arm, .aarch64 => 4,
121 else => error.ArchNotSupportedByPlan9,
122 };
123}