| ... | ... | @@ -11,6 +11,7 @@ const log = std.log.scoped(.link); |
| 11 | 11 | const wasm = std.wasm; |
| 12 | 12 | |
| 13 | 13 | const Atom = @import("Wasm/Atom.zig"); |
| 14 | const Dwarf = @import("Dwarf.zig"); |
| 14 | 15 | const Module = @import("../Module.zig"); |
| 15 | 16 | const Compilation = @import("../Compilation.zig"); |
| 16 | 17 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); |
| ... | ... | @@ -82,6 +83,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{}, |
| 82 | 83 | segment_info: std.ArrayListUnmanaged(types.Segment) = .{}, |
| 83 | 84 | /// Deduplicated string table for strings used by symbols, imports and exports. |
| 84 | 85 | string_table: StringTable = .{}, |
| 86 | /// Debug information for wasm |
| 87 | dwarf: ?Dwarf = null, |
| 85 | 88 | |
| 86 | 89 | // Output sections |
| 87 | 90 | /// Output type section |
| ... | ... | @@ -137,10 +140,15 @@ pub const Segment = struct { |
| 137 | 140 | }; |
| 138 | 141 | |
| 139 | 142 | pub const FnData = struct { |
| 143 | /// Reference to the wasm type that represents this function. |
| 140 | 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, |
| 141 | 148 | |
| 142 | 149 | pub const empty: FnData = .{ |
| 143 | 150 | .type_index = undefined, |
| 151 | .src_fn = Dwarf.SrcFn.empty, |
| 144 | 152 | }; |
| 145 | 153 | }; |
| 146 | 154 | |
| ... | ... | @@ -318,6 +326,11 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { |
| 318 | 326 | }, |
| 319 | 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 | 334 | const use_llvm = build_options.have_llvm and options.use_llvm; |
| 322 | 335 | const use_stage1 = build_options.is_stage1 and options.use_stage1; |
| 323 | 336 | if (use_llvm and !use_stage1) { |
| ... | ... | @@ -479,6 +492,10 @@ pub fn deinit(self: *Wasm) void { |
| 479 | 492 | self.exports.deinit(gpa); |
| 480 | 493 | |
| 481 | 494 | self.string_table.deinit(gpa); |
| 495 | |
| 496 | if (self.dwarf) |*dwarf| { |
| 497 | dwarf.deinit(); |
| 498 | } |
| 482 | 499 | } |
| 483 | 500 | |
| 484 | 501 | 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 |
| 515 | 532 | if (build_options.have_llvm) { |
| 516 | 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 | 539 | const decl_index = func.owner_decl; |
| 519 | 540 | const decl = mod.declPtr(decl_index); |
| 520 | 541 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() |
| 521 | 542 | |
| 522 | 543 | decl.link.wasm.clear(); |
| 523 | 544 | |
| 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 | 548 | var code_writer = std.ArrayList(u8).init(self.base.allocator); |
| 525 | 549 | defer code_writer.deinit(); |
| 526 | 550 | const result = try codegen.generateFunction( |
| ... | ... | @@ -530,7 +554,7 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes |
| 530 | 554 | air, |
| 531 | 555 | liveness, |
| 532 | 556 | &code_writer, |
| 533 | | .none, |
| 557 | if (decl_state) |*ds| .{ .dwarf = ds } else .none, |
| 534 | 558 | ); |
| 535 | 559 | |
| 536 | 560 | const code = switch (result) { |
| ... | ... | @@ -555,6 +579,9 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi |
| 555 | 579 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index); |
| 556 | 580 | } |
| 557 | 581 | |
| 582 | const tracy = trace(@src()); |
| 583 | defer tracy.end(); |
| 584 | |
| 558 | 585 | const decl = mod.declPtr(decl_index); |
| 559 | 586 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() |
| 560 | 587 | |
| ... | ... | @@ -596,6 +623,20 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi |
| 596 | 623 | return self.finishUpdateDecl(decl, code); |
| 597 | 624 | } |
| 598 | 625 | |
| 626 | pub 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 | |
| 599 | 640 | fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 600 | 641 | if (code.len == 0) return; |
| 601 | 642 | const mod = self.base.options.module.?; |
| ... | ... | @@ -852,6 +893,12 @@ pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void { |
| 852 | 893 | } |
| 853 | 894 | _ = self.resolved_symbols.swapRemove(atom.symbolLoc()); |
| 854 | 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 | 902 | atom.deinit(self.base.allocator); |
| 856 | 903 | } |
| 857 | 904 | |