Commit aeaffd42f6

Jakub Konka <kubkon@jakubkonka.com>
2022-08-12 11:55:38
x86: fix generating debug info for variables
Add handling for these additional `MCValue`s: * `.immediate` - lower to `DW.OP.consts` or `DW.OP.constu` depending on signedness followed by popping off the DWARF stack with `DW.OP.stack_value` * `.undef` - lower to `DW.OP.implicit_value` * `.none` - lower to `DW.OP.lit0` followed by popping off the DWARF stack with `DW.OP.stack_value` For any remaining unhandled case, we generate `DW.OP.nop` in order not to mess up remaining DWARF info.
1 parent f2f1bb7
Changed files (2)
src
arch
link
src/arch/x86_64/CodeGen.zig
@@ -4370,6 +4370,7 @@ fn genVarDbgInfo(
         .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| {
@@ -4390,7 +4391,6 @@ fn genVarDbgInfo(
                     dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
                 },
                 .memory, .got_load, .direct_load => {
-                    const endian = self.target.cpu.arch.endian();
                     const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
                     const is_ptr = switch (tag) {
                         .dbg_var_ptr => true,
@@ -4425,7 +4425,53 @@ fn genVarDbgInfo(
                         else => {},
                     }
                 },
+                .immediate => |x| {
+                    const signedness: std.builtin.Signedness = blk: {
+                        if (ty.zigTypeTag() != .Int) break :blk .unsigned;
+                        break :blk ty.intInfo(self.target.*).signedness;
+                    };
+                    try dbg_info.ensureUnusedCapacity(2);
+                    const fixup = dbg_info.items.len;
+                    dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
+                        1,
+                        switch (signedness) {
+                            .signed => DW.OP.consts,
+                            .unsigned => DW.OP.constu,
+                        },
+                    });
+                    switch (signedness) {
+                        .signed => try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)),
+                        .unsigned => 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});
                 },
             }
src/link/Dwarf.zig
@@ -102,7 +102,7 @@ pub const DeclState = struct {
     }
 
     pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void {
-        log.debug("{x}: target sym @{d}, via GOT {}", .{ offset, target, is_ptr });
+        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,
             .target = target,
@@ -135,7 +135,7 @@ pub const DeclState = struct {
                 .@"type" = ty,
                 .offset = undefined,
             });
-            log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });
+            log.debug("%{d}: {}", .{ sym_index, ty.fmtDebug() });
             try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{
                 .mod = self.mod,
             });
@@ -143,7 +143,7 @@ pub const DeclState = struct {
                 .mod = self.mod,
             }).?;
         };
-        log.debug("{x}: @{d} + 0", .{ offset, resolv });
+        log.debug("{x}: %{d} + 0", .{ offset, resolv });
         try self.abbrev_relocs.append(self.gpa, .{
             .target = resolv,
             .atom = atom,
@@ -1056,6 +1056,7 @@ pub fn commitDeclState(
                 break :blk false;
             };
             if (deferred) {
+                log.debug("resolving %{d} deferred until flush", .{target});
                 try self.global_abbrev_relocs.append(gpa, .{
                     .target = null,
                     .offset = reloc.offset,
@@ -1063,10 +1064,12 @@ pub fn commitDeclState(
                     .addend = reloc.addend,
                 });
             } else {
+                const value = symbol.atom.off + symbol.offset + reloc.addend;
+                log.debug("{x}: [() => {x}] (%{d}, '{}')", .{ reloc.offset, value, target, ty.fmtDebug() });
                 mem.writeInt(
                     u32,
                     dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
-                    symbol.atom.off + symbol.offset + reloc.addend,
+                    value,
                     target_endian,
                 );
             }