Commit 8fea84f77e

Jakub Konka <kubkon@jakubkonka.com>
2022-12-01 20:55:55
dwarf: move Wasm specific dwarf gen out of codegen
1 parent 17ab40f
Changed files (2)
src
arch
link
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
-            // <opcode> 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, &.{});
 }
 
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
+                // <opcode> 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,
             => {