diff options
| author | Jacob G-W <jacoblevgw@gmail.com> | 2021-08-29 15:11:01 -0400 |
|---|---|---|
| committer | Jacob G-W <jacoblevgw@gmail.com> | 2021-09-18 19:43:26 -0400 |
| commit | f388b575533b8e36999bc5ee406421feb7e80baa (patch) | |
| tree | b7739cce97e147a4fb6d8ed0de6ff18805e06bfd /src | |
| parent | f0b1eec8095e442218ff9171e284393102596dc4 (diff) | |
| download | zig-f388b575533b8e36999bc5ee406421feb7e80baa.tar.gz zig-f388b575533b8e36999bc5ee406421feb7e80baa.zip | |
plan9: emit line debug info in codegen
Diffstat (limited to 'src')
| -rw-r--r-- | src/Module.zig | 4 | ||||
| -rw-r--r-- | src/codegen.zig | 42 | ||||
| -rw-r--r-- | src/link/Plan9.zig | 24 | ||||
| -rw-r--r-- | src/link/Plan9/aout.zig | 9 |
4 files changed, 74 insertions, 5 deletions
diff --git a/src/Module.zig b/src/Module.zig index 473c27e338..ff9560e2de 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3674,7 +3674,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl }); }, .plan9 => { - // TODO implement for plan9 + // TODO Look into detecting when this would be unnecessary by storing enough state + // in `Decl` to notice that the line number did not change. + mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl }); }, .c, .wasm, .spirv => {}, } diff --git a/src/codegen.zig b/src/codegen.zig index 08ee358bff..7dc605ba73 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -48,6 +48,21 @@ pub const DebugInfoOutput = union(enum) { dbg_info: *std.ArrayList(u8), dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable, }, + /// the plan9 debuginfo output is a bytecode with 4 opcodes + /// assume all numbers/variables are bytes + /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset + /// x when x < 65 -> add x to line offset + /// x when x < 129 -> subtract 64 from x and add it to the line offset + /// x -> subtract 129 from x, multiply it by the quanta of the instruction size + /// (1 on x86_64), and add it to the pc + /// after every opcode, add the quanta of the instruction size to the pc + plan9: struct { + /// the actual opcodes + dbg_line: *std.ArrayList(u8), + /// what the line count ends on after codegen + /// 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 + end_line: *u32, + }, none, }; @@ -913,6 +928,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); }, + .plan9 => {}, .none => {}, } } @@ -923,15 +939,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); }, + .plan9 => {}, .none => {}, } } fn dbgAdvancePCAndLine(self: *Self, line: u32, column: u32) InnerError!void { + const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); + const delta_pc = self.code.items.len - self.prev_di_pc; switch (self.debug_output) { .dwarf => |dbg_out| { - const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line); - const delta_pc = self.code.items.len - self.prev_di_pc; // TODO Look into using the DWARF special opcodes to compress this data. // It lets you emit single-byte opcodes that add different numbers to // both the PC and the line number at the same time. @@ -944,6 +961,24 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { } dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); }, + .plan9 => |dbg_out| { + // we have already checked the target in the linker to make sure it is compatable + const quant = @import("link/Plan9/aout.zig").getPCQuant(self.target.cpu.arch) catch unreachable; + + // increasing the line number + if (delta_line > 0 and delta_line < 65) { + try dbg_out.dbg_line.append(@intCast(u8, delta_line)); + } else if (delta_line < 0 and delta_line > -65) { + try dbg_out.dbg_line.append(@intCast(u8, -delta_line + 64)); + } else if (delta_line != 0) { + try dbg_out.dbg_line.writer().writeIntBig(i32, delta_line); + } + // increasing the pc + if (delta_pc - quant != 0) { + try dbg_out.dbg_line.append(@intCast(u8, delta_pc - quant + 129)); + } + dbg_out.end_line.* = line; + }, .none => {}, } self.prev_di_line = line; @@ -1032,6 +1067,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { } try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index)); }, + .plan9 => {}, .none => {}, } } @@ -2457,6 +2493,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string }, + .plan9 => {}, .none => {}, } }, @@ -2491,6 +2528,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { else => {}, } }, + .plan9 => {}, .none => {}, } }, diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index bf49a238b6..cf6b05739d 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -34,6 +34,8 @@ data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, hdr: aout.ExecHdr = undefined, +magic: u32, + entry_val: ?u64 = null, got_len: usize = 0, @@ -113,6 +115,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { }, .sixtyfour_bit = sixtyfour_bit, .bases = undefined, + .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), }; return self; } @@ -127,7 +130,24 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); - const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ .none = .{} }); + var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator); + defer dbg_line_buffer.deinit(); + var end_line: u32 = 0; + + const res = try codegen.generateFunction( + &self.base, + decl.srcLoc(), + func, + air, + liveness, + &code_buffer, + .{ + .plan9 = .{ + .dbg_line = &dbg_line_buffer, + .end_line = &end_line, + }, + }, + ); const code = switch (res) { .appended => code_buffer.toOwnedSlice(), .fail => |em| { @@ -313,7 +333,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { iovecs_i += 1; // generate the header self.hdr = .{ - .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), + .magic = self.magic, .text = @intCast(u32, text_i), .data = @intCast(u32, data_i), .syms = @intCast(u32, sym_buf.items.len), diff --git a/src/link/Plan9/aout.zig b/src/link/Plan9/aout.zig index f6dff7437c..b4fafbc31d 100644 --- a/src/link/Plan9/aout.zig +++ b/src/link/Plan9/aout.zig @@ -112,3 +112,12 @@ pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 { else => error.ArchNotSupportedByPlan9, }; } + +/// gets the quantization of pc for the arch +pub fn getPCQuant(arch: std.Target.Cpu.Arch) !u8 { + return switch (arch) { + .i386, .x86_64 => 1, + .powerpc, .powerpc64, .mips, .sparc, .arm, .aarch64 => 4, + else => error.ArchNotSupportedByPlan9, + }; +} |
