Commit 8e1c220be2
src/link/Wasm/Atom.zig
@@ -4,6 +4,7 @@ const std = @import("std");
const types = @import("types.zig");
const Wasm = @import("../Wasm.zig");
const Symbol = @import("Symbol.zig");
+const Dwarf = @import("../Dwarf.zig");
const leb = std.leb;
const log = std.log.scoped(.link);
@@ -38,6 +39,9 @@ prev: ?*Atom,
/// When the parent atom is being freed, it will also do so for all local atoms.
locals: std.ArrayListUnmanaged(Atom) = .{},
+/// Represents the debug Atom that holds all debug information of this Atom.
+dbg_info_atom: Dwarf.Atom,
+
/// Represents a default empty wasm `Atom`
pub const empty: Atom = .{
.alignment = 0,
@@ -47,6 +51,7 @@ pub const empty: Atom = .{
.prev = null,
.size = 0,
.sym_index = 0,
+ .dbg_info_atom = undefined,
};
/// Frees all resources owned by this `Atom`.
src/link/Dwarf.zig
@@ -735,6 +735,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState
const atom = switch (self.tag) {
.elf => &decl.link.elf.dbg_info_atom,
.macho => &decl.link.macho.dbg_info_atom,
+ .wasm => &decl.link.wasm.dbg_info_atom,
else => unreachable,
};
try decl_state.addTypeReloc(
@@ -1250,6 +1251,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
const file_pos = sect.offset + decl.fn_link.macho.off + self.getRelocDbgLineOff();
try d_sym.file.pwriteAll(&data, file_pos);
},
+ .wasm => {
+ const wasm_file = file.cast(File.Wasm).?;
+ _ = wasm_file; // TODO, update .debug_line
+ },
else => unreachable,
}
}
@@ -1285,6 +1290,7 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {
const fn_link = switch (self.tag) {
.elf => &decl.fn_link.elf,
.macho => &decl.fn_link.macho,
+ .wasm => &decl.fn_link.wasm.src_fn,
else => unreachable,
};
_ = self.dbg_line_fn_free_list.remove(fn_link);
src/link/Wasm.zig
@@ -11,6 +11,7 @@ const log = std.log.scoped(.link);
const wasm = std.wasm;
const Atom = @import("Wasm/Atom.zig");
+const Dwarf = @import("Dwarf.zig");
const Module = @import("../Module.zig");
const Compilation = @import("../Compilation.zig");
const CodeGen = @import("../arch/wasm/CodeGen.zig");
@@ -82,6 +83,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{},
segment_info: std.ArrayListUnmanaged(types.Segment) = .{},
/// Deduplicated string table for strings used by symbols, imports and exports.
string_table: StringTable = .{},
+/// Debug information for wasm
+dwarf: ?Dwarf = null,
// Output sections
/// Output type section
@@ -137,10 +140,15 @@ pub const Segment = struct {
};
pub const FnData = struct {
+ /// Reference to the wasm type that represents this function.
type_index: u32,
+ /// Contains debug information related to this function.
+ /// For Wasm, the offset is relative to the code-section.
+ src_fn: Dwarf.SrcFn,
pub const empty: FnData = .{
.type_index = undefined,
+ .src_fn = Dwarf.SrcFn.empty,
};
};
@@ -318,6 +326,11 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
},
.name = undefined,
};
+
+ if (!options.strip and options.module != null) {
+ self.dwarf = Dwarf.init(gpa, .wasm, options.target);
+ }
+
const use_llvm = build_options.have_llvm and options.use_llvm;
const use_stage1 = build_options.is_stage1 and options.use_stage1;
if (use_llvm and !use_stage1) {
@@ -479,6 +492,10 @@ pub fn deinit(self: *Wasm) void {
self.exports.deinit(gpa);
self.string_table.deinit(gpa);
+
+ if (self.dwarf) |*dwarf| {
+ dwarf.deinit();
+ }
}
pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
@@ -515,12 +532,19 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
if (build_options.have_llvm) {
if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
}
+
+ const tracy = trace(@src());
+ defer tracy.end();
+
const decl_index = func.owner_decl;
const decl = mod.declPtr(decl_index);
assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()
decl.link.wasm.clear();
+ var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl) else null;
+ defer if (decl_state) |*ds| ds.deinit();
+
var code_writer = std.ArrayList(u8).init(self.base.allocator);
defer code_writer.deinit();
const result = try codegen.generateFunction(
@@ -530,7 +554,7 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
air,
liveness,
&code_writer,
- .none,
+ if (decl_state) |*ds| .{ .dwarf = ds } else .none,
);
const code = switch (result) {
@@ -555,6 +579,9 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
}
+ const tracy = trace(@src());
+ defer tracy.end();
+
const decl = mod.declPtr(decl_index);
assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()
@@ -596,6 +623,20 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
return self.finishUpdateDecl(decl, code);
}
+pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) !void {
+ if (self.llvm_object) |_| return;
+ if (self.dwarf) |*dw| {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const decl_name = try decl.getFullyQualifiedName(mod);
+ defer self.base.allocator.free(decl_name);
+
+ log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
+ try dw.updateDeclLineNumber(&self.base, decl);
+ }
+}
+
fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
if (code.len == 0) return;
const mod = self.base.options.module.?;
@@ -852,6 +893,12 @@ pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void {
}
_ = self.resolved_symbols.swapRemove(atom.symbolLoc());
_ = self.symbol_atom.remove(atom.symbolLoc());
+
+ if (self.dwarf) |*dwarf| {
+ dwarf.freeDecl(decl);
+ dwarf.freeAtom(&atom.dbg_info_atom);
+ }
+
atom.deinit(self.base.allocator);
}
src/link.zig
@@ -485,8 +485,9 @@ pub const File = struct {
.elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
.macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
.c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl),
+ .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclLineNumber(module, decl),
.plan9 => @panic("TODO: implement updateDeclLineNumber for plan9"),
- .wasm, .spirv, .nvptx => {},
+ .spirv, .nvptx => {},
}
}