From 5ee99f862a1b3a4d1f5ca304623e7394603136a6 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 14:06:24 +0100 Subject: [PATCH 01/10] dwarf: extract common logic for generating func arg dbg info --- src/arch/aarch64/CodeGen.zig | 37 +++++++++++------------------ src/arch/x86_64/CodeGen.zig | 45 +++++++++++++---------------------- src/link/Dwarf.zig | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 51 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 52f9a544b1..a335a5e5ad 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -186,22 +186,21 @@ const DbgInfoReloc = struct { } fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { - const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1]; + const mod = function.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(function.mod_fn.owner_decl); + const atom = switch (function.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; switch (function.debug_output) { .dwarf => |dw| { - const dbg_info = &dw.dbg_info; switch (reloc.mcv) { .register => |reg| { - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), + try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ + .register = reg.dwarfLocOp(), }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try function.addDbgInfoTypeReloc(reloc.ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string }, .stack_offset, @@ -212,20 +211,12 @@ const DbgInfoReloc = struct { .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), else => unreachable, }; - - try dbg_info.ensureUnusedCapacity(8); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // we will backpatch it after we encode the displacement in LEB128 - Register.x29.dwarfLocOpDeref(), // frame pointer + try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ + .stack = .{ + .fp_register = Register.x29.dwarfLocOpDeref(), + .offset = adjusted_offset, + }, }); - leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable; - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try function.addDbgInfoTypeReloc(reloc.ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, else => unreachable, // not a possible argument diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9efd50aec4..fb40e14d7f 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3818,38 +3818,27 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { } fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { - const name_with_null = name.ptr[0 .. name.len + 1]; + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + switch (self.debug_output) { .dwarf => |dw| { - const dbg_info = &dw.dbg_info; switch (mcv) { - .register => |reg| { - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, + .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ + .register = reg.dwarfLocOp(), + }), - .stack_offset => |off| { - try dbg_info.ensureUnusedCapacity(8); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // we will backpatch it after we encode the displacement in LEB128 - Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer - }); - leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable; - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - - }, + .stack_offset => |off| try dw.genArgDbgInfo(name, ty, atom, .{ + .stack = .{ + .fp_register = Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer + .offset = -off, + }, + }), else => unreachable, // not a valid function parameter } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 843d14edd7..299bb57d7e 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -560,6 +560,52 @@ pub const DeclState = struct { }, } } + + pub fn genArgDbgInfo( + self: *DeclState, + name: [:0]const u8, + ty: Type, + atom: *Atom, + loc: union(enum) { + register: u8, + stack: struct { fp_register: u8, offset: i32 }, + }, + ) error{OutOfMemory}!void { + const dbg_info = &self.dbg_info; + const name_with_null = name.ptr[0 .. name.len + 1]; + + switch (loc) { + .register => |reg| { + try dbg_info.ensureUnusedCapacity(3); + dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter)); + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, // ULEB128 dwarf expression length + reg, + }); + try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); + const index = dbg_info.items.len; + try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4 + dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string + + }, + .stack => |info| { + try dbg_info.ensureUnusedCapacity(8); + dbg_info.appendAssumeCapacity(@enumToInt(AbbrevKind.parameter)); + const fixup = dbg_info.items.len; + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, // we will backpatch it after we encode the displacement in LEB128 + info.fp_register, // frame pointer + }); + leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable; + dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); + try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); + const index = dbg_info.items.len; + try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); + dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string + + }, + } + } }; pub const AbbrevEntry = struct { From 7d0af639d82bc22b204e20b11f5f6aee1ed1766e Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 14:32:09 +0100 Subject: [PATCH 02/10] dwarf: update arm and riscv codegens to the new model --- src/arch/aarch64/CodeGen.zig | 44 +++++++-------- src/arch/arm/CodeGen.zig | 105 +++++++++++------------------------ src/arch/riscv64/CodeGen.zig | 67 ++++++---------------- src/arch/x86_64/CodeGen.zig | 25 ++++----- 4 files changed, 79 insertions(+), 162 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index a335a5e5ad..6bbbd00275 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -195,32 +195,28 @@ const DbgInfoReloc = struct { }; switch (function.debug_output) { - .dwarf => |dw| { - switch (reloc.mcv) { - .register => |reg| { - try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ - .register = reg.dwarfLocOp(), - }); - }, + .dwarf => |dw| switch (reloc.mcv) { + .register => |reg| try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ + .register = reg.dwarfLocOp(), + }), - .stack_offset, - .stack_argument_offset, - => |offset| { - const adjusted_offset = switch (reloc.mcv) { - .stack_offset => -@intCast(i32, offset), - .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), - else => unreachable, - }; - try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ - .stack = .{ - .fp_register = Register.x29.dwarfLocOpDeref(), - .offset = adjusted_offset, - }, - }); - }, + .stack_offset, + .stack_argument_offset, + => |offset| { + const adjusted_offset = switch (reloc.mcv) { + .stack_offset => -@intCast(i32, offset), + .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), + else => unreachable, + }; + try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ + .stack = .{ + .fp_register = Register.x29.dwarfLocOpDeref(), + .offset = adjusted_offset, + }, + }); + }, - else => unreachable, // not a possible argument - } + else => unreachable, // not a possible argument }, .plan9 => {}, .none => {}, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 970b9376e5..c58147a71d 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -4029,86 +4029,43 @@ fn genInlineMemsetCode( // end: } -/// Adds a Type to the .debug_info at the current position. The bytes will be populated later, -/// after codegen for this symbol is done. -fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { - switch (self.debug_output) { - .dwarf => |dw| { - assert(ty.hasRuntimeBits()); - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const atom = switch (self.bin_file.tag) { - .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom, - .macho => unreachable, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => {}, - .none => {}, - } -} - fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void { const mcv = self.args[arg_index]; const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const name_with_null = name.ptr[0 .. name.len + 1]; - switch (mcv) { - .register => |reg| { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, - .plan9 => {}, - .none => {}, - } + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + + switch (self.debug_output) { + .dwarf => |dw| switch (mcv) { + .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ + .register = reg.dwarfLocOp(), + }), + .stack_offset, + .stack_argument_offset, + => { + const adjusted_stack_offset = switch (mcv) { + .stack_offset => |offset| -@intCast(i32, offset), + .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), + else => unreachable, + }; + try dw.genArgDbgInfo(name, ty, atom, .{ + .stack = .{ + .fp_register = DW.OP.breg11, + .offset = adjusted_stack_offset, + }, + }); + }, + else => unreachable, // not a possible argument }, - .stack_offset, - .stack_argument_offset, - => { - switch (self.debug_output) { - .dwarf => |dw| { - const adjusted_stack_offset = switch (mcv) { - .stack_offset => |offset| -@intCast(i32, offset), - .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), - else => unreachable, - }; - - const dbg_info = &dw.dbg_info; - try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - - // Get length of the LEB128 stack offset - var counting_writer = std.io.countingWriter(std.io.null_writer); - leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; - - // DW.AT.location, DW.FORM.exprloc - // ULEB128 dwarf expression length - try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1); - try dbg_info.append(DW.OP.breg11); - try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset); - - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, - .plan9 => {}, - .none => {}, - } - }, - else => unreachable, // not a possible argument + .plan9 => {}, + .none => {}, } } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index ed132d3fbb..368c0ba71f 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -772,28 +772,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { try table.ensureUnusedCapacity(self.gpa, additional_count); } -/// Adds a Type to the .debug_info at the current position. The bytes will be populated later, -/// after codegen for this symbol is done. -fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { - switch (self.debug_output) { - .dwarf => |dw| { - assert(ty.hasRuntimeBits()); - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const atom = switch (self.bin_file.tag) { - .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom, - .macho => unreachable, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => {}, - .none => {}, - } -} - fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 { if (abi_align > self.stack_align) self.stack_align = abi_align; @@ -1627,36 +1605,25 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const name_with_null = name.ptr[0 .. name.len + 1]; - switch (mcv) { - .register => |reg| { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, - .plan9 => {}, - .none => {}, - } + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + + switch (self.debug_output) { + .dwarf => |dw| switch (mcv) { + .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ + .register = reg.dwarfLocOp(), + }), + .stack_offset => {}, + else => {}, }, - .stack_offset => |offset| { - _ = offset; - switch (self.debug_output) { - .dwarf => {}, - .plan9 => {}, - .none => {}, - } - }, - else => {}, + .plan9 => {}, + .none => {}, } } diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index fb40e14d7f..289df8d4f1 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3827,21 +3827,18 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { }; switch (self.debug_output) { - .dwarf => |dw| { - switch (mcv) { - .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ - .register = reg.dwarfLocOp(), - }), + .dwarf => |dw| switch (mcv) { + .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ + .register = reg.dwarfLocOp(), + }), + .stack_offset => |off| try dw.genArgDbgInfo(name, ty, atom, .{ + .stack = .{ + .fp_register = Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer + .offset = -off, + }, + }), - .stack_offset => |off| try dw.genArgDbgInfo(name, ty, atom, .{ - .stack = .{ - .fp_register = Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer - .offset = -off, - }, - }), - - else => unreachable, // not a valid function parameter - } + else => unreachable, // not a valid function parameter }, .plan9 => {}, .none => {}, From 00016ab6a0bd31bed77c86074a6666822b8d0f20 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 15:28:22 +0100 Subject: [PATCH 03/10] dwarf: extract common logic for generating func var dbg info --- src/arch/aarch64/CodeGen.zig | 21 ++-- src/arch/x86_64/CodeGen.zig | 223 +++++++++-------------------------- src/link/Dwarf.zig | 134 +++++++++++++++++++++ 3 files changed, 206 insertions(+), 172 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 6bbbd00275..d258fe2e28 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -184,15 +184,8 @@ const DbgInfoReloc = struct { else => unreachable, } } - fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { - const mod = function.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(function.mod_fn.owner_decl); - const atom = switch (function.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; + const atom = function.getDbgInfoAtomPtr(); switch (function.debug_output) { .dwarf => |dw| switch (reloc.mcv) { @@ -230,6 +223,7 @@ const DbgInfoReloc = struct { .dbg_var_val => reloc.ty, else => unreachable, }; + // const atom= function.getDbgInfoAtomPtr(); switch (function.debug_output) { .dwarf => |dw| { @@ -368,6 +362,17 @@ const DbgInfoReloc = struct { } }; +fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + return atom; +} + const Branch = struct { inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{}, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 289df8d4f1..f15f394f8c 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3818,13 +3818,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { } fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; + const atom = self.getDbgInfoAtomPtr(); switch (self.debug_output) { .dwarf => |dw| switch (mcv) { @@ -3845,6 +3839,64 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { } } +fn genVarDbgInfo( + self: Self, + tag: Air.Inst.Tag, + ty: Type, + mcv: MCValue, + name: [:0]const u8, +) !void { + const is_ptr = switch (tag) { + .dbg_var_ptr => true, + .dbg_var_val => false, + else => unreachable, + }; + const atom = self.getDbgInfoAtomPtr(); + + switch (self.debug_output) { + .dwarf => |dw| { + const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (mcv) { + .register => |reg| .{ + .register = reg.dwarfLocOp(), + }, + .ptr_stack_offset, + .stack_offset, + => |off| .{ .stack = .{ + .fp_register = Register.rbp.dwarfLocOpDeref(), + .offset = -off, + } }, + .memory => |address| .{ + .memory = .{ + .address = address, + .is_ptr = is_ptr, + }, + }, + .immediate => |x| .{ .immediate = x }, + .undef => .undef, + .none => .none, + else => blk: { + log.debug("TODO generate debug info for {}", .{mcv}); + break :blk .nop; + }, + }; + try dw.genVarDbgInfo(name, ty, atom, loc); + }, + .plan9 => {}, + .none => {}, + } +} + +fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + return atom; +} + fn airBreakpoint(self: *Self) !void { _ = try self.addInst(.{ .tag = .interrupt, @@ -4413,163 +4465,6 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ operand, .none, .none }); } -fn genVarDbgInfo( - self: Self, - tag: Air.Inst.Tag, - ty: Type, - mcv: MCValue, - name: [:0]const u8, -) !void { - const name_with_null = name.ptr[0 .. name.len + 1]; - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); - const endian = self.target.cpu.arch.endian(); - - switch (mcv) { - .register => |reg| { - try dbg_info.ensureUnusedCapacity(2); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); - }, - - .ptr_stack_offset, - .stack_offset, - => |off| { - try dbg_info.ensureUnusedCapacity(7); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // we will backpatch it after we encode the displacement in LEB128 - Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer - }); - leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable; - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - }, - - .memory, - .linker_load, - => { - const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)); - const is_ptr = switch (tag) { - .dbg_var_ptr => true, - .dbg_var_val => false, - else => unreachable, - }; - try dbg_info.ensureUnusedCapacity(2 + ptr_width); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1 + ptr_width + @boolToInt(is_ptr), - DW.OP.addr, // literal address - }); - const offset = @intCast(u32, dbg_info.items.len); - const addr = switch (mcv) { - .memory => |addr| addr, - else => 0, - }; - switch (ptr_width) { - 0...4 => { - try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); - }, - 5...8 => { - try dbg_info.writer().writeInt(u64, addr, endian); - }, - else => unreachable, - } - if (is_ptr) { - // We need deref the address as we point to the value via GOT entry. - try dbg_info.append(DW.OP.deref); - } - switch (mcv) { - .linker_load => |load_struct| try dw.addExprlocReloc( - load_struct.sym_index, - offset, - is_ptr, - ), - else => {}, - } - }, - - .immediate => |x| { - try dbg_info.ensureUnusedCapacity(2); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, - if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, - }); - if (ty.isSignedInt()) { - try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); - } else { - try leb128.writeULEB128(dbg_info.writer(), x); - } - try dbg_info.append(DW.OP.stack_value); - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - }, - - .undef => { - // DW.AT.location, DW.FORM.exprloc - // uleb128(exprloc_len) - // DW.OP.implicit_value uleb128(len_of_bytes) bytes - const abi_size = @intCast(u32, ty.abiSize(self.target.*)); - var implicit_value_len = std.ArrayList(u8).init(self.gpa); - defer implicit_value_len.deinit(); - try leb128.writeULEB128(implicit_value_len.writer(), abi_size); - const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; - try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); - try dbg_info.ensureUnusedCapacity(total_exprloc_len); - dbg_info.appendAssumeCapacity(DW.OP.implicit_value); - dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); - dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); - }, - - .none => { - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc - 2, DW.OP.lit0, DW.OP.stack_value, - }); - }, - - else => { - try dbg_info.ensureUnusedCapacity(2); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, DW.OP.nop, - }); - log.debug("TODO generate debug info for {}", .{mcv}); - }, - } - - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, - .plan9 => {}, - .none => {}, - } -} - -/// Adds a Type to the .debug_info at the current position. The bytes will be populated later, -/// after codegen for this symbol is done. -fn addDbgInfoTypeReloc(self: Self, ty: Type) !void { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => {}, - .none => {}, - } -} - fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { const abi_size = ty.abiSize(self.target.*); switch (mcv) { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 299bb57d7e..31b7d5b6e6 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -606,6 +606,140 @@ pub const DeclState = struct { }, } } + + pub const VarArgDbgInfoLoc = union(enum) { + register: u8, + stack: struct { + fp_register: u8, + offset: i32, + }, + memory: struct { + address: u64, + is_ptr: bool, + linker_load: ?struct { + type: enum { got, direct, import }, + sym_index: u32, + } = null, + }, + immediate: u64, + undef, + none, + nop, + }; + + pub fn genVarDbgInfo( + self: *DeclState, + name: [:0]const u8, + ty: Type, + atom: *Atom, + loc: VarArgDbgInfoLoc, + ) error{OutOfMemory}!void { + const dbg_info = &self.dbg_info; + const name_with_null = name.ptr[0 .. name.len + 1]; + try dbg_info.append(@enumToInt(AbbrevKind.variable)); + const target = self.mod.getTarget(); + const endian = target.cpu.arch.endian(); + + switch (loc) { + .register => |reg| { + try dbg_info.ensureUnusedCapacity(2); + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, // ULEB128 dwarf expression length + reg, + }); + }, + + .stack => |info| { + try dbg_info.ensureUnusedCapacity(7); + const fixup = dbg_info.items.len; + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, // we will backpatch it after we encode the displacement in LEB128 + info.fp_register, + }); + leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable; + dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); + }, + + .memory => |info| { + const ptr_width = @intCast(u8, @divExact(target.cpu.arch.ptrBitWidth(), 8)); + try dbg_info.ensureUnusedCapacity(2 + ptr_width); + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1 + ptr_width + @boolToInt(info.is_ptr), + DW.OP.addr, // literal address + }); + const offset = @intCast(u32, dbg_info.items.len); + switch (ptr_width) { + 0...4 => { + try dbg_info.writer().writeInt(u32, @intCast(u32, info.address), endian); + }, + 5...8 => { + try dbg_info.writer().writeInt(u64, info.address, endian); + }, + else => unreachable, + } + if (info.is_ptr) { + // We need deref the address as we point to the value via GOT entry. + try dbg_info.append(DW.OP.deref); + } + if (info.linker_load) |load_struct| try self.addExprlocReloc( + load_struct.sym_index, + offset, + info.is_ptr, + ); + }, + + .immediate => |x| { + try dbg_info.ensureUnusedCapacity(2); + const fixup = dbg_info.items.len; + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, + if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, + }); + if (ty.isSignedInt()) { + try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); + } else { + try leb128.writeULEB128(dbg_info.writer(), x); + } + try dbg_info.append(DW.OP.stack_value); + dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); + }, + + .undef => { + // DW.AT.location, DW.FORM.exprloc + // uleb128(exprloc_len) + // DW.OP.implicit_value uleb128(len_of_bytes) bytes + const abi_size = @intCast(u32, ty.abiSize(target)); + var implicit_value_len = std.ArrayList(u8).init(self.gpa); + defer implicit_value_len.deinit(); + try leb128.writeULEB128(implicit_value_len.writer(), abi_size); + const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; + try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); + try dbg_info.ensureUnusedCapacity(total_exprloc_len); + dbg_info.appendAssumeCapacity(DW.OP.implicit_value); + dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); + dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); + }, + + .none => { + try dbg_info.ensureUnusedCapacity(3); + dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc + 2, DW.OP.lit0, DW.OP.stack_value, + }); + }, + + .nop => { + try dbg_info.ensureUnusedCapacity(2); + dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc + 1, DW.OP.nop, + }); + }, + } + + try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); + const index = dbg_info.items.len; + try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); + dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string + } }; pub const AbbrevEntry = struct { From 5bffc17c42bb6eacd0cc09a61954e98ccf912fa4 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 16:32:09 +0100 Subject: [PATCH 04/10] codegen: make LinkerLoad a common struct shared by backends --- src/arch/aarch64/CodeGen.zig | 176 ++++++----------------------------- src/arch/x86_64/CodeGen.zig | 22 ++--- src/codegen.zig | 13 +++ src/link/Dwarf.zig | 6 +- 4 files changed, 57 insertions(+), 160 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index d258fe2e28..7beec57ebc 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -146,11 +146,8 @@ const MCValue = union(enum) { /// If the type is a pointer, it means the pointer address is at /// this memory location. memory: u64, - /// The value is in memory but requires a linker relocation fixup: - /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) - /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) - /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) - linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, + /// The value is in memory but requires a linker relocation fixup. + linker_load: codegen.LinkerLoad, /// The value is one of the stack variables. /// /// If the type is a pointer, it means the pointer address is in @@ -217,33 +214,23 @@ const DbgInfoReloc = struct { } fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { - const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1]; - const ty = switch (reloc.tag) { - .dbg_var_ptr => reloc.ty.childType(), - .dbg_var_val => reloc.ty, + const is_ptr = switch (reloc.tag) { + .dbg_var_ptr => true, + .dbg_var_val => false, else => unreachable, }; - // const atom= function.getDbgInfoAtomPtr(); + const atom = function.getDbgInfoAtomPtr(); switch (function.debug_output) { .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); - const endian = function.target.cpu.arch.endian(); - - switch (reloc.mcv) { - .register => |reg| { - try dbg_info.ensureUnusedCapacity(2); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); + const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) { + .register => |reg| .{ + .register = reg.dwarfLocOp(), }, - .ptr_stack_offset, .stack_offset, .stack_argument_offset, - => |offset| { + => |offset| blk: { const adjusted_offset = switch (reloc.mcv) { .ptr_stack_offset, .stack_offset, @@ -251,110 +238,31 @@ const DbgInfoReloc = struct { .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), else => unreachable, }; - - try dbg_info.ensureUnusedCapacity(7); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // we will backpatch it after we encode the displacement in LEB128 - Register.x29.dwarfLocOpDeref(), // frame pointer - }); - leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable; - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - }, - - .memory, - .linker_load, - => { - const ptr_width = @intCast(u8, @divExact(function.target.cpu.arch.ptrBitWidth(), 8)); - const is_ptr = switch (reloc.tag) { - .dbg_var_ptr => true, - .dbg_var_val => false, - else => unreachable, - }; - try dbg_info.ensureUnusedCapacity(2 + ptr_width); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1 + ptr_width + @boolToInt(is_ptr), - DW.OP.addr, // literal address - }); - const offset = @intCast(u32, dbg_info.items.len); - const addr = switch (reloc.mcv) { - .memory => |addr| addr, - else => 0, - }; - switch (ptr_width) { - 0...4 => { - try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); + break :blk .{ + .stack = .{ + .fp_register = Register.x29.dwarfLocOpDeref(), + .offset = adjusted_offset, }, - 5...8 => { - try dbg_info.writer().writeInt(u64, addr, endian); - }, - else => unreachable, - } - if (is_ptr) { - // We need deref the address as we point to the value via GOT entry. - try dbg_info.append(DW.OP.deref); - } - switch (reloc.mcv) { - .linker_load => |load_struct| try dw.addExprlocReloc( - load_struct.sym_index, - offset, - is_ptr, - ), - else => {}, - } + }; }, - - .immediate => |x| { - try dbg_info.ensureUnusedCapacity(2); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, - if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, - }); - if (ty.isSignedInt()) { - try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); - } else { - try leb128.writeULEB128(dbg_info.writer(), x); - } - try dbg_info.append(DW.OP.stack_value); - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - }, - - .undef => { - // DW.AT.location, DW.FORM.exprloc - // uleb128(exprloc_len) - // DW.OP.implicit_value uleb128(len_of_bytes) bytes - const abi_size = @intCast(u32, ty.abiSize(function.target.*)); - var implicit_value_len = std.ArrayList(u8).init(function.gpa); - defer implicit_value_len.deinit(); - try leb128.writeULEB128(implicit_value_len.writer(), abi_size); - const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; - try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); - try dbg_info.ensureUnusedCapacity(total_exprloc_len); - dbg_info.appendAssumeCapacity(DW.OP.implicit_value); - dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); - dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); - }, - - .none => { - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc - 2, DW.OP.lit0, DW.OP.stack_value, - }); - }, - - else => { - try dbg_info.ensureUnusedCapacity(2); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, DW.OP.nop, - }); + .memory => |address| .{ .memory = .{ + .address = address, + .is_ptr = is_ptr, + } }, + .linker_load => |linker_load| .{ .memory = .{ + .address = 0, + .is_ptr = is_ptr, + .linker_load = linker_load, + } }, + .immediate => |x| .{ .immediate = x }, + .undef => .undef, + .none => .none, + else => blk: { log.debug("TODO generate debug info for {}", .{reloc.mcv}); + break :blk .nop; }, - } - - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try function.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string + }; + try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc); }, .plan9 => {}, .none => {}, @@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { try table.ensureUnusedCapacity(self.gpa, additional_count); } -/// Adds a Type to the .debug_info at the current position. The bytes will be populated later, -/// after codegen for this symbol is done. -fn addDbgInfoTypeReloc(self: Self, ty: Type) !void { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => {}, - .none => {}, - } -} - fn allocMem( self: *Self, abi_size: u32, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f15f394f8c..8b3ae1e606 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -128,11 +128,8 @@ pub const MCValue = union(enum) { /// The value is in memory at a hard-coded address. /// If the type is a pointer, it means the pointer address is at this memory location. memory: u64, - /// The value is in memory but requires a linker relocation fixup: - /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) - /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) - /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) - linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, + /// The value is in memory but requires a linker relocation fixup. + linker_load: codegen.LinkerLoad, /// The value is one of the stack variables. /// If the type is a pointer, it means the pointer address is in the stack at this offset. stack_offset: i32, @@ -3865,12 +3862,15 @@ fn genVarDbgInfo( .fp_register = Register.rbp.dwarfLocOpDeref(), .offset = -off, } }, - .memory => |address| .{ - .memory = .{ - .address = address, - .is_ptr = is_ptr, - }, - }, + .memory => |address| .{ .memory = .{ + .address = address, + .is_ptr = is_ptr, + } }, + .linker_load => |linker_load| .{ .memory = .{ + .address = 0, + .is_ptr = is_ptr, + .linker_load = linker_load, + } }, .immediate => |x| .{ .immediate = x }, .undef => .undef, .none => .none, diff --git a/src/codegen.zig b/src/codegen.zig index 5a28ce1860..d6b2ed7d93 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -68,6 +68,19 @@ pub const DebugInfoOutput = union(enum) { none, }; +/// Helper struct to denote that the value is in memory but requires a linker relocation fixup: +/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) +/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) +/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) +pub const LinkerLoad = struct { + type: enum { + got, + direct, + import, + }, + sym_index: u32, +}; + pub fn generateFunction( bin_file: *link.File, src_loc: Module.SrcLoc, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 31b7d5b6e6..2c5a948d98 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -16,6 +16,7 @@ const DW = std.dwarf; const File = link.File; const LinkBlock = File.LinkBlock; const LinkFn = File.LinkFn; +const LinkerLoad = @import("../codegen.zig").LinkerLoad; const Module = @import("../Module.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; @@ -616,10 +617,7 @@ pub const DeclState = struct { memory: struct { address: u64, is_ptr: bool, - linker_load: ?struct { - type: enum { got, direct, import }, - sym_index: u32, - } = null, + linker_load: ?LinkerLoad = null, }, immediate: u64, undef, From 41203325770e87920e797a7113da626ce2cf1b06 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 17:23:28 +0100 Subject: [PATCH 05/10] dwarf: fix typos after refactoring dbi gen --- src/arch/aarch64/CodeGen.zig | 13 +++------- src/arch/x86_64/CodeGen.zig | 13 +++------- src/link/Dwarf.zig | 49 ++++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 7beec57ebc..ae24178a5a 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -245,15 +245,8 @@ const DbgInfoReloc = struct { }, }; }, - .memory => |address| .{ .memory = .{ - .address = address, - .is_ptr = is_ptr, - } }, - .linker_load => |linker_load| .{ .memory = .{ - .address = 0, - .is_ptr = is_ptr, - .linker_load = linker_load, - } }, + .memory => |address| .{ .memory = address }, + .linker_load => |linker_load| .{ .linker_load = linker_load }, .immediate => |x| .{ .immediate = x }, .undef => .undef, .none => .none, @@ -262,7 +255,7 @@ const DbgInfoReloc = struct { break :blk .nop; }, }; - try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc); + try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, is_ptr, loc); }, .plan9 => {}, .none => {}, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 8b3ae1e606..5d9e3ccb5e 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3862,15 +3862,8 @@ fn genVarDbgInfo( .fp_register = Register.rbp.dwarfLocOpDeref(), .offset = -off, } }, - .memory => |address| .{ .memory = .{ - .address = address, - .is_ptr = is_ptr, - } }, - .linker_load => |linker_load| .{ .memory = .{ - .address = 0, - .is_ptr = is_ptr, - .linker_load = linker_load, - } }, + .memory => |address| .{ .memory = address }, + .linker_load => |linker_load| .{ .linker_load = linker_load }, .immediate => |x| .{ .immediate = x }, .undef => .undef, .none => .none, @@ -3879,7 +3872,7 @@ fn genVarDbgInfo( break :blk .nop; }, }; - try dw.genVarDbgInfo(name, ty, atom, loc); + try dw.genVarDbgInfo(name, ty, atom, is_ptr, loc); }, .plan9 => {}, .none => {}, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 2c5a948d98..89ef68b6cf 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -585,6 +585,7 @@ pub const DeclState = struct { }); try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); const index = dbg_info.items.len; + try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string @@ -601,6 +602,7 @@ pub const DeclState = struct { dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); const index = dbg_info.items.len; + try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string @@ -614,11 +616,8 @@ pub const DeclState = struct { fp_register: u8, offset: i32, }, - memory: struct { - address: u64, - is_ptr: bool, - linker_load: ?LinkerLoad = null, - }, + memory: u64, + linker_load: LinkerLoad, immediate: u64, undef, none, @@ -630,6 +629,7 @@ pub const DeclState = struct { name: [:0]const u8, ty: Type, atom: *Atom, + is_ptr: bool, loc: VarArgDbgInfoLoc, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; @@ -637,6 +637,7 @@ pub const DeclState = struct { try dbg_info.append(@enumToInt(AbbrevKind.variable)); const target = self.mod.getTarget(); const endian = target.cpu.arch.endian(); + const child_ty = if (is_ptr) ty.childType() else ty; switch (loc) { .register => |reg| { @@ -658,32 +659,41 @@ pub const DeclState = struct { dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); }, - .memory => |info| { + .memory, + .linker_load, + => { const ptr_width = @intCast(u8, @divExact(target.cpu.arch.ptrBitWidth(), 8)); try dbg_info.ensureUnusedCapacity(2 + ptr_width); dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1 + ptr_width + @boolToInt(info.is_ptr), + 1 + ptr_width + @boolToInt(is_ptr), DW.OP.addr, // literal address }); const offset = @intCast(u32, dbg_info.items.len); + const addr = switch (loc) { + .memory => |x| x, + else => 0, + }; switch (ptr_width) { 0...4 => { - try dbg_info.writer().writeInt(u32, @intCast(u32, info.address), endian); + try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); }, 5...8 => { - try dbg_info.writer().writeInt(u64, info.address, endian); + try dbg_info.writer().writeInt(u64, addr, endian); }, else => unreachable, } - if (info.is_ptr) { + if (is_ptr) { // We need deref the address as we point to the value via GOT entry. try dbg_info.append(DW.OP.deref); } - if (info.linker_load) |load_struct| try self.addExprlocReloc( - load_struct.sym_index, - offset, - info.is_ptr, - ); + switch (loc) { + .linker_load => |load_struct| try self.addExprlocReloc( + load_struct.sym_index, + offset, + is_ptr, + ), + else => {}, + } }, .immediate => |x| { @@ -691,9 +701,9 @@ pub const DeclState = struct { const fixup = dbg_info.items.len; dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc 1, - if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, + if (child_ty.isSignedInt()) DW.OP.consts else DW.OP.constu, }); - if (ty.isSignedInt()) { + if (child_ty.isSignedInt()) { try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); } else { try leb128.writeULEB128(dbg_info.writer(), x); @@ -706,7 +716,7 @@ pub const DeclState = struct { // DW.AT.location, DW.FORM.exprloc // uleb128(exprloc_len) // DW.OP.implicit_value uleb128(len_of_bytes) bytes - const abi_size = @intCast(u32, ty.abiSize(target)); + const abi_size = @intCast(u32, child_ty.abiSize(target)); var implicit_value_len = std.ArrayList(u8).init(self.gpa); defer implicit_value_len.deinit(); try leb128.writeULEB128(implicit_value_len.writer(), abi_size); @@ -735,7 +745,8 @@ pub const DeclState = struct { try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); const index = dbg_info.items.len; - try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); + try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 + try self.addTypeRelocGlobal(atom, child_ty, @intCast(u32, index)); dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string } }; From 17ab40f755a038bd9c06c7817354f9ce2eb4353f Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 20:06:11 +0100 Subject: [PATCH 06/10] dwarf: refactor arm and riscv64 to the new scheme --- src/arch/arm/CodeGen.zig | 22 ++++++++----- src/arch/sparc64/CodeGen.zig | 64 ++++++++++-------------------------- 2 files changed, 31 insertions(+), 55 deletions(-) diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index c58147a71d..066a82e5a2 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -4029,18 +4029,11 @@ fn genInlineMemsetCode( // end: } -fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void { +fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void { const mcv = self.args[arg_index]; const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; + const atom = self.getDbgInfoAtom(); switch (self.debug_output) { .dwarf => |dw| switch (mcv) { @@ -4069,6 +4062,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfM } } +fn getDbgInfoAtom(self: Self) *link.File.Dwarf.Atom { + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + return atom; +} + fn airArg(self: *Self, inst: Air.Inst.Index) !void { const arg_index = self.arg_index; self.arg_index += 1; diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index f22849c652..66d14f755b 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -2460,26 +2460,6 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { // Common helper functions -/// Adds a Type to the .debug_info at the current position. The bytes will be populated later, -/// after codegen for this symbol is done. -fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { - switch (self.debug_output) { - .dwarf => |dw| { - assert(ty.hasRuntimeBits()); - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const atom = switch (self.bin_file.tag) { - .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - else => {}, - } -} - fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { const gpa = self.gpa; try self.mir_instructions.ensureUnusedCapacity(gpa, 1); @@ -3272,40 +3252,32 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live self.finishAirBookkeeping(); } -fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { +fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const name_with_null = name.ptr[0 .. name.len + 1]; + const atom = self.getDbgInfoAtomPtr(); - switch (mcv) { - .register => |reg| { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.ensureUnusedCapacity(3); - dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, - else => {}, - } - }, - .stack_offset => |offset| { - _ = offset; - switch (self.debug_output) { - .dwarf => {}, - else => {}, - } + switch (self.debug_output) { + .dwarf => |dw| switch (mcv) { + .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ + .register = reg.dwarfLocOp(), + }), + else => {}, }, else => {}, } } +fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + else => unreachable, + }; + return atom; +} + // TODO replace this to call to extern memcpy fn genInlineMemcpy( self: *Self, From 8fea84f77ebc6805fe4558ae73064955dbfdcb64 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 1 Dec 2022 20:55:55 +0100 Subject: [PATCH 07/10] dwarf: move Wasm specific dwarf gen out of codegen --- src/arch/wasm/CodeGen.zig | 77 +++++++++------------------------------ src/link/Dwarf.zig | 58 +++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 74 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ebfff25b2f..ddb1803998 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1291,23 +1291,6 @@ fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, target: } } -/// For a given `Type`, add debug information to .debug_info at the current position. -/// The actual bytes will be written to the position after relocation. -fn addDbgInfoTypeReloc(func: *CodeGen, ty: Type) !void { - switch (func.debug_output) { - .dwarf => |dwarf| { - assert(ty.hasRuntimeBitsIgnoreComptime()); - const dbg_info = &dwarf.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); - const atom = &func.decl.link.wasm.dbg_info_atom; - try dwarf.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => unreachable, - .none => {}, - } -} - /// Lowers a Zig type and its value based on a given calling convention to ensure /// it matches the ABI. fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void { @@ -2358,24 +2341,10 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .dwarf => |dwarf| { // TODO: Get the original arg index rather than wasm arg index const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, arg_index); - const leb_size = link.File.Wasm.getULEB128Size(arg.local.value); - const dbg_info = &dwarf.dbg_info; - try dbg_info.ensureUnusedCapacity(3 + leb_size + 5 + name.len + 1); - // wasm locations are encoded as follow: - // DW_OP_WASM_location wasm-op - // where wasm-op is defined as - // wasm-op := wasm-local | wasm-global | wasm-operand_stack - // where each argument is encoded as - // i:uleb128 - dbg_info.appendSliceAssumeCapacity(&.{ - @enumToInt(link.File.Dwarf.AbbrevKind.parameter), - std.dwarf.OP.WASM_location, - std.dwarf.OP.WASM_local, + const atom = func.getDbgInfoAtom(); + try dwarf.genArgDbgInfo(name, arg_ty, atom, .{ + .wasm_local = arg.local.value, }); - leb.writeULEB128(dbg_info.writer(), arg.local.value) catch unreachable; - try func.addDbgInfoTypeReloc(arg_ty); - dbg_info.appendSliceAssumeCapacity(name); - dbg_info.appendAssumeCapacity(0); }, else => {}, } @@ -2383,6 +2352,12 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { func.finishAir(inst, arg, &.{}); } +fn getDbgInfoAtom(func: CodeGen) *link.File.Dwarf.Atom { + const mod = func.bin_file.base.options.module.?; + const fn_owner_decl = mod.declPtr(func.mod_fn.owner_decl); + return &fn_owner_decl.link.wasm.dbg_info_atom; +} + fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { const bin_op = func.air.instructions.items(.data)[inst].bin_op; if (func.liveness.isUnused(inst)) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs }); @@ -5345,38 +5320,22 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { const pl_op = func.air.instructions.items(.data)[inst].pl_op; const ty = func.air.typeOf(pl_op.operand); const operand = try func.resolveInst(pl_op.operand); - const op_ty = if (is_ptr) ty.childType() else ty; - log.debug("airDbgVar: %{d}: {}, {}", .{ inst, op_ty.fmtDebug(), operand }); + log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand }); const name = func.air.nullTerminatedString(pl_op.payload); log.debug(" var name = ({s})", .{name}); - const dbg_info = &func.debug_output.dwarf.dbg_info; - try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); - switch (operand) { - .local => |local| { - const leb_size = link.File.Wasm.getULEB128Size(local.value); - try dbg_info.ensureUnusedCapacity(2 + leb_size); - // wasm locals are encoded as follow: - // DW_OP_WASM_location wasm-op - // where wasm-op is defined as - // wasm-op := wasm-local | wasm-global | wasm-operand_stack - // where wasm-local is encoded as - // wasm-local := 0x00 i:uleb128 - dbg_info.appendSliceAssumeCapacity(&.{ - std.dwarf.OP.WASM_location, - std.dwarf.OP.WASM_local, - }); - leb.writeULEB128(dbg_info.writer(), local.value) catch unreachable; + const atom = func.getDbgInfoAtom(); + const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (operand) { + .local => |local| .{ .wasm_local = local.value }, + else => blk: { + log.debug("TODO generate debug info for {}", .{operand}); + break :blk .nop; }, - else => {}, // TODO - } + }; + try func.debug_output.dwarf.genVarDbgInfo(name, ty, atom, is_ptr, loc); - try dbg_info.ensureUnusedCapacity(5 + name.len + 1); - try func.addDbgInfoTypeReloc(op_ty); - dbg_info.appendSliceAssumeCapacity(name); - dbg_info.appendAssumeCapacity(0); func.finishAir(inst, .none, &.{}); } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 89ef68b6cf..feb2857322 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -102,7 +102,7 @@ pub const DeclState = struct { self.exprloc_relocs.deinit(self.gpa); } - pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void { + fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void { log.debug("{x}: target sym %{d}, via GOT {}", .{ offset, target, is_ptr }); try self.exprloc_relocs.append(self.gpa, .{ .type = if (is_ptr) .got_load else .direct_load, @@ -113,7 +113,7 @@ pub const DeclState = struct { /// Adds local type relocation of the form: @offset => @this + addend /// @this signifies the offset within the .debug_abbrev section of the containing atom. - pub fn addTypeRelocLocal(self: *DeclState, atom: *const Atom, offset: u32, addend: u32) !void { + fn addTypeRelocLocal(self: *DeclState, atom: *const Atom, offset: u32, addend: u32) !void { log.debug("{x}: @this + {x}", .{ offset, addend }); try self.abbrev_relocs.append(self.gpa, .{ .target = null, @@ -126,7 +126,7 @@ pub const DeclState = struct { /// Adds global type relocation of the form: @offset => @symbol + 0 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section /// which we use as our target of the relocation. - pub fn addTypeRelocGlobal(self: *DeclState, atom: *const Atom, ty: Type, offset: u32) !void { + fn addTypeRelocGlobal(self: *DeclState, atom: *const Atom, ty: Type, offset: u32) !void { const resolv = self.abbrev_resolver.getContext(ty, .{ .mod = self.mod, }) orelse blk: { @@ -570,6 +570,7 @@ pub const DeclState = struct { loc: union(enum) { register: u8, stack: struct { fp_register: u8, offset: i32 }, + wasm_local: u32, }, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; @@ -583,12 +584,6 @@ pub const DeclState = struct { 1, // ULEB128 dwarf expression length reg, }); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 - try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - }, .stack => |info| { try dbg_info.ensureUnusedCapacity(8); @@ -600,14 +595,30 @@ pub const DeclState = struct { }); leb128.writeILEB128(dbg_info.writer(), info.offset) catch unreachable; dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 - try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string - + }, + .wasm_local => |value| { + const leb_size = link.File.Wasm.getULEB128Size(value); + try dbg_info.ensureUnusedCapacity(3 + leb_size); + // wasm locations are encoded as follow: + // DW_OP_WASM_location wasm-op + // where wasm-op is defined as + // wasm-op := wasm-local | wasm-global | wasm-operand_stack + // where each argument is encoded as + // i:uleb128 + dbg_info.appendSliceAssumeCapacity(&.{ + @enumToInt(AbbrevKind.parameter), + DW.OP.WASM_location, + DW.OP.WASM_local, + }); + leb128.writeULEB128(dbg_info.writer(), value) catch unreachable; }, } + + try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); + const index = dbg_info.items.len; + try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4 + try self.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); // DW.AT.type, DW.FORM.ref4 + dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string } pub const VarArgDbgInfoLoc = union(enum) { @@ -616,6 +627,7 @@ pub const DeclState = struct { fp_register: u8, offset: i32, }, + wasm_local: u32, memory: u64, linker_load: LinkerLoad, immediate: u64, @@ -659,6 +671,22 @@ pub const DeclState = struct { dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); }, + .wasm_local => |value| { + const leb_size = link.File.Wasm.getULEB128Size(value); + try dbg_info.ensureUnusedCapacity(2 + leb_size); + // wasm locals are encoded as follow: + // DW_OP_WASM_location wasm-op + // where wasm-op is defined as + // wasm-op := wasm-local | wasm-global | wasm-operand_stack + // where wasm-local is encoded as + // wasm-local := 0x00 i:uleb128 + dbg_info.appendSliceAssumeCapacity(&.{ + DW.OP.WASM_location, + DW.OP.WASM_local, + }); + leb128.writeULEB128(dbg_info.writer(), value) catch unreachable; + }, + .memory, .linker_load, => { From 3ec0520bac74cf750482abae0c8ce09344299613 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 2 Dec 2022 12:22:17 +0100 Subject: [PATCH 08/10] dwarf: use common DI union object for arg and var gen --- src/arch/aarch64/CodeGen.zig | 42 ++++++++++++++++-------------------- src/arch/arm/CodeGen.zig | 36 +++++++++++++++---------------- src/arch/riscv64/CodeGen.zig | 22 +++++++++++-------- src/arch/wasm/CodeGen.zig | 2 +- src/arch/x86_64/CodeGen.zig | 29 ++++++++++++------------- src/link/Dwarf.zig | 39 ++++++++++++++++----------------- 6 files changed, 83 insertions(+), 87 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index ae24178a5a..7bf0f99a84 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -185,28 +185,26 @@ const DbgInfoReloc = struct { const atom = function.getDbgInfoAtomPtr(); switch (function.debug_output) { - .dwarf => |dw| switch (reloc.mcv) { - .register => |reg| try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ - .register = reg.dwarfLocOp(), - }), - - .stack_offset, - .stack_argument_offset, - => |offset| { - const adjusted_offset = switch (reloc.mcv) { - .stack_offset => -@intCast(i32, offset), - .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), - else => unreachable, - }; - try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, .{ - .stack = .{ + .dwarf => |dw| { + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { + .register => |reg| .{ .register = reg.dwarfLocOp() }, + .stack_offset, + .stack_argument_offset, + => |offset| blk: { + const adjusted_offset = switch (reloc.mcv) { + .stack_offset => -@intCast(i32, offset), + .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), + else => unreachable, + }; + break :blk .{ .stack = .{ .fp_register = Register.x29.dwarfLocOpDeref(), .offset = adjusted_offset, - }, - }); - }, + } }; + }, + else => unreachable, // not a possible argument - else => unreachable, // not a possible argument + }; + try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, loc); }, .plan9 => {}, .none => {}, @@ -223,10 +221,8 @@ const DbgInfoReloc = struct { switch (function.debug_output) { .dwarf => |dw| { - const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) { - .register => |reg| .{ - .register = reg.dwarfLocOp(), - }, + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { + .register => |reg| .{ .register = reg.dwarfLocOp() }, .ptr_stack_offset, .stack_offset, .stack_argument_offset, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 066a82e5a2..0a19214e48 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -4036,26 +4036,26 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMe const atom = self.getDbgInfoAtom(); switch (self.debug_output) { - .dwarf => |dw| switch (mcv) { - .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ - .register = reg.dwarfLocOp(), - }), - .stack_offset, - .stack_argument_offset, - => { - const adjusted_stack_offset = switch (mcv) { - .stack_offset => |offset| -@intCast(i32, offset), - .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), - else => unreachable, - }; - try dw.genArgDbgInfo(name, ty, atom, .{ - .stack = .{ + .dwarf => |dw| { + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { + .register => |reg| .{ .register = reg.dwarfLocOp() }, + .stack_offset, + .stack_argument_offset, + => blk: { + const adjusted_stack_offset = switch (mcv) { + .stack_offset => |offset| -@intCast(i32, offset), + .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), + else => unreachable, + }; + break :blk .{ .stack = .{ .fp_register = DW.OP.breg11, .offset = adjusted_stack_offset, - }, - }); - }, - else => unreachable, // not a possible argument + } }; + }, + else => unreachable, // not a possible argument + + }; + try dw.genArgDbgInfo(name, ty, atom, loc); }, .plan9 => {}, .none => {}, diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 368c0ba71f..b2c7ac293f 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1602,17 +1602,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { return self.fail("TODO implement codegen airFieldParentPtr", .{}); } -fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { +fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; + const atom = self.getDbgIntoAtomPtr(); switch (self.debug_output) { .dwarf => |dw| switch (mcv) { @@ -1627,6 +1620,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32 } } +fn getDbgIntoAtomPtr(self: Self) *link.File.Dwarf.Atom { + const mod = self.bin_file.options.module.?; + const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); + const atom = switch (self.bin_file.tag) { + .elf => &fn_owner_decl.link.elf.dbg_info_atom, + .macho => &fn_owner_decl.link.macho.dbg_info_atom, + else => unreachable, + }; + return atom; +} + fn airArg(self: *Self, inst: Air.Inst.Index) !void { const arg_index = self.arg_index; self.arg_index += 1; diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ddb1803998..6584ad2041 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -5327,7 +5327,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { log.debug(" var name = ({s})", .{name}); const atom = func.getDbgInfoAtom(); - const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (operand) { + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (operand) { .local => |local| .{ .wasm_local = local.value }, else => blk: { log.debug("TODO generate debug info for {}", .{operand}); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 5d9e3ccb5e..b526743b2a 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3818,18 +3818,19 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { const atom = self.getDbgInfoAtomPtr(); switch (self.debug_output) { - .dwarf => |dw| switch (mcv) { - .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ - .register = reg.dwarfLocOp(), - }), - .stack_offset => |off| try dw.genArgDbgInfo(name, ty, atom, .{ - .stack = .{ - .fp_register = Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer - .offset = -off, + .dwarf => |dw| { + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { + .register => |reg| .{ .register = reg.dwarfLocOp() }, + .stack_offset => |off| .{ + .stack = .{ + // TODO handle -fomit-frame-pointer + .fp_register = Register.rbp.dwarfLocOpDeref(), + .offset = -off, + }, }, - }), - - else => unreachable, // not a valid function parameter + else => unreachable, // not a valid function parameter + }; + try dw.genArgDbgInfo(name, ty, atom, loc); }, .plan9 => {}, .none => {}, @@ -3852,10 +3853,8 @@ fn genVarDbgInfo( switch (self.debug_output) { .dwarf => |dw| { - const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (mcv) { - .register => |reg| .{ - .register = reg.dwarfLocOp(), - }, + const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { + .register => |reg| .{ .register = reg.dwarfLocOp() }, .ptr_stack_offset, .stack_offset, => |off| .{ .stack = .{ diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index feb2857322..8540b8a542 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -562,16 +562,27 @@ pub const DeclState = struct { } } + pub const DbgInfoLoc = union(enum) { + register: u8, + stack: struct { + fp_register: u8, + offset: i32, + }, + wasm_local: u32, + memory: u64, + linker_load: LinkerLoad, + immediate: u64, + undef, + none, + nop, + }; + pub fn genArgDbgInfo( self: *DeclState, name: [:0]const u8, ty: Type, atom: *Atom, - loc: union(enum) { - register: u8, - stack: struct { fp_register: u8, offset: i32 }, - wasm_local: u32, - }, + loc: DbgInfoLoc, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; const name_with_null = name.ptr[0 .. name.len + 1]; @@ -612,6 +623,7 @@ pub const DeclState = struct { }); leb128.writeULEB128(dbg_info.writer(), value) catch unreachable; }, + else => unreachable, } try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); @@ -621,28 +633,13 @@ pub const DeclState = struct { dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string } - pub const VarArgDbgInfoLoc = union(enum) { - register: u8, - stack: struct { - fp_register: u8, - offset: i32, - }, - wasm_local: u32, - memory: u64, - linker_load: LinkerLoad, - immediate: u64, - undef, - none, - nop, - }; - pub fn genVarDbgInfo( self: *DeclState, name: [:0]const u8, ty: Type, atom: *Atom, is_ptr: bool, - loc: VarArgDbgInfoLoc, + loc: DbgInfoLoc, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; const name_with_null = name.ptr[0 .. name.len + 1]; From 05962a4aa28eca701bb22c4b17d2f9ea236583f5 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 2 Dec 2022 12:23:01 +0100 Subject: [PATCH 09/10] x86: do not deref ptr type, let Dwart do it --- src/arch/x86_64/CodeGen.zig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index b526743b2a..8769b7ae61 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -4448,11 +4448,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { const name = self.air.nullTerminatedString(pl_op.payload); const tag = self.air.instructions.items(.tag)[inst]; - switch (tag) { - .dbg_var_ptr => try self.genVarDbgInfo(tag, ty.childType(), mcv, name), - .dbg_var_val => try self.genVarDbgInfo(tag, ty, mcv, name), - else => unreachable, - } + try self.genVarDbgInfo(tag, ty, mcv, name); return self.finishAir(inst, .dead, .{ operand, .none, .none }); } From bfd36cbf97bfa012e5c399c16578b8756782e1d8 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 2 Dec 2022 13:17:52 +0100 Subject: [PATCH 10/10] dwarf: pass linker Tag and owner Decl.Index instead of *Atom --- src/arch/aarch64/CodeGen.zig | 31 +++++++++++++++---------------- src/arch/arm/CodeGen.zig | 14 +------------- src/arch/riscv64/CodeGen.zig | 22 +++++++--------------- src/arch/sparc64/CodeGen.zig | 21 +++++++-------------- src/arch/wasm/CodeGen.zig | 12 ++---------- src/arch/x86_64/CodeGen.zig | 18 ++---------------- src/link/Dwarf.zig | 18 ++++++++++++++++-- 7 files changed, 50 insertions(+), 86 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 7bf0f99a84..9975e08ea9 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -182,8 +182,6 @@ const DbgInfoReloc = struct { } } fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { - const atom = function.getDbgInfoAtomPtr(); - switch (function.debug_output) { .dwarf => |dw| { const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { @@ -204,7 +202,13 @@ const DbgInfoReloc = struct { else => unreachable, // not a possible argument }; - try dw.genArgDbgInfo(reloc.name, reloc.ty, atom, loc); + try dw.genArgDbgInfo( + reloc.name, + reloc.ty, + function.bin_file.tag, + function.mod_fn.owner_decl, + loc, + ); }, .plan9 => {}, .none => {}, @@ -217,7 +221,6 @@ const DbgInfoReloc = struct { .dbg_var_val => false, else => unreachable, }; - const atom = function.getDbgInfoAtomPtr(); switch (function.debug_output) { .dwarf => |dw| { @@ -251,7 +254,14 @@ const DbgInfoReloc = struct { break :blk .nop; }, }; - try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, is_ptr, loc); + try dw.genVarDbgInfo( + reloc.name, + reloc.ty, + function.bin_file.tag, + function.mod_fn.owner_decl, + is_ptr, + loc, + ); }, .plan9 => {}, .none => {}, @@ -259,17 +269,6 @@ const DbgInfoReloc = struct { } }; -fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - return atom; -} - const Branch = struct { inst_table: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, MCValue) = .{}, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 0a19214e48..7a9e00b83f 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -4033,7 +4033,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMe const mcv = self.args[arg_index]; const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const atom = self.getDbgInfoAtom(); switch (self.debug_output) { .dwarf => |dw| { @@ -4055,24 +4054,13 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMe else => unreachable, // not a possible argument }; - try dw.genArgDbgInfo(name, ty, atom, loc); + try dw.genArgDbgInfo(name, ty, self.bin_file.tag, self.mod_fn.owner_decl, loc); }, .plan9 => {}, .none => {}, } } -fn getDbgInfoAtom(self: Self) *link.File.Dwarf.Atom { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - return atom; -} - fn airArg(self: *Self, inst: Air.Inst.Index) !void { const arg_index = self.arg_index; self.arg_index += 1; diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index b2c7ac293f..6a54ffeea2 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1605,13 +1605,16 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const atom = self.getDbgIntoAtomPtr(); switch (self.debug_output) { .dwarf => |dw| switch (mcv) { - .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ - .register = reg.dwarfLocOp(), - }), + .register => |reg| try dw.genArgDbgInfo( + name, + ty, + self.bin_file.tag, + self.mod_fn.owner_decl, + .{ .register = reg.dwarfLocOp() }, + ), .stack_offset => {}, else => {}, }, @@ -1620,17 +1623,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) } } -fn getDbgIntoAtomPtr(self: Self) *link.File.Dwarf.Atom { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - return atom; -} - fn airArg(self: *Self, inst: Air.Inst.Index) !void { const arg_index = self.arg_index; self.arg_index += 1; diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 66d14f755b..9f345767de 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -3255,29 +3255,22 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void { const ty = self.air.instructions.items(.data)[inst].ty; const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); - const atom = self.getDbgInfoAtomPtr(); switch (self.debug_output) { .dwarf => |dw| switch (mcv) { - .register => |reg| try dw.genArgDbgInfo(name, ty, atom, .{ - .register = reg.dwarfLocOp(), - }), + .register => |reg| try dw.genArgDbgInfo( + name, + ty, + self.bin_file.tag, + self.mod_fn.owner_decl, + .{ .register = reg.dwarfLocOp() }, + ), else => {}, }, else => {}, } } -fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - else => unreachable, - }; - return atom; -} - // TODO replace this to call to extern memcpy fn genInlineMemcpy( self: *Self, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 6584ad2041..c424c7b59d 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -2341,8 +2341,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .dwarf => |dwarf| { // TODO: Get the original arg index rather than wasm arg index const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, arg_index); - const atom = func.getDbgInfoAtom(); - try dwarf.genArgDbgInfo(name, arg_ty, atom, .{ + try dwarf.genArgDbgInfo(name, arg_ty, .wasm, func.mod_fn.owner_decl, .{ .wasm_local = arg.local.value, }); }, @@ -2352,12 +2351,6 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { func.finishAir(inst, arg, &.{}); } -fn getDbgInfoAtom(func: CodeGen) *link.File.Dwarf.Atom { - const mod = func.bin_file.base.options.module.?; - const fn_owner_decl = mod.declPtr(func.mod_fn.owner_decl); - return &fn_owner_decl.link.wasm.dbg_info_atom; -} - fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { const bin_op = func.air.instructions.items(.data)[inst].bin_op; if (func.liveness.isUnused(inst)) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs }); @@ -5326,7 +5319,6 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { const name = func.air.nullTerminatedString(pl_op.payload); log.debug(" var name = ({s})", .{name}); - const atom = func.getDbgInfoAtom(); const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (operand) { .local => |local| .{ .wasm_local = local.value }, else => blk: { @@ -5334,7 +5326,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { break :blk .nop; }, }; - try func.debug_output.dwarf.genVarDbgInfo(name, ty, atom, is_ptr, loc); + try func.debug_output.dwarf.genVarDbgInfo(name, ty, .wasm, func.mod_fn.owner_decl, is_ptr, loc); func.finishAir(inst, .none, &.{}); } diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 8769b7ae61..ae7cbc762d 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3815,8 +3815,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { } fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { - const atom = self.getDbgInfoAtomPtr(); - switch (self.debug_output) { .dwarf => |dw| { const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { @@ -3830,7 +3828,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { }, else => unreachable, // not a valid function parameter }; - try dw.genArgDbgInfo(name, ty, atom, loc); + try dw.genArgDbgInfo(name, ty, self.bin_file.tag, self.mod_fn.owner_decl, loc); }, .plan9 => {}, .none => {}, @@ -3849,7 +3847,6 @@ fn genVarDbgInfo( .dbg_var_val => false, else => unreachable, }; - const atom = self.getDbgInfoAtomPtr(); switch (self.debug_output) { .dwarf => |dw| { @@ -3871,24 +3868,13 @@ fn genVarDbgInfo( break :blk .nop; }, }; - try dw.genVarDbgInfo(name, ty, atom, is_ptr, loc); + try dw.genVarDbgInfo(name, ty, self.bin_file.tag, self.mod_fn.owner_decl, is_ptr, loc); }, .plan9 => {}, .none => {}, } } -fn getDbgInfoAtomPtr(self: Self) *link.File.Dwarf.Atom { - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - return atom; -} - fn airBreakpoint(self: *Self) !void { _ = try self.addInst(.{ .tag = .interrupt, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 8540b8a542..63ccb57e77 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -581,10 +581,12 @@ pub const DeclState = struct { self: *DeclState, name: [:0]const u8, ty: Type, - atom: *Atom, + tag: File.Tag, + owner_decl: Module.Decl.Index, loc: DbgInfoLoc, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; + const atom = self.getDbgInfoAtom(tag, owner_decl); const name_with_null = name.ptr[0 .. name.len + 1]; switch (loc) { @@ -637,11 +639,13 @@ pub const DeclState = struct { self: *DeclState, name: [:0]const u8, ty: Type, - atom: *Atom, + tag: File.Tag, + owner_decl: Module.Decl.Index, is_ptr: bool, loc: DbgInfoLoc, ) error{OutOfMemory}!void { const dbg_info = &self.dbg_info; + const atom = self.getDbgInfoAtom(tag, owner_decl); const name_with_null = name.ptr[0 .. name.len + 1]; try dbg_info.append(@enumToInt(AbbrevKind.variable)); const target = self.mod.getTarget(); @@ -774,6 +778,16 @@ pub const DeclState = struct { try self.addTypeRelocGlobal(atom, child_ty, @intCast(u32, index)); dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string } + + fn getDbgInfoAtom(self: *DeclState, tag: File.Tag, decl_index: Module.Decl.Index) *Atom { + const decl = self.mod.declPtr(decl_index); + return switch (tag) { + .elf => &decl.link.elf.dbg_info_atom, + .macho => &decl.link.macho.dbg_info_atom, + .wasm => &decl.link.wasm.dbg_info_atom, + else => unreachable, + }; + } }; pub const AbbrevEntry = struct {