Commit 33b2f4f382
Changed files (3)
lib
std
dwarf
src
arch
wasm
link
lib/std/dwarf/OP.zig
@@ -205,3 +205,9 @@ pub const HP_unmod_range = 0xe5;
pub const HP_tls = 0xe6;
// PGI (STMicroelectronics) extensions.
pub const PGI_omp_thread_num = 0xf8;
+// Wasm extensions.
+pub const WASM_location = 0xed;
+pub const WASM_local = 0x00;
+pub const WASM_global = 0x01;
+pub const WASM_global_u32 = 0x03;
+pub const WASM_operand_stack = 0x02;
src/arch/wasm/CodeGen.zig
@@ -546,6 +546,8 @@ block_depth: u32 = 0,
air: Air,
liveness: Liveness,
gpa: mem.Allocator,
+debug_output: codegen.DebugInfoOutput,
+mod_fn: *const Module.Fn,
/// Table to save `WValue`'s generated by an `Air.Inst`
values: ValueTable,
/// Mapping from Air.Inst.Index to block ids
@@ -856,6 +858,8 @@ pub fn generate(
.locals = .{},
.target = bin_file.options.target,
.bin_file = bin_file.cast(link.File.Wasm).?,
+ .debug_output = debug_output,
+ .mod_fn = func,
};
defer code_gen.deinit();
@@ -1022,6 +1026,23 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool
}
}
+/// 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(self: *Self, ty: Type) !void {
+ switch (self.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 = &self.decl.link.wasm.dbg_info_atom;
+ try dwarf.addTypeReloc(atom, ty, @intCast(u32, index), null);
+ },
+ .plan9 => unreachable,
+ .none => {},
+ }
+}
+
/// Lowers a Zig type and its value based on a given calling convention to ensure
/// it matches the ABI.
fn lowerArg(self: *Self, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void {
@@ -1873,7 +1894,8 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
}
fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
- const arg = self.args[self.arg_index];
+ const arg_index = self.arg_index;
+ const arg = self.args[arg_index];
const cc = self.decl.ty.fnInfo().cc;
if (cc == .C) {
const ty = self.air.typeOfIndex(inst);
@@ -1886,6 +1908,32 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
} else {
self.arg_index += 1;
}
+
+ switch (self.debug_output) {
+ .dwarf => |dwarf| {
+ // TODO: Get the original arg index rather than wasm arg index
+ const name = self.mod_fn.getParamName(arg_index);
+ const leb_size = link.File.Wasm.getULEB128Size(arg.local);
+ 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,
+ });
+ leb.writeULEB128(dbg_info.writer(), arg.local) catch unreachable;
+ try self.addDbgInfoTypeReloc(self.air.typeOfIndex(inst));
+ dbg_info.appendSliceAssumeCapacity(name);
+ dbg_info.appendAssumeCapacity(0);
+ },
+ else => {},
+ }
return arg;
}
src/link/Wasm.zig
@@ -2668,7 +2668,7 @@ fn emitSegmentInfo(self: *Wasm, file: fs.File, arena: Allocator) !void {
try file.writevAll(&iovecs);
}
-fn getULEB128Size(uint_value: anytype) u32 {
+pub fn getULEB128Size(uint_value: anytype) u32 {
const T = @TypeOf(uint_value);
const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
var value = @intCast(U, uint_value);