authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-08 17:16:58+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-09 18:51:46+02:00
log62453496bac17f13e1e129de5cf08accddc02302
treeaa540817a86ae174af39bf1ea4803271fafdc23b
parent2ae2ac33d9ddd1fb181e08a811d97b1bf238bced

wasm: Write nops for padding debug info


4 files changed, 119 insertions(+), 12 deletions(-)

src/arch/wasm/CodeGen.zig+3-3
......@@ -1362,7 +1362,6 @@ fn isByRef(ty: Type, target: std.Target) bool {
13621362 .NoReturn,
13631363 .Void,
13641364 .Bool,
1365 .Float,
13661365 .ErrorSet,
13671366 .Fn,
13681367 .Enum,
......@@ -1375,7 +1374,8 @@ fn isByRef(ty: Type, target: std.Target) bool {
13751374 .Frame,
13761375 .Union,
13771376 => return ty.hasRuntimeBitsIgnoreComptime(),
1378 .Int => return if (ty.intInfo(target).bits > 64) true else false,
1377 .Int => return ty.intInfo(target).bits > 64,
1378 .Float => return ty.floatBits(target) > 64,
13791379 .ErrorUnion => {
13801380 const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime();
13811381 const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime();
......@@ -4326,7 +4326,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index, is_ptr: bool) !WValue {
43264326 try self.addDbgInfoTypeReloc(op_ty);
43274327 dbg_info.appendSliceAssumeCapacity(name);
43284328 dbg_info.appendAssumeCapacity(0);
4329 try return WValue{ .none = {} };
4329 return WValue{ .none = {} };
43304330}
43314331
43324332fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue {
src/link/Dwarf.zig+101-5
......@@ -851,6 +851,10 @@ pub fn commitDeclState(
851851 const file_pos = debug_line_sect.offset + src_fn.off;
852852 try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
853853 },
854 .wasm => {
855 const wasm_file = file.cast(File.Wasm).?;
856 writeDbgLineNopsBuffered(wasm_file.debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
857 },
854858 else => unreachable,
855859 }
856860 // TODO Look at the free list before appending at the end.
......@@ -972,9 +976,16 @@ pub fn commitDeclState(
972976 mem.set(u8, debug_line.items[segment.size..], 0);
973977 }
974978 segment.size = needed_size;
979 debug_line.items.len = needed_size;
975980 }
976981 const offset = segment.offset + src_fn.off;
977 mem.copy(u8, debug_line.items[offset..], dbg_line_buffer.items);
982 writeDbgLineNopsBuffered(
983 debug_line.items,
984 offset,
985 prev_padding_size,
986 dbg_line_buffer.items,
987 next_padding_size,
988 );
978989 },
979990 else => unreachable,
980991 }
......@@ -1114,7 +1125,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
11141125 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
11151126 },
11161127 .wasm => {
1117 log.debug(" todo: updateDeclDebugInfoAllocation for Wasm: {d}", .{atom.len});
1128 const wasm_file = file.cast(File.Wasm).?;
1129 writeDbgInfoNopsBuffered(wasm_file.debug_info.items, atom.off, 0, &.{0}, atom.len, false);
11181130 },
11191131 else => unreachable,
11201132 }
......@@ -1253,9 +1265,17 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
12531265 mem.set(u8, debug_info.items[segment.size..], 0);
12541266 }
12551267 segment.size = needed_size;
1268 debug_info.items.len = needed_size;
12561269 }
12571270 const offset = segment.offset + atom.off;
1258 mem.copy(u8, debug_info.items[offset..], dbg_info_buf);
1271 writeDbgInfoNopsBuffered(
1272 debug_info.items,
1273 offset,
1274 prev_padding_size,
1275 dbg_info_buf,
1276 next_padding_size,
1277 trailing_zero,
1278 );
12591279 },
12601280 else => unreachable,
12611281 }
......@@ -1643,7 +1663,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
16431663 },
16441664 .wasm => {
16451665 const wasm_file = file.cast(File.Wasm).?;
1646 mem.copy(u8, wasm_file.debug_info.items, di_buf.items);
1666 writeDbgInfoNopsBuffered(wasm_file.debug_info.items, 0, 0, di_buf.items, jmp_amt, false);
16471667 },
16481668 else => unreachable,
16491669 }
......@@ -1738,6 +1758,45 @@ fn pwriteDbgLineNops(
17381758 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
17391759}
17401760
1761fn writeDbgLineNopsBuffered(
1762 buf: []u8,
1763 offset: u32,
1764 prev_padding_size: usize,
1765 content: []const u8,
1766 next_padding_size: usize,
1767) void {
1768 assert(buf.len >= content.len + prev_padding_size + next_padding_size);
1769 const tracy = trace(@src());
1770 defer tracy.end();
1771
1772 const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 };
1773 {
1774 var padding_left = prev_padding_size;
1775 if (padding_left % 2 != 0) {
1776 buf[offset - padding_left ..][0..3].* = three_byte_nop;
1777 padding_left -= 3;
1778 }
1779
1780 while (padding_left > 0) : (padding_left -= 1) {
1781 buf[offset - padding_left] = DW.LNS.negate_stmt;
1782 }
1783 }
1784
1785 mem.copy(u8, buf[offset..], content);
1786
1787 {
1788 var padding_left = next_padding_size;
1789 if (padding_left % 2 != 0) {
1790 buf[offset + content.len + padding_left ..][0..3].* = three_byte_nop;
1791 padding_left -= 3;
1792 }
1793
1794 while (padding_left > 0) : (padding_left -= 1) {
1795 buf[offset + content.len + padding_left] = DW.LNS.negate_stmt;
1796 }
1797 }
1798}
1799
17411800/// Writes to the file a buffer, prefixed and suffixed by the specified number of
17421801/// bytes of padding.
17431802fn pwriteDbgInfoNops(
......@@ -1810,6 +1869,38 @@ fn pwriteDbgInfoNops(
18101869 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
18111870}
18121871
1872fn writeDbgInfoNopsBuffered(
1873 buf: []u8,
1874 offset: u32,
1875 prev_padding_size: usize,
1876 content: []const u8,
1877 next_padding_size: usize,
1878 trailing_zero: bool,
1879) void {
1880 assert(buf.len >= content.len + prev_padding_size + next_padding_size + @boolToInt(trailing_zero));
1881 const tracy = trace(@src());
1882 defer tracy.end();
1883
1884 {
1885 var padding_left = prev_padding_size;
1886 while (padding_left > 0) : (padding_left -= 1) {
1887 buf[offset - padding_left] = @enumToInt(AbbrevKind.pad1);
1888 }
1889 }
1890
1891 mem.copy(u8, buf[offset..], content);
1892 {
1893 var padding_left = next_padding_size;
1894 while (padding_left > 0) : (padding_left -= 1) {
1895 buf[offset + content.len + padding_left] = @enumToInt(AbbrevKind.pad1);
1896 }
1897 }
1898
1899 if (trailing_zero) {
1900 buf[offset + content.len + next_padding_size] = 0;
1901 }
1902}
1903
18131904pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
18141905 const target_endian = self.target.cpu.arch.endian();
18151906 const init_len_size: usize = if (self.tag == .macho)
......@@ -1909,6 +2000,11 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
19092000 const file_pos = debug_aranges_sect.offset;
19102001 try d_sym.file.pwriteAll(di_buf.items, file_pos);
19112002 },
2003 .wasm => {
2004 const wasm_file = file.cast(File.Wasm).?;
2005 try wasm_file.debug_aranges.resize(wasm_file.base.allocator, needed_size);
2006 mem.copy(u8, wasm_file.debug_aranges.items, di_buf.items);
2007 },
19122008 else => unreachable,
19132009 }
19142010}
......@@ -2030,7 +2126,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
20302126 },
20312127 .wasm => {
20322128 const wasm_file = file.cast(File.Wasm).?;
2033 mem.copy(u8, wasm_file.debug_line.items, di_buf.items);
2129 writeDbgLineNopsBuffered(wasm_file.debug_line.items, 0, 0, di_buf.items, jmp_amt);
20342130 },
20352131 else => unreachable,
20362132 }
src/link/Wasm.zig+13-4
......@@ -97,6 +97,8 @@ debug_info: std.ArrayListUnmanaged(u8) = .{},
9797debug_line: std.ArrayListUnmanaged(u8) = .{},
9898/// Contains all bytes for the '.debug_abbrev' section
9999debug_abbrev: std.ArrayListUnmanaged(u8) = .{},
100/// Contains all bytes for the '.debug_ranges' section
101debug_aranges: std.ArrayListUnmanaged(u8) = .{},
100102
101103// Output sections
102104/// Output type section
......@@ -513,6 +515,7 @@ pub fn deinit(self: *Wasm) void {
513515 self.debug_info.deinit(gpa);
514516 self.debug_line.deinit(gpa);
515517 self.debug_abbrev.deinit(gpa);
518 self.debug_aranges.deinit(gpa);
516519}
517520
518521pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
......@@ -1928,6 +1931,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
19281931 }
19291932
19301933 // Code section
1934 var code_section_size: u32 = 0;
19311935 if (self.code_section_index) |code_index| {
19321936 const header_offset = try reserveVecSectionHeader(file);
19331937 const writer = file.writer();
......@@ -1940,11 +1944,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
19401944 try writer.writeAll(atom.code.items);
19411945 atom = atom.next orelse break;
19421946 }
1947
1948 code_section_size = @intCast(u32, (try file.getPos()) - header_offset - header_size);
19431949 try writeVecSectionHeader(
19441950 file,
19451951 header_offset,
19461952 .code,
1947 @intCast(u32, (try file.getPos()) - header_offset - header_size),
1953 code_section_size,
19481954 @intCast(u32, self.functions.items.len),
19491955 );
19501956 code_section_index = section_count;
......@@ -2032,13 +2038,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
20322038 } else if (!self.base.options.strip) {
20332039 if (self.dwarf) |*dwarf| {
20342040 if (self.debug_info_index != null) {
2035 _ = dwarf;
20362041 try dwarf.writeDbgAbbrev(&self.base);
2037 try dwarf.writeDbgInfoHeader(&self.base, mod, 0, 0);
2042 // for debug info and ranges, the address is always 0,
2043 // as locations are always offsets relative to 'code' section.
2044 try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size);
2045 try dwarf.writeDbgAranges(&self.base, 0, code_section_size);
20382046 try dwarf.writeDbgLineHeader(&self.base, mod);
20392047
20402048 try emitDebugSection(file, self.debug_info.items, ".debug_info");
2041 try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev"); // TODO
2049 try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges");
2050 try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev");
20422051 try emitDebugSection(file, self.debug_line.items, ".debug_line");
20432052 try emitDebugSection(file, dwarf.strtab.items, ".debug_str");
20442053 }
test/behavior/ptrcast.zig+2
......@@ -134,6 +134,7 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
134134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
135135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
136136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
137138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields
138139
139140 // Test lowering a field ptr
......@@ -158,6 +159,7 @@ test "lower reinterpreted comptime field ptr" {
158159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
159160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
160161 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
161163
162164 // Test lowering a field ptr
163165 comptime var bytes align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };