Commit 00016ab6a0

Jakub Konka <kubkon@jakubkonka.com>
2022-12-01 15:28:22
dwarf: extract common logic for generating func var dbg info
1 parent 7d0af63
Changed files (3)
src
arch
aarch64
x86_64
link
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) = .{},
 
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) {
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 {