authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-15 19:22:35+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-16 09:41:27+02:00
log3bfb1616db0883e6145a1fe1844eee3038bd4ca1
tree8242c4c816ef753747cb492131a57a6f7cebf795
parent4c83b11f71564e0de80f496f471ca6dfb83a95e3

stage2 ARM: move genArgDbgInfo back to CodeGen

This removes the questionable Air -> Mir dependency that existed before. The x86_64 backend also performed this change.

3 files changed, 106 insertions(+), 124 deletions(-)

src/arch/arm/CodeGen.zig+106-8
...@@ -49,6 +49,7 @@ gpa: Allocator,...@@ -49,6 +49,7 @@ gpa: Allocator,
49air: Air,49air: Air,
50liveness: Liveness,50liveness: Liveness,
51bin_file: *link.File,51bin_file: *link.File,
52debug_output: DebugInfoOutput,
52target: *const std.Target,53target: *const std.Target,
53mod_fn: *const Module.Fn,54mod_fn: *const Module.Fn,
54err_msg: ?*ErrorMsg,55err_msg: ?*ErrorMsg,
...@@ -73,6 +74,12 @@ end_di_column: u32,...@@ -73,6 +74,12 @@ end_di_column: u32,
73/// which is a relative jump, based on the address following the reloc.74/// which is a relative jump, based on the address following the reloc.
74exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{},75exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{},
7576
77/// For every argument, we postpone the creation of debug info for
78/// later after all Mir instructions have been generated. Only then we
79/// will know saved_regs_stack_space which is necessary in order to
80/// address parameters passed on the stack.
81dbg_arg_relocs: std.ArrayListUnmanaged(DbgArgReloc) = .{},
82
76/// Whenever there is a runtime branch, we push a Branch onto this stack,83/// Whenever there is a runtime branch, we push a Branch onto this stack,
77/// and pop it off when the runtime branch joins. This provides an "overlay"84/// and pop it off when the runtime branch joins. This provides an "overlay"
78/// of the table of mappings from instructions to `MCValue` from within the branch.85/// of the table of mappings from instructions to `MCValue` from within the branch.
...@@ -244,6 +251,11 @@ const BigTomb = struct {...@@ -244,6 +251,11 @@ const BigTomb = struct {
244 }251 }
245};252};
246253
254const DbgArgReloc = struct {
255 inst: Air.Inst.Index,
256 index: u32,
257};
258
247const Self = @This();259const Self = @This();
248260
249pub fn generate(261pub fn generate(
...@@ -276,6 +288,7 @@ pub fn generate(...@@ -276,6 +288,7 @@ pub fn generate(
276 .liveness = liveness,288 .liveness = liveness,
277 .target = &bin_file.options.target,289 .target = &bin_file.options.target,
278 .bin_file = bin_file,290 .bin_file = bin_file,
291 .debug_output = debug_output,
279 .mod_fn = module_fn,292 .mod_fn = module_fn,
280 .err_msg = null,293 .err_msg = null,
281 .args = undefined, // populated after `resolveCallingConventionValues`294 .args = undefined, // populated after `resolveCallingConventionValues`
...@@ -291,6 +304,7 @@ pub fn generate(...@@ -291,6 +304,7 @@ pub fn generate(
291 defer function.stack.deinit(bin_file.allocator);304 defer function.stack.deinit(bin_file.allocator);
292 defer function.blocks.deinit(bin_file.allocator);305 defer function.blocks.deinit(bin_file.allocator);
293 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);306 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
307 defer function.dbg_arg_relocs.deinit(bin_file.allocator);
294308
295 var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {309 var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {
296 error.CodegenFail => return FnResult{ .fail = function.err_msg.? },310 error.CodegenFail => return FnResult{ .fail = function.err_msg.? },
...@@ -314,6 +328,10 @@ pub fn generate(...@@ -314,6 +328,10 @@ pub fn generate(
314 else => |e| return e,328 else => |e| return e,
315 };329 };
316330
331 for (function.dbg_arg_relocs.items) |reloc| {
332 try function.genArgDbgInfo(reloc.inst, reloc.index, call_info.stack_byte_count);
333 }
334
317 var mir = Mir{335 var mir = Mir{
318 .instructions = function.mir_instructions.toOwnedSlice(),336 .instructions = function.mir_instructions.toOwnedSlice(),
319 .extra = function.mir_extra.toOwnedSlice(bin_file.allocator),337 .extra = function.mir_extra.toOwnedSlice(bin_file.allocator),
...@@ -323,7 +341,6 @@ pub fn generate(...@@ -323,7 +341,6 @@ pub fn generate(
323 var emit = Emit{341 var emit = Emit{
324 .mir = mir,342 .mir = mir,
325 .bin_file = bin_file,343 .bin_file = bin_file,
326 .function = &function,
327 .debug_output = debug_output,344 .debug_output = debug_output,
328 .target = &bin_file.options.target,345 .target = &bin_file.options.target,
329 .src_loc = src_loc,346 .src_loc = src_loc,
...@@ -3074,6 +3091,91 @@ fn genInlineMemcpy(...@@ -3074,6 +3091,91 @@ fn genInlineMemcpy(
3074 // end:3091 // end:
3075}3092}
30763093
3094/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
3095/// after codegen for this symbol is done.
3096fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
3097 switch (self.debug_output) {
3098 .dwarf => |dw| {
3099 assert(ty.hasRuntimeBits());
3100 const dbg_info = &dw.dbg_info;
3101 const index = dbg_info.items.len;
3102 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
3103 const atom = switch (self.bin_file.tag) {
3104 .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom,
3105 .macho => unreachable,
3106 else => unreachable,
3107 };
3108 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
3109 },
3110 .plan9 => {},
3111 .none => {},
3112 }
3113}
3114
3115fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void {
3116 const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space;
3117
3118 const mcv = self.args[arg_index];
3119 const ty = self.air.instructions.items(.data)[inst].ty;
3120 const name = self.mod_fn.getParamName(arg_index);
3121 const name_with_null = name.ptr[0 .. name.len + 1];
3122
3123 switch (mcv) {
3124 .register => |reg| {
3125 switch (self.debug_output) {
3126 .dwarf => |dw| {
3127 const dbg_info = &dw.dbg_info;
3128 try dbg_info.ensureUnusedCapacity(3);
3129 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
3130 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
3131 1, // ULEB128 dwarf expression length
3132 reg.dwarfLocOp(),
3133 });
3134 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3135 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3136 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3137 },
3138 .plan9 => {},
3139 .none => {},
3140 }
3141 },
3142 .stack_offset,
3143 .stack_argument_offset,
3144 => {
3145 switch (self.debug_output) {
3146 .dwarf => |dw| {
3147 // const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3148 const adjusted_stack_offset = switch (mcv) {
3149 .stack_offset => |offset| -@intCast(i32, offset),
3150 .stack_argument_offset => |offset| @intCast(i32, prologue_stack_space - offset),
3151 else => unreachable,
3152 };
3153
3154 const dbg_info = &dw.dbg_info;
3155 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
3156
3157 // Get length of the LEB128 stack offset
3158 var counting_writer = std.io.countingWriter(std.io.null_writer);
3159 leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
3160
3161 // DW.AT.location, DW.FORM.exprloc
3162 // ULEB128 dwarf expression length
3163 try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1);
3164 try dbg_info.append(DW.OP.breg11);
3165 try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset);
3166
3167 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3168 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3169 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3170 },
3171 .plan9 => {},
3172 .none => {},
3173 }
3174 },
3175 else => unreachable, // not a possible argument
3176 }
3177}
3178
3077fn airArg(self: *Self, inst: Air.Inst.Index) !void {3179fn airArg(self: *Self, inst: Air.Inst.Index) !void {
3078 const arg_index = self.arg_index;3180 const arg_index = self.arg_index;
3079 self.arg_index += 1;3181 self.arg_index += 1;
...@@ -3094,13 +3196,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -3094,13 +3196,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
3094 else => result,3196 else => result,
3095 };3197 };
30963198
3097 _ = try self.addInst(.{3199 try self.dbg_arg_relocs.append(self.gpa, .{
3098 .tag = .dbg_arg,3200 .inst = inst,
3099 .cond = undefined,3201 .index = arg_index,
3100 .data = .{ .dbg_arg_info = .{
3101 .air_inst = inst,
3102 .arg_index = arg_index,
3103 } },
3104 });3202 });
31053203
3106 if (self.liveness.isUnused(inst))3204 if (self.liveness.isUnused(inst))
src/arch/arm/Emit.zig-106
...@@ -9,7 +9,6 @@ const Mir = @import("Mir.zig");...@@ -9,7 +9,6 @@ const Mir = @import("Mir.zig");
9const bits = @import("bits.zig");9const bits = @import("bits.zig");
10const link = @import("../../link.zig");10const link = @import("../../link.zig");
11const Module = @import("../../Module.zig");11const Module = @import("../../Module.zig");
12const Air = @import("../../Air.zig");
13const Type = @import("../../type.zig").Type;12const Type = @import("../../type.zig").Type;
14const ErrorMsg = Module.ErrorMsg;13const ErrorMsg = Module.ErrorMsg;
15const assert = std.debug.assert;14const assert = std.debug.assert;
...@@ -23,7 +22,6 @@ const CodeGen = @import("CodeGen.zig");...@@ -23,7 +22,6 @@ const CodeGen = @import("CodeGen.zig");
2322
24mir: Mir,23mir: Mir,
25bin_file: *link.File,24bin_file: *link.File,
26function: *const CodeGen,
27debug_output: DebugInfoOutput,25debug_output: DebugInfoOutput,
28target: *const std.Target,26target: *const std.Target,
29err_msg: ?*ErrorMsg = null,27err_msg: ?*ErrorMsg = null,
...@@ -102,8 +100,6 @@ pub fn emitMir(...@@ -102,8 +100,6 @@ pub fn emitMir(
102 .blx => try emit.mirBranchExchange(inst),100 .blx => try emit.mirBranchExchange(inst),
103 .bx => try emit.mirBranchExchange(inst),101 .bx => try emit.mirBranchExchange(inst),
104102
105 .dbg_arg => try emit.mirDbgArg(inst),
106
107 .dbg_line => try emit.mirDbgLine(inst),103 .dbg_line => try emit.mirDbgLine(inst),
108104
109 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),105 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
...@@ -189,7 +185,6 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {...@@ -189,7 +185,6 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
189 .dbg_line,185 .dbg_line,
190 .dbg_epilogue_begin,186 .dbg_epilogue_begin,
191 .dbg_prologue_end,187 .dbg_prologue_end,
192 .dbg_arg,
193 => return 0,188 => return 0,
194 else => return 4,189 else => return 4,
195 }190 }
...@@ -383,97 +378,6 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -383,97 +378,6 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
383 }378 }
384}379}
385380
386/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
387/// after codegen for this symbol is done.
388fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
389 switch (self.debug_output) {
390 .dwarf => |dw| {
391 assert(ty.hasRuntimeBits());
392 const dbg_info = &dw.dbg_info;
393 const index = dbg_info.items.len;
394 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
395 const atom = switch (self.bin_file.tag) {
396 .elf => &self.function.mod_fn.owner_decl.link.elf.dbg_info_atom,
397 .macho => unreachable,
398 else => unreachable,
399 };
400 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
401 },
402 .plan9 => {},
403 .none => {},
404 }
405}
406
407fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
408 const mcv = self.function.args[arg_index];
409
410 const ty = self.function.air.instructions.items(.data)[inst].ty;
411 const name = self.function.mod_fn.getParamName(arg_index);
412 const name_with_null = name.ptr[0 .. name.len + 1];
413 const target = self.target.*;
414
415 switch (mcv) {
416 .register => |reg| {
417 switch (self.debug_output) {
418 .dwarf => |dw| {
419 const dbg_info = &dw.dbg_info;
420 try dbg_info.ensureUnusedCapacity(3);
421 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
422 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
423 1, // ULEB128 dwarf expression length
424 reg.dwarfLocOp(),
425 });
426 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
427 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
428 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
429 },
430 .plan9 => {},
431 .none => {},
432 }
433 },
434 .stack_offset,
435 .stack_argument_offset,
436 => {
437 switch (self.debug_output) {
438 .dwarf => |dw| {
439 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
440 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)});
441 };
442 const adjusted_stack_offset = switch (mcv) {
443 .stack_offset => |offset| math.negateCast(offset + abi_size) catch {
444 return self.fail("Stack offset too large for arguments", .{});
445 },
446 .stack_argument_offset => |offset| math.cast(i32, self.prologue_stack_space - offset - abi_size) catch {
447 return self.fail("Stack offset too large for arguments", .{});
448 },
449 else => unreachable,
450 };
451
452 const dbg_info = &dw.dbg_info;
453 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
454
455 // Get length of the LEB128 stack offset
456 var counting_writer = std.io.countingWriter(std.io.null_writer);
457 leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable;
458
459 // DW.AT.location, DW.FORM.exprloc
460 // ULEB128 dwarf expression length
461 try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1);
462 try dbg_info.append(DW.OP.breg11);
463 try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset);
464
465 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
466 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
467 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
468 },
469 .plan9 => {},
470 .none => {},
471 }
472 },
473 else => unreachable, // not a possible argument
474 }
475}
476
477fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {381fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
478 const tag = emit.mir.instructions.items(.tag)[inst];382 const tag = emit.mir.instructions.items(.tag)[inst];
479 const cond = emit.mir.instructions.items(.cond)[inst];383 const cond = emit.mir.instructions.items(.cond)[inst];
...@@ -546,16 +450,6 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -546,16 +450,6 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void {
546 }450 }
547}451}
548452
549fn mirDbgArg(emit: *Emit, inst: Mir.Inst.Index) !void {
550 const tag = emit.mir.instructions.items(.tag)[inst];
551 const dbg_arg_info = emit.mir.instructions.items(.data)[inst].dbg_arg_info;
552
553 switch (tag) {
554 .dbg_arg => try emit.genArgDbgInfo(dbg_arg_info.air_inst, dbg_arg_info.arg_index),
555 else => unreachable,
556 }
557}
558
559fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {453fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
560 const tag = emit.mir.instructions.items(.tag)[inst];454 const tag = emit.mir.instructions.items(.tag)[inst];
561 const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column;455 const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column;
src/arch/arm/Mir.zig-10
...@@ -12,7 +12,6 @@ const builtin = @import("builtin");...@@ -12,7 +12,6 @@ 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");
16const Register = bits.Register;15const Register = bits.Register;
1716
18instructions: std.MultiArrayList(Inst).Slice,17instructions: std.MultiArrayList(Inst).Slice,
...@@ -44,8 +43,6 @@ pub const Inst = struct {...@@ -44,8 +43,6 @@ pub const Inst = struct {
44 bx,43 bx,
45 /// Compare44 /// Compare
46 cmp,45 cmp,
47 /// Pseudo-instruction: Argument
48 dbg_arg,
49 /// Pseudo-instruction: End of prologue46 /// Pseudo-instruction: End of prologue
50 dbg_prologue_end,47 dbg_prologue_end,
51 /// Pseudo-instruction: Beginning of epilogue48 /// Pseudo-instruction: Beginning of epilogue
...@@ -239,13 +236,6 @@ pub const Inst = struct {...@@ -239,13 +236,6 @@ pub const Inst = struct {
239 line: u32,236 line: u32,
240 column: u32,237 column: u32,
241 },238 },
242 /// Debug info: argument
243 ///
244 /// Used by e.g. dbg_arg
245 dbg_arg_info: struct {
246 air_inst: Air.Inst.Index,
247 arg_index: u32,
248 },
249 };239 };
250240
251 // Make sure we don't accidentally make instructions bigger than expected.241 // Make sure we don't accidentally make instructions bigger than expected.