wasm: Add basic debug info references

This commit is contained in:
Luuk de Gram 2022-04-30 15:42:21 +02:00
parent 941b6830b1
commit 8e1c220be2
4 changed files with 61 additions and 2 deletions

View File

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

View File

@ -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);

View File

@ -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);
}

View File

@ -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`.