authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-02 21:41:47+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-09 18:51:46+02:00
log9b6b7034c20a0089b88e58b5142c91b2d26bcef8
tree83d346c2e35e381bf019430205b0937f072177bd
parentf76027220042d965278184088f1f04b6c8430bcb

wasm: Flush debug information + commit decl

This implements parts to commit a decl's debug information into a linear memory buffer. The goal is to write this buffer at once after we finished linking.

2 files changed, 77 insertions(+), 1 deletions(-)

src/link/Dwarf.zig+28-1
...@@ -818,6 +818,7 @@ pub fn commitDeclState(...@@ -818,6 +818,7 @@ pub fn commitDeclState(
818 const src_fn = switch (self.tag) {818 const src_fn = switch (self.tag) {
819 .elf => &decl.fn_link.elf,819 .elf => &decl.fn_link.elf,
820 .macho => &decl.fn_link.macho,820 .macho => &decl.fn_link.macho,
821 .wasm => &decl.fn_link.wasm.src_fn,
821 else => unreachable, // TODO822 else => unreachable, // TODO
822 };823 };
823 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);824 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
...@@ -958,6 +959,26 @@ pub fn commitDeclState(...@@ -958,6 +959,26 @@ pub fn commitDeclState(
958 next_padding_size,959 next_padding_size,
959 );960 );
960 },961 },
962 .wasm => {
963 const wasm_file = file.cast(File.Wasm).?;
964 const segment_index = try wasm_file.getDebugLineIndex();
965 const segment = &wasm_file.segments.items[segment_index];
966 const debug_atom = wasm_file.atoms.get(segment_index).?;
967 if (needed_size != segment.size) {
968 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
969 if (needed_size > segment.size) {
970 log.debug(" allocating {d} bytes for debug line information", .{needed_size - segment.size});
971 try debug_atom.code.resize(self.allocator, needed_size);
972 std.mem.set(u8, debug_atom.code.items[segment.size..], 0);
973 }
974 debug_atom.size = needed_size;
975 segment.size = needed_size;
976 }
977 // since we can tighly pack the debug lines, wasm does not require
978 // us to pad with Nops.
979 const offset = segment.offset + src_fn.off;
980 std.mem.copy(u8, debug_atom.code.items[offset..], dbg_line_buffer.items);
981 },
961 else => unreachable,982 else => unreachable,
962 }983 }
963984
...@@ -973,6 +994,7 @@ pub fn commitDeclState(...@@ -973,6 +994,7 @@ pub fn commitDeclState(
973 const atom = switch (self.tag) {994 const atom = switch (self.tag) {
974 .elf => &decl.link.elf.dbg_info_atom,995 .elf => &decl.link.elf.dbg_info_atom,
975 .macho => &decl.link.macho.dbg_info_atom,996 .macho => &decl.link.macho.dbg_info_atom,
997 .wasm => &decl.link.wasm.dbg_info_atom,
976 else => unreachable,998 else => unreachable,
977 };999 };
9781000
...@@ -1094,6 +1116,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3...@@ -1094,6 +1116,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
1094 const file_pos = debug_info_sect.offset + atom.off;1116 const file_pos = debug_info_sect.offset + atom.off;
1095 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);1117 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
1096 },1118 },
1119 .wasm => {},
1097 else => unreachable,1120 else => unreachable,
1098 }1121 }
1099 // TODO Look at the free list before appending at the end.1122 // TODO Look at the free list before appending at the end.
...@@ -1253,7 +1276,11 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)...@@ -1253,7 +1276,11 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
1253 },1276 },
1254 .wasm => {1277 .wasm => {
1255 const wasm_file = file.cast(File.Wasm).?;1278 const wasm_file = file.cast(File.Wasm).?;
1256 _ = wasm_file; // TODO, update .debug_line1279 const segment_index = wasm_file.getDebugLineIndex() catch unreachable;
1280 const segment = wasm_file.segments.items[segment_index];
1281 const offset = segment.offset + decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
1282 const debug_atom = wasm_file.atoms.get(segment_index).?;
1283 std.mem.copy(u8, debug_atom.code.items[offset..], &data);
1257 },1284 },
1258 else => unreachable,1285 else => unreachable,
1259 }1286 }
src/link/Wasm.zig+49
...@@ -62,6 +62,10 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},...@@ -62,6 +62,10 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
62/// Represents the index into `segments` where the 'code' section62/// Represents the index into `segments` where the 'code' section
63/// lives.63/// lives.
64code_section_index: ?u32 = null,64code_section_index: ?u32 = null,
65/// The index of the segment representing the custom '.debug_info' section.
66debug_info_index: ?u32 = null,
67/// The index of the segment representing the custom '.debug_line' section.
68debug_line_index: ?u32 = null,
65/// The count of imported functions. This number will be appended69/// The count of imported functions. This number will be appended
66/// to the function indexes as their index starts at the lowest non-extern function.70/// to the function indexes as their index starts at the lowest non-extern function.
67imported_functions_count: u32 = 0,71imported_functions_count: u32 = 0,
...@@ -311,6 +315,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -311,6 +315,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
311 .init = .{ .i32_const = 0 },315 .init = .{ .i32_const = 0 },
312 };316 };
313 }317 }
318
314 return wasm_bin;319 return wasm_bin;
315}320}
316321
...@@ -566,6 +571,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes...@@ -566,6 +571,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
566 },571 },
567 };572 };
568573
574 if (self.dwarf) |*dwarf| {
575 try dwarf.commitDeclState(
576 &self.base,
577 mod,
578 decl,
579 // Actual value will be written after relocation
580 0,
581 code.len,
582 &decl_state.?,
583 );
584 }
569 return self.finishUpdateDecl(decl, code);585 return self.finishUpdateDecl(decl, code);
570}586}
571587
...@@ -1517,6 +1533,35 @@ fn populateErrorNameTable(self: *Wasm) !void {...@@ -1517,6 +1533,35 @@ fn populateErrorNameTable(self: *Wasm) !void {
1517 try self.parseAtom(names_atom, .data);1533 try self.parseAtom(names_atom, .data);
1518}1534}
15191535
1536pub fn getDebugInfoIndex(self: *Wasm) !u32 {
1537 assert(self.dwarf != null);
1538 return self.debug_info_index orelse {
1539 self.debug_info_index = @intCast(u32, self.segments.items.len);
1540 const segment = try self.segments.addOne(self.base.allocator);
1541 segment.* = .{
1542 .size = 0,
1543 .offset = 0,
1544 // debug sections always have alignment '1'
1545 .alignment = 1,
1546 };
1547 return self.debug_info_index.?;
1548 };
1549}
1550
1551pub fn getDebugLineIndex(self: *Wasm) !u32 {
1552 assert(self.dwarf != null);
1553 return self.debug_line_index orelse {
1554 self.debug_line_index = @intCast(u32, self.segments.items.len);
1555 const segment = try self.segments.addOne(self.base.allocator);
1556 segment.* = .{
1557 .size = 0,
1558 .offset = 0,
1559 .alignment = 1,
1560 };
1561 return self.debug_line_index.?;
1562 };
1563}
1564
1520fn resetState(self: *Wasm) void {1565fn resetState(self: *Wasm) void {
1521 for (self.segment_info.items) |*segment_info| {1566 for (self.segment_info.items) |*segment_info| {
1522 self.base.allocator.free(segment_info.name);1567 self.base.allocator.free(segment_info.name);
...@@ -1542,6 +1587,7 @@ fn resetState(self: *Wasm) void {...@@ -1542,6 +1587,7 @@ fn resetState(self: *Wasm) void {
1542 self.atoms.clearRetainingCapacity();1587 self.atoms.clearRetainingCapacity();
1543 self.symbol_atom.clearRetainingCapacity();1588 self.symbol_atom.clearRetainingCapacity();
1544 self.code_section_index = null;1589 self.code_section_index = null;
1590 self.debug_info_index = null;
1545}1591}
15461592
1547pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {1593pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
...@@ -1636,6 +1682,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1636,6 +1682,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
1636 try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self);1682 try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self);
1637 }1683 }
16381684
1685 if (self.dwarf) |*dwarf| {
1686 try dwarf.flushModule(&self.base, self.base.options.module.?);
1687 }
1639 try self.allocateAtoms();1688 try self.allocateAtoms();
1640 try self.setupMemory();1689 try self.setupMemory();
1641 self.mapFunctionTable();1690 self.mapFunctionTable();