authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-30 15:42:21+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-09 18:51:46+02:00
log8e1c220be257236565fb28d84dc56045f15be697
tree6715e0f845829c9e2a0ab3b25d0a75a866537417
parent941b6830b1831c4df5ba369088ff473a012a3b54

wasm: Add basic debug info references


4 files changed, 61 insertions(+), 2 deletions(-)

src/link.zig+2-1
...@@ -485,8 +485,9 @@ pub const File = struct {...@@ -485,8 +485,9 @@ pub const File = struct {
485 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),485 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
486 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),486 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
487 .c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl),487 .c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl),
488 .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclLineNumber(module, decl),
488 .plan9 => @panic("TODO: implement updateDeclLineNumber for plan9"),489 .plan9 => @panic("TODO: implement updateDeclLineNumber for plan9"),
489 .wasm, .spirv, .nvptx => {},490 .spirv, .nvptx => {},
490 }491 }
491 }492 }
492493
src/link/Dwarf.zig+6
...@@ -735,6 +735,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState...@@ -735,6 +735,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState
735 const atom = switch (self.tag) {735 const atom = switch (self.tag) {
736 .elf => &decl.link.elf.dbg_info_atom,736 .elf => &decl.link.elf.dbg_info_atom,
737 .macho => &decl.link.macho.dbg_info_atom,737 .macho => &decl.link.macho.dbg_info_atom,
738 .wasm => &decl.link.wasm.dbg_info_atom,
738 else => unreachable,739 else => unreachable,
739 };740 };
740 try decl_state.addTypeReloc(741 try decl_state.addTypeReloc(
...@@ -1250,6 +1251,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)...@@ -1250,6 +1251,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
1250 const file_pos = sect.offset + decl.fn_link.macho.off + self.getRelocDbgLineOff();1251 const file_pos = sect.offset + decl.fn_link.macho.off + self.getRelocDbgLineOff();
1251 try d_sym.file.pwriteAll(&data, file_pos);1252 try d_sym.file.pwriteAll(&data, file_pos);
1252 },1253 },
1254 .wasm => {
1255 const wasm_file = file.cast(File.Wasm).?;
1256 _ = wasm_file; // TODO, update .debug_line
1257 },
1253 else => unreachable,1258 else => unreachable,
1254 }1259 }
1255}1260}
...@@ -1285,6 +1290,7 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {...@@ -1285,6 +1290,7 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {
1285 const fn_link = switch (self.tag) {1290 const fn_link = switch (self.tag) {
1286 .elf => &decl.fn_link.elf,1291 .elf => &decl.fn_link.elf,
1287 .macho => &decl.fn_link.macho,1292 .macho => &decl.fn_link.macho,
1293 .wasm => &decl.fn_link.wasm.src_fn,
1288 else => unreachable,1294 else => unreachable,
1289 };1295 };
1290 _ = self.dbg_line_fn_free_list.remove(fn_link);1296 _ = self.dbg_line_fn_free_list.remove(fn_link);
src/link/Wasm.zig+48-1
...@@ -11,6 +11,7 @@ const log = std.log.scoped(.link);...@@ -11,6 +11,7 @@ const log = std.log.scoped(.link);
11const wasm = std.wasm;11const wasm = std.wasm;
1212
13const Atom = @import("Wasm/Atom.zig");13const Atom = @import("Wasm/Atom.zig");
14const Dwarf = @import("Dwarf.zig");
14const Module = @import("../Module.zig");15const Module = @import("../Module.zig");
15const Compilation = @import("../Compilation.zig");16const Compilation = @import("../Compilation.zig");
16const CodeGen = @import("../arch/wasm/CodeGen.zig");17const CodeGen = @import("../arch/wasm/CodeGen.zig");
...@@ -82,6 +83,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{},...@@ -82,6 +83,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{},
82segment_info: std.ArrayListUnmanaged(types.Segment) = .{},83segment_info: std.ArrayListUnmanaged(types.Segment) = .{},
83/// Deduplicated string table for strings used by symbols, imports and exports.84/// Deduplicated string table for strings used by symbols, imports and exports.
84string_table: StringTable = .{},85string_table: StringTable = .{},
86/// Debug information for wasm
87dwarf: ?Dwarf = null,
8588
86// Output sections89// Output sections
87/// Output type section90/// Output type section
...@@ -137,10 +140,15 @@ pub const Segment = struct {...@@ -137,10 +140,15 @@ pub const Segment = struct {
137};140};
138141
139pub const FnData = struct {142pub const FnData = struct {
143 /// Reference to the wasm type that represents this function.
140 type_index: u32,144 type_index: u32,
145 /// Contains debug information related to this function.
146 /// For Wasm, the offset is relative to the code-section.
147 src_fn: Dwarf.SrcFn,
141148
142 pub const empty: FnData = .{149 pub const empty: FnData = .{
143 .type_index = undefined,150 .type_index = undefined,
151 .src_fn = Dwarf.SrcFn.empty,
144 };152 };
145};153};
146154
...@@ -318,6 +326,11 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {...@@ -318,6 +326,11 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
318 },326 },
319 .name = undefined,327 .name = undefined,
320 };328 };
329
330 if (!options.strip and options.module != null) {
331 self.dwarf = Dwarf.init(gpa, .wasm, options.target);
332 }
333
321 const use_llvm = build_options.have_llvm and options.use_llvm;334 const use_llvm = build_options.have_llvm and options.use_llvm;
322 const use_stage1 = build_options.is_stage1 and options.use_stage1;335 const use_stage1 = build_options.is_stage1 and options.use_stage1;
323 if (use_llvm and !use_stage1) {336 if (use_llvm and !use_stage1) {
...@@ -479,6 +492,10 @@ pub fn deinit(self: *Wasm) void {...@@ -479,6 +492,10 @@ pub fn deinit(self: *Wasm) void {
479 self.exports.deinit(gpa);492 self.exports.deinit(gpa);
480493
481 self.string_table.deinit(gpa);494 self.string_table.deinit(gpa);
495
496 if (self.dwarf) |*dwarf| {
497 dwarf.deinit();
498 }
482}499}
483500
484pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {501pub 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...@@ -515,12 +532,19 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
515 if (build_options.have_llvm) {532 if (build_options.have_llvm) {
516 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);533 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
517 }534 }
535
536 const tracy = trace(@src());
537 defer tracy.end();
538
518 const decl_index = func.owner_decl;539 const decl_index = func.owner_decl;
519 const decl = mod.declPtr(decl_index);540 const decl = mod.declPtr(decl_index);
520 assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()541 assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()
521542
522 decl.link.wasm.clear();543 decl.link.wasm.clear();
523544
545 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl) else null;
546 defer if (decl_state) |*ds| ds.deinit();
547
524 var code_writer = std.ArrayList(u8).init(self.base.allocator);548 var code_writer = std.ArrayList(u8).init(self.base.allocator);
525 defer code_writer.deinit();549 defer code_writer.deinit();
526 const result = try codegen.generateFunction(550 const result = try codegen.generateFunction(
...@@ -530,7 +554,7 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -530,7 +554,7 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
530 air,554 air,
531 liveness,555 liveness,
532 &code_writer,556 &code_writer,
533 .none,557 if (decl_state) |*ds| .{ .dwarf = ds } else .none,
534 );558 );
535559
536 const code = switch (result) {560 const code = switch (result) {
...@@ -555,6 +579,9 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -555,6 +579,9 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
555 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);579 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
556 }580 }
557581
582 const tracy = trace(@src());
583 defer tracy.end();
584
558 const decl = mod.declPtr(decl_index);585 const decl = mod.declPtr(decl_index);
559 assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()586 assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes()
560587
...@@ -596,6 +623,20 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi...@@ -596,6 +623,20 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
596 return self.finishUpdateDecl(decl, code);623 return self.finishUpdateDecl(decl, code);
597}624}
598625
626pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) !void {
627 if (self.llvm_object) |_| return;
628 if (self.dwarf) |*dw| {
629 const tracy = trace(@src());
630 defer tracy.end();
631
632 const decl_name = try decl.getFullyQualifiedName(mod);
633 defer self.base.allocator.free(decl_name);
634
635 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
636 try dw.updateDeclLineNumber(&self.base, decl);
637 }
638}
639
599fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {640fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
600 if (code.len == 0) return;641 if (code.len == 0) return;
601 const mod = self.base.options.module.?;642 const mod = self.base.options.module.?;
...@@ -852,6 +893,12 @@ pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void {...@@ -852,6 +893,12 @@ pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void {
852 }893 }
853 _ = self.resolved_symbols.swapRemove(atom.symbolLoc());894 _ = self.resolved_symbols.swapRemove(atom.symbolLoc());
854 _ = self.symbol_atom.remove(atom.symbolLoc());895 _ = self.symbol_atom.remove(atom.symbolLoc());
896
897 if (self.dwarf) |*dwarf| {
898 dwarf.freeDecl(decl);
899 dwarf.freeAtom(&atom.dbg_info_atom);
900 }
901
855 atom.deinit(self.base.allocator);902 atom.deinit(self.base.allocator);
856}903}
857904
src/link/Wasm/Atom.zig+5
...@@ -4,6 +4,7 @@ const std = @import("std");...@@ -4,6 +4,7 @@ const std = @import("std");
4const types = @import("types.zig");4const types = @import("types.zig");
5const Wasm = @import("../Wasm.zig");5const Wasm = @import("../Wasm.zig");
6const Symbol = @import("Symbol.zig");6const Symbol = @import("Symbol.zig");
7const Dwarf = @import("../Dwarf.zig");
78
8const leb = std.leb;9const leb = std.leb;
9const log = std.log.scoped(.link);10const log = std.log.scoped(.link);
...@@ -38,6 +39,9 @@ prev: ?*Atom,...@@ -38,6 +39,9 @@ prev: ?*Atom,
38/// When the parent atom is being freed, it will also do so for all local atoms.39/// When the parent atom is being freed, it will also do so for all local atoms.
39locals: std.ArrayListUnmanaged(Atom) = .{},40locals: std.ArrayListUnmanaged(Atom) = .{},
4041
42/// Represents the debug Atom that holds all debug information of this Atom.
43dbg_info_atom: Dwarf.Atom,
44
41/// Represents a default empty wasm `Atom`45/// Represents a default empty wasm `Atom`
42pub const empty: Atom = .{46pub const empty: Atom = .{
43 .alignment = 0,47 .alignment = 0,
...@@ -47,6 +51,7 @@ pub const empty: Atom = .{...@@ -47,6 +51,7 @@ pub const empty: Atom = .{
47 .prev = null,51 .prev = null,
48 .size = 0,52 .size = 0,
49 .sym_index = 0,53 .sym_index = 0,
54 .dbg_info_atom = undefined,
50};55};
5156
52/// Frees all resources owned by this `Atom`.57/// Frees all resources owned by this `Atom`.