dwarf: move Wasm specific dwarf gen out of codegen

This commit is contained in:
Jakub Konka 2022-12-01 20:55:55 +01:00
parent 17ab40f755
commit 8fea84f77e
2 changed files with 61 additions and 74 deletions

View File

@ -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, &.{});
}

View File

@ -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,
=> {