| ... | ... | @@ -77,11 +77,11 @@ end_di_column: u32, |
| 77 | 77 | /// which is a relative jump, based on the address following the reloc. |
| 78 | 78 | exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{}, |
| 79 | 79 | |
| 80 | | /// For every argument, we postpone the creation of debug info for |
| 81 | | /// later after all Mir instructions have been generated. Only then we |
| 80 | /// We postpone the creation of debug info for function args and locals |
| 81 | /// until after all Mir instructions have been generated. Only then we |
| 82 | 82 | /// will know saved_regs_stack_space which is necessary in order to |
| 83 | | /// address parameters passed on the stack. |
| 84 | | dbg_arg_relocs: std.ArrayListUnmanaged(DbgArgReloc) = .{}, |
| 83 | /// calculate the right stack offsest with respect to the `.fp` register. |
| 84 | dbg_info_relocs: std.ArrayListUnmanaged(DbgInfoReloc) = .{}, |
| 85 | 85 | |
| 86 | 86 | /// Whenever there is a runtime branch, we push a Branch onto this stack, |
| 87 | 87 | /// and pop it off when the runtime branch joins. This provides an "overlay" |
| ... | ... | @@ -243,9 +243,107 @@ const BigTomb = struct { |
| 243 | 243 | } |
| 244 | 244 | }; |
| 245 | 245 | |
| 246 | | const DbgArgReloc = struct { |
| 247 | | inst: Air.Inst.Index, |
| 248 | | index: u32, |
| 246 | const DbgInfoReloc = struct { |
| 247 | tag: Air.Inst.Tag, |
| 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 | }; |
| 250 | 348 | |
| 251 | 349 | const Self = @This(); |
| ... | ... | @@ -298,7 +396,7 @@ pub fn generate( |
| 298 | 396 | defer function.stack.deinit(bin_file.allocator); |
| 299 | 397 | defer function.blocks.deinit(bin_file.allocator); |
| 300 | 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); |
| 302 | 400 | |
| 303 | 401 | var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { |
| 304 | 402 | error.CodegenFail => return FnResult{ .fail = function.err_msg.? }, |
| ... | ... | @@ -322,8 +420,8 @@ pub fn generate( |
| 322 | 420 | else => |e| return e, |
| 323 | 421 | }; |
| 324 | 422 | |
| 325 | | for (function.dbg_arg_relocs.items) |reloc| { |
| 326 | | try function.genArgDbgInfo(reloc.inst, reloc.index); |
| 423 | for (function.dbg_info_relocs.items) |reloc| { |
| 424 | try reloc.genDbgInfo(function); |
| 327 | 425 | } |
| 328 | 426 | |
| 329 | 427 | var mir = Mir{ |
| ... | ... | @@ -896,9 +994,6 @@ fn allocMem( |
| 896 | 994 | assert(abi_size > 0); |
| 897 | 995 | assert(abi_align > 0); |
| 898 | 996 | |
| 899 | | if (abi_align > self.stack_align) |
| 900 | | self.stack_align = abi_align; |
| 901 | | |
| 902 | 997 | // TODO find a free slot instead of always appending |
| 903 | 998 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 904 | 999 | self.next_stack_offset = offset; |
| ... | ... | @@ -4035,46 +4130,20 @@ fn genInlineMemsetCode( |
| 4035 | 4130 | // end: |
| 4036 | 4131 | } |
| 4037 | 4132 | |
| 4038 | | fn 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 | | |
| 4071 | 4133 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4072 | 4134 | const arg_index = self.arg_index; |
| 4073 | 4135 | self.arg_index += 1; |
| 4074 | 4136 | |
| 4075 | | try self.dbg_arg_relocs.append(self.gpa, .{ |
| 4076 | | .inst = inst, |
| 4077 | | .index = arg_index, |
| 4137 | const ty = self.air.typeOfIndex(inst); |
| 4138 | const tag = self.air.instructions.items(.tag)[inst]; |
| 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 | }); |
| 4079 | 4148 | |
| 4080 | 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 | 4554 | |
| 4486 | 4555 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 4487 | 4556 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 4488 | | const name = self.air.nullTerminatedString(pl_op.payload); |
| 4489 | 4557 | const operand = pl_op.operand; |
| 4490 | | // TODO emit debug info for this variable |
| 4491 | | _ = name; |
| 4558 | const tag = self.air.instructions.items(.tag)[inst]; |
| 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 | 4572 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); |
| 4493 | 4573 | } |
| 4494 | 4574 | |