| ... | @@ -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. |
| 78 | exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{}, | 78 | exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{}, |
| 79 | | 79 | |
| 80 | /// For every argument, we postpone the creation of debug info for | 80 | /// We postpone the creation of debug info for function args and locals |
| 81 | /// later after all Mir instructions have been generated. Only then we | 81 | /// until after all Mir instructions have been generated. Only then we |
| 82 | /// will know saved_regs_stack_space which is necessary in order to | 82 | /// 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. |
| 84 | dbg_arg_relocs: std.ArrayListUnmanaged(DbgArgReloc) = .{}, | 84 | dbg_info_relocs: std.ArrayListUnmanaged(DbgInfoReloc) = .{}, |
| 85 | | 85 | |
| 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 | }; |
| 245 | | 245 | |
| 246 | const DbgArgReloc = struct { | 246 | const 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 | }; |
| 250 | | 348 | |
| 251 | const Self = @This(); | 349 | const 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); |
| 302 | | 400 | |
| 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 | }; |
| 324 | | 422 | |
| 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 | } |
| 328 | | 426 | |
| 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); |
| 898 | | 996 | |
| 899 | if (abi_align > self.stack_align) | | |
| 900 | self.stack_align = abi_align; | | |
| 901 | | | |
| 902 | // TODO find a free slot instead of always appending | 997 | // 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 | } |
| 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 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { | 4133 | fn 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; |
| 4074 | | 4136 | |
| 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 | }); |
| 4079 | | 4148 | |
| 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 { |
| 4485 | | 4554 | |
| 4486 | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { | 4555 | fn 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 variable | 4558 | 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 | } |
| 4494 | | 4574 | |