Commit 0bdb367ee4
Changed files (3)
src
arch
aarch64
src/arch/aarch64/CodeGen.zig
@@ -39,7 +39,6 @@ liveness: Liveness,
bin_file: *link.File,
target: *const std.Target,
mod_fn: *const Module.Fn,
-debug_output: DebugInfoOutput,
err_msg: ?*ErrorMsg,
args: []MCValue,
ret_mcv: MCValue,
@@ -53,13 +52,9 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
/// MIR extra data
mir_extra: std.ArrayListUnmanaged(u32) = .{},
-prev_di_line: u32,
-prev_di_column: u32,
/// Byte offset within the source file of the ending curly.
end_di_line: u32,
end_di_column: u32,
-/// Relative to the beginning of `code`.
-prev_di_pc: usize,
/// The value is an offset into the `Function` `code` from the beginning.
/// To perform the reloc, write 32-bit signed little-endian integer
@@ -272,7 +267,6 @@ pub fn generate(
.target = &bin_file.options.target,
.bin_file = bin_file,
.mod_fn = module_fn,
- .debug_output = debug_output,
.err_msg = null,
.args = undefined, // populated after `resolveCallingConventionValues`
.ret_mcv = undefined, // populated after `resolveCallingConventionValues`
@@ -281,9 +275,6 @@ pub fn generate(
.branch_stack = &branch_stack,
.src_loc = src_loc,
.stack_align = undefined,
- .prev_di_pc = 0,
- .prev_di_line = module_fn.lbrace_line,
- .prev_di_column = module_fn.lbrace_column,
.end_di_line = module_fn.rbrace_line,
.end_di_column = module_fn.rbrace_column,
};
@@ -316,8 +307,12 @@ pub fn generate(
var emit = Emit{
.mir = mir,
.bin_file = bin_file,
+ .debug_output = debug_output,
.target = &bin_file.options.target,
.code = code,
+ .prev_di_pc = 0,
+ .prev_di_line = module_fn.lbrace_line,
+ .prev_di_column = module_fn.lbrace_column,
};
try emit.emitMir();
@@ -386,7 +381,10 @@ fn gen(self: *Self) !void {
.data = .{ .nop = {} },
});
- try self.dbgSetPrologueEnd();
+ _ = try self.addInst(.{
+ .tag = .dbg_prologue_end,
+ .data = .{ .nop = {} },
+ });
try self.genBody(self.air.getMainBody());
@@ -402,7 +400,10 @@ fn gen(self: *Self) !void {
return self.failSymbol("TODO AArch64: allow larger stacks", .{});
}
- try self.dbgSetEpilogueBegin();
+ _ = try self.addInst(.{
+ .tag = .dbg_epilogue_begin,
+ .data = .{ .nop = {} },
+ });
// exitlude jumps
if (self.exitlude_jump_relocs.items.len == 1) {
@@ -442,13 +443,27 @@ fn gen(self: *Self) !void {
.data = .{ .reg = .x30 },
});
} else {
- try self.dbgSetPrologueEnd();
+ _ = try self.addInst(.{
+ .tag = .dbg_prologue_end,
+ .data = .{ .nop = {} },
+ });
+
try self.genBody(self.air.getMainBody());
- try self.dbgSetEpilogueBegin();
+
+ _ = try self.addInst(.{
+ .tag = .dbg_epilogue_begin,
+ .data = .{ .nop = {} },
+ });
}
// Drop them off at the rbrace.
- // try self.dbgAdvancePCAndLine(self.end_di_line, self.end_di_column);
+ _ = try self.addInst(.{
+ .tag = .dbg_line,
+ .data = .{ .dbg_line_column = .{
+ .line = self.end_di_line,
+ .column = self.end_di_column,
+ } },
+ });
}
fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
@@ -589,79 +604,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
}
}
-fn dbgSetPrologueEnd(self: *Self) InnerError!void {
- switch (self.debug_output) {
- .dwarf => |dbg_out| {
- try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
- // try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
- },
- .plan9 => {},
- .none => {},
- }
-}
-
-fn dbgSetEpilogueBegin(self: *Self) InnerError!void {
- switch (self.debug_output) {
- .dwarf => |dbg_out| {
- 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: usize = self.code.items.len - self.prev_di_pc;
- switch (self.debug_output) {
- .dwarf => |dbg_out| {
- // 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.
- try dbg_out.dbg_line.ensureUnusedCapacity(11);
- dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
- leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
- if (delta_line != 0) {
- dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
- leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
- }
- dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
- self.prev_di_pc = self.code.items.len;
- self.prev_di_line = line;
- self.prev_di_column = column;
- self.prev_di_pc = self.code.items.len;
- },
- .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);
- // increasing the pc
- const d_pc_p9 = @intCast(i64, delta_pc) - quant;
- 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(@intCast(u8, @divExact(d_pc_p9, quant) + 128) - quant);
- if (dbg_out.pcop_change_index.*) |pci|
- dbg_out.dbg_line.items[pci] += 1;
- dbg_out.pcop_change_index.* = @intCast(u32, 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
- } else unreachable;
- 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;
- self.prev_di_pc = self.code.items.len;
- },
- .none => {},
- }
-}
-
/// Asserts there is already capacity to insert into top branch inst_table.
fn processDeath(self: *Self, inst: Air.Inst.Index) void {
const air_tags = self.air.instructions.items(.tag);
@@ -1407,7 +1349,8 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
},
else => result,
};
- try self.genArgDbgInfo(inst, mcv);
+ // TODO generate debug info
+ // try self.genArgDbgInfo(inst, mcv);
if (self.liveness.isUnused(inst))
return self.finishAirBookkeeping();
@@ -1698,8 +1641,15 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
- _ = dbg_stmt;
- // try self.dbgAdvancePCAndLine(dbg_stmt.line, dbg_stmt.column);
+
+ _ = try self.addInst(.{
+ .tag = .dbg_line,
+ .data = .{ .dbg_line_column = .{
+ .line = dbg_stmt.line,
+ .column = dbg_stmt.column,
+ } },
+ });
+
return self.finishAirBookkeeping();
}
src/arch/aarch64/Emit.zig
@@ -8,14 +8,23 @@ const Mir = @import("Mir.zig");
const bits = @import("bits.zig");
const link = @import("../../link.zig");
const assert = std.debug.assert;
+const DW = std.dwarf;
+const leb128 = std.leb;
const Instruction = bits.Instruction;
const Register = bits.Register;
+const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
mir: Mir,
bin_file: *link.File,
+debug_output: DebugInfoOutput,
target: *const std.Target,
code: *std.ArrayList(u8),
+prev_di_line: u32,
+prev_di_column: u32,
+/// Relative to the beginning of `code`.
+prev_di_pc: usize,
+
pub fn emitMir(
emit: *Emit,
) !void {
@@ -38,6 +47,11 @@ pub fn emitMir(
.call_extern => try emit.mirCallExtern(inst),
+ .dbg_line => try emit.mirDbgLine(inst),
+
+ .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
+ .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
+
.load_memory => try emit.mirLoadMemory(inst),
.ldp => try emit.mirLoadStoreRegisterPair(inst),
@@ -80,6 +94,57 @@ fn moveImmediate(emit: *Emit, reg: Register, imm64: u64) !void {
}
}
+fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
+ const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
+ const delta_pc: usize = self.code.items.len - self.prev_di_pc;
+ switch (self.debug_output) {
+ .dwarf => |dbg_out| {
+ // 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.
+ try dbg_out.dbg_line.ensureUnusedCapacity(11);
+ dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
+ leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
+ if (delta_line != 0) {
+ dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
+ leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
+ }
+ dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
+ self.prev_di_pc = self.code.items.len;
+ self.prev_di_line = line;
+ self.prev_di_column = column;
+ self.prev_di_pc = self.code.items.len;
+ },
+ .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);
+ // increasing the pc
+ const d_pc_p9 = @intCast(i64, delta_pc) - quant;
+ 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(@intCast(u8, @divExact(d_pc_p9, quant) + 128) - quant);
+ if (dbg_out.pcop_change_index.*) |pci|
+ dbg_out.dbg_line.items[pci] += 1;
+ dbg_out.pcop_change_index.* = @intCast(u32, 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
+ } else unreachable;
+ 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;
+ self.prev_di_pc = self.code.items.len;
+ },
+ .none => {},
+ }
+}
+
fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
@@ -136,6 +201,38 @@ fn mirExceptionGeneration(emit: *Emit, inst: Mir.Inst.Index) !void {
}
}
+fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column;
+
+ switch (tag) {
+ .dbg_line => try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column),
+ else => unreachable,
+ }
+}
+
+fn mirDebugPrologueEnd(self: *Emit) !void {
+ switch (self.debug_output) {
+ .dwarf => |dbg_out| {
+ try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
+ try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
+ },
+ .plan9 => {},
+ .none => {},
+ }
+}
+
+fn mirDebugEpilogueBegin(self: *Emit) !void {
+ switch (self.debug_output) {
+ .dwarf => |dbg_out| {
+ 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 mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
assert(emit.mir.instructions.items(.tag)[inst] == .call_extern);
const n_strx = emit.mir.instructions.items(.data)[inst].extern_fn;
src/arch/aarch64/Mir.zig
@@ -36,6 +36,12 @@ pub const Inst = struct {
brk,
/// Pseudo-instruction: Call extern
call_extern,
+ /// Pseudo-instruction: End of prologue
+ dbg_prologue_end,
+ /// Pseudo-instruction: Beginning of epilogue
+ dbg_epilogue_begin,
+ /// Pseudo-instruction: Update debug line
+ dbg_line,
/// Psuedo-instruction: Load memory
///
/// Payload is `LoadMemory`
@@ -152,6 +158,13 @@ pub const Inst = struct {
rn: Register,
offset: bits.Instruction.LoadStorePairOffset,
},
+ /// Debug info: line and column
+ ///
+ /// Used by e.g. dbg_line
+ dbg_line_column: struct {
+ line: u32,
+ column: u32,
+ },
};
// Make sure we don't accidentally make instructions bigger than expected.