plan9: refactor debug info

The main goal is to stop depending on `emit.lower.target`.
This commit is contained in:
Jacob Young 2023-10-04 19:22:52 -04:00
parent 5a35734a48
commit b4427bc300
6 changed files with 79 additions and 86 deletions

View File

@ -445,25 +445,23 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
},
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// 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
try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);
// increasing the pc
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - quant;
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
if (d_pc_p9 > 0) {
// minus one because if its the last one, we want to leave space to change the line which is one quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, quant) + 128)) - quant);
if (dbg_out.pcop_change_index.*) |pci|
// minus one because if its the last one, we want to leave space to change the line which is one pc quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
if (dbg_out.pcop_change_index) |pci|
dbg_out.dbg_line.items[pci] += 1;
dbg_out.pcop_change_index.* = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
} else if (d_pc_p9 == 0) {
// we don't need to do anything, because adding the quant does it for us
// we don't need to do anything, because adding the pc quanta does it for us
} else unreachable;
if (dbg_out.start_line.* == null)
dbg_out.start_line.* = self.prev_di_line;
dbg_out.end_line.* = line;
if (dbg_out.start_line == null)
dbg_out.start_line = self.prev_di_line;
dbg_out.end_line = line;
// only do this if the pc changed
self.prev_di_line = line;
self.prev_di_column = column;

View File

@ -362,25 +362,23 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
},
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// 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
try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);
// increasing the pc
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - quant;
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
if (d_pc_p9 > 0) {
// minus one because if its the last one, we want to leave space to change the line which is one quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, quant) + 128)) - quant);
if (dbg_out.pcop_change_index.*) |pci|
// minus one because if its the last one, we want to leave space to change the line which is one pc quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
if (dbg_out.pcop_change_index) |pci|
dbg_out.dbg_line.items[pci] += 1;
dbg_out.pcop_change_index.* = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
} else if (d_pc_p9 == 0) {
// we don't need to do anything, because adding the quant does it for us
// we don't need to do anything, because adding the pc quanta does it for us
} else unreachable;
if (dbg_out.start_line.* == null)
dbg_out.start_line.* = self.prev_di_line;
dbg_out.end_line.* = line;
if (dbg_out.start_line == null)
dbg_out.start_line = self.prev_di_line;
dbg_out.end_line = line;
// only do this if the pc changed
self.prev_di_line = line;
self.prev_di_column = column;

View File

@ -96,25 +96,23 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
},
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// 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
try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);
// increasing the pc
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - quant;
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
if (d_pc_p9 > 0) {
// minus one because if its the last one, we want to leave space to change the line which is one quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, quant) + 128)) - quant);
if (dbg_out.pcop_change_index.*) |pci|
// minus one because if its the last one, we want to leave space to change the line which is one pc quanta
try dbg_out.dbg_line.append(@as(u8, @intCast(@divExact(d_pc_p9, dbg_out.pc_quanta) + 128)) - dbg_out.pc_quanta);
if (dbg_out.pcop_change_index) |pci|
dbg_out.dbg_line.items[pci] += 1;
dbg_out.pcop_change_index.* = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
} else if (d_pc_p9 == 0) {
// we don't need to do anything, because adding the quant does it for us
// we don't need to do anything, because adding the pc quanta does it for us
} else unreachable;
if (dbg_out.start_line.* == null)
dbg_out.start_line.* = self.prev_di_line;
dbg_out.end_line.* = line;
if (dbg_out.start_line == null)
dbg_out.start_line = self.prev_di_line;
dbg_out.end_line = line;
// only do this if the pc changed
self.prev_di_line = line;
self.prev_di_column = column;

View File

@ -242,16 +242,14 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
},
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// we have already checked the target in the linker to make sure it is compatable
const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.lower.target.cpu.arch) catch unreachable;
// increasing the line number
try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);
// increasing the pc
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - quant;
const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
if (d_pc_p9 > 0) {
// minus one because if its the last one, we want to leave space to change the line which is one quanta
var diff = @divExact(d_pc_p9, quant) - quant;
// minus one because if its the last one, we want to leave space to change the line which is one pc quanta
var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;
while (diff > 0) {
if (diff < 64) {
try dbg_out.dbg_line.append(@as(u8, @intCast(diff + 128)));
@ -261,15 +259,15 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
diff -= 64;
}
}
if (dbg_out.pcop_change_index.*) |pci|
if (dbg_out.pcop_change_index) |pci|
dbg_out.dbg_line.items[pci] += 1;
dbg_out.pcop_change_index.* = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));
} else if (d_pc_p9 == 0) {
// we don't need to do anything, because adding the quant does it for us
// we don't need to do anything, because adding the pc quanta does it for us
} else unreachable;
if (dbg_out.start_line.* == null)
dbg_out.start_line.* = emit.prev_di_line;
dbg_out.end_line.* = line;
if (dbg_out.start_line == null)
dbg_out.start_line = emit.prev_di_line;
dbg_out.end_line = line;
// only do this if the pc changed
emit.prev_di_line = line;
emit.prev_di_column = column;

View File

@ -40,28 +40,7 @@ pub const CodeGenError = error{
pub const DebugInfoOutput = union(enum) {
dwarf: *link.File.Dwarf.DeclState,
/// 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 subtract it from 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 line the debuginfo starts on
/// 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
start_line: *?u32,
/// 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,
/// the last pc change op
/// This is very useful for adding quanta
/// to it if its not actually the last one.
pcop_change_index: *?u32,
},
plan9: *link.File.Plan9.DebugInfoOutput,
none,
};

View File

@ -211,6 +211,31 @@ pub const Atom = struct {
}
};
/// 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 subtract it from 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
pub const DebugInfoOutput = struct {
/// the actual opcodes
dbg_line: std.ArrayList(u8),
/// what line the debuginfo starts on
/// 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
start_line: ?u32,
/// 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,
/// the last pc change op
/// This is very useful for adding quanta
/// to it if its not actually the last one.
pcop_change_index: ?u32,
/// cached pc quanta
pc_quanta: u8,
};
const DeclMetadata = struct {
index: Atom.Index,
exports: std.ArrayListUnmanaged(usize) = .{},
@ -376,11 +401,15 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator);
defer dbg_line_buffer.deinit();
var start_line: ?u32 = null;
var end_line: u32 = undefined;
var pcop_change_index: ?u32 = null;
var dbg_info_output: DebugInfoOutput = .{
.dbg_line = std.ArrayList(u8).init(self.base.allocator),
.start_line = null,
.end_line = undefined,
.pcop_change_index = null,
// we have already checked the target in the linker to make sure it is compatable
.pc_quanta = aout.getPCQuant(self.base.options.target.cpu.arch) catch unreachable,
};
defer dbg_info_output.dbg_line.deinit();
const res = try codegen.generateFunction(
&self.base,
@ -389,14 +418,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
air,
liveness,
&code_buffer,
.{
.plan9 = .{
.dbg_line = &dbg_line_buffer,
.end_line = &end_line,
.start_line = &start_line,
.pcop_change_index = &pcop_change_index,
},
},
.{ .plan9 = &dbg_info_output },
);
const code = switch (res) {
.ok => try code_buffer.toOwnedSlice(),
@ -412,9 +434,9 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
};
const out: FnDeclOutput = .{
.code = code,
.lineinfo = try dbg_line_buffer.toOwnedSlice(),
.start_line = start_line.?,
.end_line = end_line,
.lineinfo = try dbg_info_output.dbg_line.toOwnedSlice(),
.start_line = dbg_info_output.start_line.?,
.end_line = dbg_info_output.end_line,
};
try self.putFn(decl_index, out);
return self.updateFinish(decl_index);