authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-01-24 13:27:54+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-24 23:18:13+01:00
log76654015009038a07f14b9eb8500bb84e9e28099
tree1fb8848228473a8d9e85cf4fb30305f0671df94b
parent4e5495e443f8978f1e0fd8ccb6670a95f014f3b1

stage2 ARM: re-enable debug info for arguments

These were disabled during the MIR transition

3 files changed, 140 insertions(+), 93 deletions(-)

src/arch/arm/CodeGen.zig+17-89
...@@ -43,7 +43,7 @@ err_msg: ?*ErrorMsg,...@@ -43,7 +43,7 @@ err_msg: ?*ErrorMsg,
43args: []MCValue,43args: []MCValue,
44ret_mcv: MCValue,44ret_mcv: MCValue,
45fn_type: Type,45fn_type: Type,
46arg_index: usize,46arg_index: u32,
47src_loc: Module.SrcLoc,47src_loc: Module.SrcLoc,
48stack_align: u32,48stack_align: u32,
4949
...@@ -302,6 +302,7 @@ pub fn generate(...@@ -302,6 +302,7 @@ pub fn generate(
302 var emit = Emit{302 var emit = Emit{
303 .mir = mir,303 .mir = mir,
304 .bin_file = bin_file,304 .bin_file = bin_file,
305 .function = &function,
305 .debug_output = debug_output,306 .debug_output = debug_output,
306 .target = &bin_file.options.target,307 .target = &bin_file.options.target,
307 .src_loc = src_loc,308 .src_loc = src_loc,
...@@ -706,29 +707,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {...@@ -706,29 +707,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
706 try table.ensureUnusedCapacity(self.gpa, additional_count);707 try table.ensureUnusedCapacity(self.gpa, additional_count);
707}708}
708709
709/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
710/// after codegen for this symbol is done.
711fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
712 switch (self.debug_output) {
713 .dwarf => |dbg_out| {
714 assert(ty.hasCodeGenBits());
715 const index = dbg_out.dbg_info.items.len;
716 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
717
718 const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.gpa, ty);
719 if (!gop.found_existing) {
720 gop.value_ptr.* = .{
721 .off = undefined,
722 .relocs = .{},
723 };
724 }
725 try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index));
726 },
727 .plan9 => {},
728 .none => {},
729 }
730}
731
732fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 {710fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 {
733 if (abi_align > self.stack_align)711 if (abi_align > self.stack_align)
734 self.stack_align = abi_align;712 self.stack_align = abi_align;
...@@ -1171,6 +1149,9 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1171,6 +1149,9 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1171 switch (mcv) {1149 switch (mcv) {
1172 .dead, .unreach => unreachable,1150 .dead, .unreach => unreachable,
1173 .register => unreachable, // a slice doesn't fit in one register1151 .register => unreachable, // a slice doesn't fit in one register
1152 .stack_argument_offset => |off| {
1153 break :result MCValue{ .stack_argument_offset = off };
1154 },
1174 .stack_offset => |off| {1155 .stack_offset => |off| {
1175 break :result MCValue{ .stack_offset = off };1156 break :result MCValue{ .stack_offset = off };
1176 },1157 },
...@@ -1190,6 +1171,9 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1190,6 +1171,9 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1190 switch (mcv) {1171 switch (mcv) {
1191 .dead, .unreach => unreachable,1172 .dead, .unreach => unreachable,
1192 .register => unreachable, // a slice doesn't fit in one register1173 .register => unreachable, // a slice doesn't fit in one register
1174 .stack_argument_offset => |off| {
1175 break :result MCValue{ .stack_argument_offset = off + 4 };
1176 },
1193 .stack_offset => |off| {1177 .stack_offset => |off| {
1194 break :result MCValue{ .stack_offset = off + 4 };1178 break :result MCValue{ .stack_offset = off + 4 };
1195 },1179 },
...@@ -1208,7 +1192,6 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1208,7 +1192,6 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
1208 const mcv = try self.resolveInst(ty_op.operand);1192 const mcv = try self.resolveInst(ty_op.operand);
1209 switch (mcv) {1193 switch (mcv) {
1210 .dead, .unreach => unreachable,1194 .dead, .unreach => unreachable,
1211 .register => unreachable, // a slice doesn't fit in one register
1212 .ptr_stack_offset => |off| {1195 .ptr_stack_offset => |off| {
1213 break :result MCValue{ .ptr_stack_offset = off + 4 };1196 break :result MCValue{ .ptr_stack_offset = off + 4 };
1214 },1197 },
...@@ -1224,7 +1207,6 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1224,7 +1207,6 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
1224 const mcv = try self.resolveInst(ty_op.operand);1207 const mcv = try self.resolveInst(ty_op.operand);
1225 switch (mcv) {1208 switch (mcv) {
1226 .dead, .unreach => unreachable,1209 .dead, .unreach => unreachable,
1227 .register => unreachable, // a slice doesn't fit in one register
1228 .ptr_stack_offset => |off| {1210 .ptr_stack_offset => |off| {
1229 break :result MCValue{ .ptr_stack_offset = off };1211 break :result MCValue{ .ptr_stack_offset = off };
1230 },1212 },
...@@ -2135,66 +2117,6 @@ fn genArmInlineMemcpy(...@@ -2135,66 +2117,6 @@ fn genArmInlineMemcpy(
2135 // end:2117 // end:
2136}2118}
21372119
2138fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void {
2139 const ty_str = self.air.instructions.items(.data)[inst].ty_str;
2140 const zir = &self.mod_fn.owner_decl.getFileScope().zir;
2141 const name = zir.nullTerminatedString(ty_str.str);
2142 const name_with_null = name.ptr[0 .. name.len + 1];
2143 const ty = self.air.getRefType(ty_str.ty);
2144
2145 switch (mcv) {
2146 .register => |reg| {
2147 switch (self.debug_output) {
2148 .dwarf => |dbg_out| {
2149 try dbg_out.dbg_info.ensureUnusedCapacity(3);
2150 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
2151 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
2152 1, // ULEB128 dwarf expression length
2153 reg.dwarfLocOp(),
2154 });
2155 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
2156 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
2157 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
2158 },
2159 .plan9 => {},
2160 .none => {},
2161 }
2162 },
2163 .stack_offset => |offset| {
2164 switch (self.debug_output) {
2165 .dwarf => |dbg_out| {
2166 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
2167 return self.fail("type '{}' too big to fit into stack frame", .{ty});
2168 };
2169 const adjusted_stack_offset = math.negateCast(offset + abi_size) catch {
2170 return self.fail("Stack offset too large for arguments", .{});
2171 };
2172
2173 try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
2174
2175 // Get length of the LEB128 stack offset
2176 var counting_writer = std.io.countingWriter(std.io.null_writer);
2177 leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
2178
2179 // DW.AT.location, DW.FORM.exprloc
2180 // ULEB128 dwarf expression length
2181 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
2182 try dbg_out.dbg_info.append(DW.OP.breg11);
2183 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
2184
2185 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
2186 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
2187 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
2188 },
2189 .plan9 => {},
2190 .none => {},
2191 }
2192 },
2193 .stack_argument_offset => return self.fail("TODO genArgDbgInfo for stack_argument_offset", .{}),
2194 else => {},
2195 }
2196}
2197
2198fn airArg(self: *Self, inst: Air.Inst.Index) !void {2120fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2199 const arg_index = self.arg_index;2121 const arg_index = self.arg_index;
2200 self.arg_index += 1;2122 self.arg_index += 1;
...@@ -2216,8 +2138,15 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -2216,8 +2138,15 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2216 },2138 },
2217 else => result,2139 else => result,
2218 };2140 };
2219 // TODO generate debug info2141
2220 // try self.genArgDbgInfo(inst, mcv);2142 _ = try self.addInst(.{
2143 .tag = .dbg_arg,
2144 .cond = undefined,
2145 .data = .{ .dbg_arg_info = .{
2146 .air_inst = inst,
2147 .arg_index = arg_index,
2148 } },
2149 });
22212150
2222 if (self.liveness.isUnused(inst))2151 if (self.liveness.isUnused(inst))
2223 return self.finishAirBookkeeping();2152 return self.finishAirBookkeeping();
...@@ -3496,7 +3425,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3496,7 +3425,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3496 }3425 }
3497 },3426 },
3498 .stack_argument_offset => |unadjusted_off| {3427 .stack_argument_offset => |unadjusted_off| {
3499 // TODO: maybe addressing from sp instead of fp
3500 const abi_size = ty.abiSize(self.target.*);3428 const abi_size = ty.abiSize(self.target.*);
3501 const adj_off = unadjusted_off + abi_size;3429 const adj_off = unadjusted_off + abi_size;
35023430
src/arch/arm/Emit.zig+113-4
...@@ -8,6 +8,8 @@ const Mir = @import("Mir.zig");...@@ -8,6 +8,8 @@ const Mir = @import("Mir.zig");
8const bits = @import("bits.zig");8const bits = @import("bits.zig");
9const link = @import("../../link.zig");9const link = @import("../../link.zig");
10const Module = @import("../../Module.zig");10const Module = @import("../../Module.zig");
11const Air = @import("../../Air.zig");
12const Type = @import("../../type.zig").Type;
11const ErrorMsg = Module.ErrorMsg;13const ErrorMsg = Module.ErrorMsg;
12const assert = std.debug.assert;14const assert = std.debug.assert;
13const DW = std.dwarf;15const DW = std.dwarf;
...@@ -16,9 +18,11 @@ const Instruction = bits.Instruction;...@@ -16,9 +18,11 @@ const Instruction = bits.Instruction;
16const Register = bits.Register;18const Register = bits.Register;
17const log = std.log.scoped(.aarch64_emit);19const log = std.log.scoped(.aarch64_emit);
18const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;20const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
21const CodeGen = @import("CodeGen.zig");
1922
20mir: Mir,23mir: Mir,
21bin_file: *link.File,24bin_file: *link.File,
25function: *const CodeGen,
22debug_output: DebugInfoOutput,26debug_output: DebugInfoOutput,
23target: *const std.Target,27target: *const std.Target,
24err_msg: ?*ErrorMsg = null,28err_msg: ?*ErrorMsg = null,
...@@ -95,6 +99,8 @@ pub fn emitMir(...@@ -95,6 +99,8 @@ pub fn emitMir(
95 .blx => try emit.mirBranchExchange(inst),99 .blx => try emit.mirBranchExchange(inst),
96 .bx => try emit.mirBranchExchange(inst),100 .bx => try emit.mirBranchExchange(inst),
97101
102 .dbg_arg => try emit.mirDbgArg(inst),
103
98 .dbg_line => try emit.mirDbgLine(inst),104 .dbg_line => try emit.mirDbgLine(inst),
99105
100 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),106 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
...@@ -106,9 +112,9 @@ pub fn emitMir(...@@ -106,9 +112,9 @@ pub fn emitMir(
106 .str => try emit.mirLoadStore(inst),112 .str => try emit.mirLoadStore(inst),
107 .strb => try emit.mirLoadStore(inst),113 .strb => try emit.mirLoadStore(inst),
108114
109 .ldr_stack_argument => try emit.mirLoadStack(inst),115 .ldr_stack_argument => try emit.mirLoadStackArgument(inst),
110 .ldrb_stack_argument => try emit.mirLoadStack(inst),116 .ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
111 .ldrh_stack_argument => try emit.mirLoadStack(inst),117 .ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
112118
113 .ldrh => try emit.mirLoadStoreExtra(inst),119 .ldrh => try emit.mirLoadStoreExtra(inst),
114 .strh => try emit.mirLoadStoreExtra(inst),120 .strh => try emit.mirLoadStoreExtra(inst),
...@@ -168,6 +174,7 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -168,6 +174,7 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
168 .dbg_line,174 .dbg_line,
169 .dbg_epilogue_begin,175 .dbg_epilogue_begin,
170 .dbg_prologue_end,176 .dbg_prologue_end,
177 .dbg_arg,
171 => return 0,178 => return 0,
172 else => return 4,179 else => return 4,
173 }180 }
...@@ -360,6 +367,98 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -360,6 +367,98 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
360 }367 }
361}368}
362369
370/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
371/// after codegen for this symbol is done.
372fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
373 switch (self.debug_output) {
374 .dwarf => |dbg_out| {
375 assert(ty.hasCodeGenBits());
376 const index = dbg_out.dbg_info.items.len;
377 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
378
379 const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.bin_file.allocator, ty);
380 if (!gop.found_existing) {
381 gop.value_ptr.* = .{
382 .off = undefined,
383 .relocs = .{},
384 };
385 }
386 try gop.value_ptr.relocs.append(self.bin_file.allocator, @intCast(u32, index));
387 },
388 .plan9 => {},
389 .none => {},
390 }
391}
392
393fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
394 const mcv = self.function.args[arg_index];
395
396 const ty_str = self.function.air.instructions.items(.data)[inst].ty_str;
397 const zir = &self.function.mod_fn.owner_decl.getFileScope().zir;
398 const name = zir.nullTerminatedString(ty_str.str);
399 const name_with_null = name.ptr[0 .. name.len + 1];
400 const ty = self.function.air.getRefType(ty_str.ty);
401
402 switch (mcv) {
403 .register => |reg| {
404 switch (self.debug_output) {
405 .dwarf => |dbg_out| {
406 try dbg_out.dbg_info.ensureUnusedCapacity(3);
407 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
408 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
409 1, // ULEB128 dwarf expression length
410 reg.dwarfLocOp(),
411 });
412 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
413 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
414 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
415 },
416 .plan9 => {},
417 .none => {},
418 }
419 },
420 .stack_offset,
421 .stack_argument_offset,
422 => {
423 switch (self.debug_output) {
424 .dwarf => |dbg_out| {
425 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
426 return self.fail("type '{}' too big to fit into stack frame", .{ty});
427 };
428 const adjusted_stack_offset = switch (mcv) {
429 .stack_offset => |offset| math.negateCast(offset + abi_size) catch {
430 return self.fail("Stack offset too large for arguments", .{});
431 },
432 .stack_argument_offset => |offset| math.cast(i32, self.prologue_stack_space - offset - abi_size) catch {
433 return self.fail("Stack offset too large for arguments", .{});
434 },
435 else => unreachable,
436 };
437
438 try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
439
440 // Get length of the LEB128 stack offset
441 var counting_writer = std.io.countingWriter(std.io.null_writer);
442 leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
443
444 // DW.AT.location, DW.FORM.exprloc
445 // ULEB128 dwarf expression length
446 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
447 try dbg_out.dbg_info.append(DW.OP.breg11);
448 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
449
450 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
451 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
452 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
453 },
454 .plan9 => {},
455 .none => {},
456 }
457 },
458 else => unreachable, // not a possible argument
459 }
460}
461
363fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {462fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
364 const tag = emit.mir.instructions.items(.tag)[inst];463 const tag = emit.mir.instructions.items(.tag)[inst];
365 const cond = emit.mir.instructions.items(.cond)[inst];464 const cond = emit.mir.instructions.items(.cond)[inst];
...@@ -430,6 +529,16 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -430,6 +529,16 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void {
430 }529 }
431}530}
432531
532fn mirDbgArg(emit: *Emit, inst: Mir.Inst.Index) !void {
533 const tag = emit.mir.instructions.items(.tag)[inst];
534 const dbg_arg_info = emit.mir.instructions.items(.data)[inst].dbg_arg_info;
535
536 switch (tag) {
537 .dbg_arg => try emit.genArgDbgInfo(dbg_arg_info.air_inst, dbg_arg_info.arg_index),
538 else => unreachable,
539 }
540}
541
433fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {542fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
434 const tag = emit.mir.instructions.items(.tag)[inst];543 const tag = emit.mir.instructions.items(.tag)[inst];
435 const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column;544 const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column;
...@@ -476,7 +585,7 @@ fn mirLoadStore(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -476,7 +585,7 @@ fn mirLoadStore(emit: *Emit, inst: Mir.Inst.Index) !void {
476 }585 }
477}586}
478587
479fn mirLoadStack(emit: *Emit, inst: Mir.Inst.Index) !void {588fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
480 const tag = emit.mir.instructions.items(.tag)[inst];589 const tag = emit.mir.instructions.items(.tag)[inst];
481 const cond = emit.mir.instructions.items(.cond)[inst];590 const cond = emit.mir.instructions.items(.cond)[inst];
482 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;591 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;
src/arch/arm/Mir.zig+10
...@@ -12,6 +12,7 @@ const builtin = @import("builtin");...@@ -12,6 +12,7 @@ const builtin = @import("builtin");
12const assert = std.debug.assert;12const assert = std.debug.assert;
1313
14const bits = @import("bits.zig");14const bits = @import("bits.zig");
15const Air = @import("../../Air.zig");
15const Register = bits.Register;16const Register = bits.Register;
1617
17instructions: std.MultiArrayList(Inst).Slice,18instructions: std.MultiArrayList(Inst).Slice,
...@@ -41,6 +42,8 @@ pub const Inst = struct {...@@ -41,6 +42,8 @@ pub const Inst = struct {
41 bx,42 bx,
42 /// Compare43 /// Compare
43 cmp,44 cmp,
45 /// Pseudo-instruction: Argument
46 dbg_arg,
44 /// Pseudo-instruction: End of prologue47 /// Pseudo-instruction: End of prologue
45 dbg_prologue_end,48 dbg_prologue_end,
46 /// Pseudo-instruction: Beginning of epilogue49 /// Pseudo-instruction: Beginning of epilogue
...@@ -195,6 +198,13 @@ pub const Inst = struct {...@@ -195,6 +198,13 @@ pub const Inst = struct {
195 line: u32,198 line: u32,
196 column: u32,199 column: u32,
197 },200 },
201 /// Debug info: argument
202 ///
203 /// Used by e.g. dbg_arg
204 dbg_arg_info: struct {
205 air_inst: Air.Inst.Index,
206 arg_index: u32,
207 },
198 };208 };
199209
200 // Make sure we don't accidentally make instructions bigger than expected.210 // Make sure we don't accidentally make instructions bigger than expected.