authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2023-01-21 21:57:01+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-22 12:00:04+01:00
logc0284e242f7d78955204dc8a627fecd45aa5e521
tree7bfe52fde9be75289898b39c4a4a841ec531b3b4
parenta51c76541d60da81ef53e0ab1f221a80d9956bd5

stage2 ARM: add basic debug info for locals

Also disables one behavior test which was failing

2 files changed, 133 insertions(+), 52 deletions(-)

src/arch/arm/CodeGen.zig+132-52
...@@ -77,11 +77,11 @@ end_di_column: u32,...@@ -77,11 +77,11 @@ end_di_column: u32,
77/// which is a relative jump, based on the address following the reloc.77/// which is a relative jump, based on the address following the reloc.
78exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{},78exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{},
7979
80/// For every argument, we postpone the creation of debug info for80/// We postpone the creation of debug info for function args and locals
81/// later after all Mir instructions have been generated. Only then we81/// until after all Mir instructions have been generated. Only then we
82/// will know saved_regs_stack_space which is necessary in order to82/// will know saved_regs_stack_space which is necessary in order to
83/// address parameters passed on the stack.83/// calculate the right stack offsest with respect to the `.fp` register.
84dbg_arg_relocs: std.ArrayListUnmanaged(DbgArgReloc) = .{},84dbg_info_relocs: std.ArrayListUnmanaged(DbgInfoReloc) = .{},
8585
86/// Whenever there is a runtime branch, we push a Branch onto this stack,86/// Whenever there is a runtime branch, we push a Branch onto this stack,
87/// and pop it off when the runtime branch joins. This provides an "overlay"87/// and pop it off when the runtime branch joins. This provides an "overlay"
...@@ -243,9 +243,107 @@ const BigTomb = struct {...@@ -243,9 +243,107 @@ const BigTomb = struct {
243 }243 }
244};244};
245245
246const DbgArgReloc = struct {246const DbgInfoReloc = struct {
247 inst: Air.Inst.Index,247 tag: Air.Inst.Tag,
248 index: u32,248 ty: Type,
249 name: [:0]const u8,
250 mcv: MCValue,
251
252 fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
253 switch (reloc.tag) {
254 .arg => try reloc.genArgDbgInfo(function),
255
256 .dbg_var_ptr,
257 .dbg_var_val,
258 => try reloc.genVarDbgInfo(function),
259
260 else => unreachable,
261 }
262 }
263
264 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
265 switch (function.debug_output) {
266 .dwarf => |dw| {
267 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
268 .register => |reg| .{ .register = reg.dwarfLocOp() },
269 .stack_offset,
270 .stack_argument_offset,
271 => blk: {
272 const adjusted_stack_offset = switch (reloc.mcv) {
273 .stack_offset => |offset| -@intCast(i32, offset),
274 .stack_argument_offset => |offset| @intCast(i32, function.saved_regs_stack_space + offset),
275 else => unreachable,
276 };
277 break :blk .{ .stack = .{
278 .fp_register = DW.OP.breg11,
279 .offset = adjusted_stack_offset,
280 } };
281 },
282 else => unreachable, // not a possible argument
283 };
284
285 try dw.genArgDbgInfo(
286 reloc.name,
287 reloc.ty,
288 function.bin_file.tag,
289 function.mod_fn.owner_decl,
290 loc,
291 );
292 },
293 .plan9 => {},
294 .none => {},
295 }
296 }
297
298 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
299 const is_ptr = switch (reloc.tag) {
300 .dbg_var_ptr => true,
301 .dbg_var_val => false,
302 else => unreachable,
303 };
304
305 switch (function.debug_output) {
306 .dwarf => |dw| {
307 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
308 .register => |reg| .{ .register = reg.dwarfLocOp() },
309 .ptr_stack_offset,
310 .stack_offset,
311 .stack_argument_offset,
312 => |offset| blk: {
313 const adjusted_offset = switch (reloc.mcv) {
314 .ptr_stack_offset,
315 .stack_offset,
316 => -@intCast(i32, offset),
317 .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset),
318 else => unreachable,
319 };
320 break :blk .{ .stack = .{
321 .fp_register = DW.OP.breg11,
322 .offset = adjusted_offset,
323 } };
324 },
325 .memory => |address| .{ .memory = address },
326 .immediate => |x| .{ .immediate = x },
327 .undef => .undef,
328 .none => .none,
329 else => blk: {
330 log.debug("TODO generate debug info for {}", .{reloc.mcv});
331 break :blk .nop;
332 },
333 };
334 try dw.genVarDbgInfo(
335 reloc.name,
336 reloc.ty,
337 function.bin_file.tag,
338 function.mod_fn.owner_decl,
339 is_ptr,
340 loc,
341 );
342 },
343 .plan9 => {},
344 .none => {},
345 }
346 }
249};347};
250348
251const Self = @This();349const Self = @This();
...@@ -298,7 +396,7 @@ pub fn generate(...@@ -298,7 +396,7 @@ pub fn generate(
298 defer function.stack.deinit(bin_file.allocator);396 defer function.stack.deinit(bin_file.allocator);
299 defer function.blocks.deinit(bin_file.allocator);397 defer function.blocks.deinit(bin_file.allocator);
300 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);398 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
301 defer function.dbg_arg_relocs.deinit(bin_file.allocator);399 defer function.dbg_info_relocs.deinit(bin_file.allocator);
302400
303 var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {401 var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {
304 error.CodegenFail => return FnResult{ .fail = function.err_msg.? },402 error.CodegenFail => return FnResult{ .fail = function.err_msg.? },
...@@ -322,8 +420,8 @@ pub fn generate(...@@ -322,8 +420,8 @@ pub fn generate(
322 else => |e| return e,420 else => |e| return e,
323 };421 };
324422
325 for (function.dbg_arg_relocs.items) |reloc| {423 for (function.dbg_info_relocs.items) |reloc| {
326 try function.genArgDbgInfo(reloc.inst, reloc.index);424 try reloc.genDbgInfo(function);
327 }425 }
328426
329 var mir = Mir{427 var mir = Mir{
...@@ -896,9 +994,6 @@ fn allocMem(...@@ -896,9 +994,6 @@ fn allocMem(
896 assert(abi_size > 0);994 assert(abi_size > 0);
897 assert(abi_align > 0);995 assert(abi_align > 0);
898996
899 if (abi_align > self.stack_align)
900 self.stack_align = abi_align;
901
902 // TODO find a free slot instead of always appending997 // TODO find a free slot instead of always appending
903 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;998 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
904 self.next_stack_offset = offset;999 self.next_stack_offset = offset;
...@@ -4035,46 +4130,20 @@ fn genInlineMemsetCode(...@@ -4035,46 +4130,20 @@ fn genInlineMemsetCode(
4035 // end:4130 // end:
4036}4131}
40374132
4038fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void {
4039 const mcv = self.args[arg_index];
4040 const arg = self.air.instructions.items(.data)[inst].arg;
4041 const ty = self.air.getRefType(arg.ty);
4042 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
4043
4044 switch (self.debug_output) {
4045 .dwarf => |dw| {
4046 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
4047 .register => |reg| .{ .register = reg.dwarfLocOp() },
4048 .stack_offset,
4049 .stack_argument_offset,
4050 => blk: {
4051 const adjusted_stack_offset = switch (mcv) {
4052 .stack_offset => |offset| -@intCast(i32, offset),
4053 .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset),
4054 else => unreachable,
4055 };
4056 break :blk .{ .stack = .{
4057 .fp_register = DW.OP.breg11,
4058 .offset = adjusted_stack_offset,
4059 } };
4060 },
4061 else => unreachable, // not a possible argument
4062
4063 };
4064 try dw.genArgDbgInfo(name, ty, self.bin_file.tag, self.mod_fn.owner_decl, loc);
4065 },
4066 .plan9 => {},
4067 .none => {},
4068 }
4069}
4070
4071fn airArg(self: *Self, inst: Air.Inst.Index) !void {4133fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4072 const arg_index = self.arg_index;4134 const arg_index = self.arg_index;
4073 self.arg_index += 1;4135 self.arg_index += 1;
40744136
4075 try self.dbg_arg_relocs.append(self.gpa, .{4137 const ty = self.air.typeOfIndex(inst);
4076 .inst = inst,4138 const tag = self.air.instructions.items(.tag)[inst];
4077 .index = arg_index,4139 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4140 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
4141
4142 try self.dbg_info_relocs.append(self.gpa, .{
4143 .tag = tag,
4144 .ty = ty,
4145 .name = name,
4146 .mcv = self.args[arg_index],
4078 });4147 });
40794148
4080 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];4149 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
...@@ -4485,10 +4554,21 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -4485,10 +4554,21 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
44854554
4486fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {4555fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4487 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4556 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
4488 const name = self.air.nullTerminatedString(pl_op.payload);
4489 const operand = pl_op.operand;4557 const operand = pl_op.operand;
4490 // TODO emit debug info for this variable4558 const tag = self.air.instructions.items(.tag)[inst];
4491 _ = name;4559 const ty = self.air.typeOf(operand);
4560 const mcv = try self.resolveInst(operand);
4561 const name = self.air.nullTerminatedString(pl_op.payload);
4562
4563 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
4564
4565 try self.dbg_info_relocs.append(self.gpa, .{
4566 .tag = tag,
4567 .ty = ty,
4568 .name = name,
4569 .mcv = mcv,
4570 });
4571
4492 return self.finishAir(inst, .dead, .{ operand, .none, .none });4572 return self.finishAir(inst, .dead, .{ operand, .none, .none });
4493}4573}
44944574
test/behavior/pointers.zig+1
...@@ -509,6 +509,7 @@ test "ptrCast comptime known slice to C pointer" {...@@ -509,6 +509,7 @@ test "ptrCast comptime known slice to C pointer" {
509test "ptrToInt on a generic function" {509test "ptrToInt on a generic function" {
510 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO510 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
511 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO511 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
512 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO513 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
513 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
514515