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 {...@@ -1362,7 +1362,6 @@ fn isByRef(ty: Type, target: std.Target) bool {
1362 .NoReturn,1362 .NoReturn,
1363 .Void,1363 .Void,
1364 .Bool,1364 .Bool,
1365 .Float,
1366 .ErrorSet,1365 .ErrorSet,
1367 .Fn,1366 .Fn,
1368 .Enum,1367 .Enum,
...@@ -1375,7 +1374,8 @@ fn isByRef(ty: Type, target: std.Target) bool {...@@ -1375,7 +1374,8 @@ fn isByRef(ty: Type, target: std.Target) bool {
1375 .Frame,1374 .Frame,
1376 .Union,1375 .Union,
1377 => return ty.hasRuntimeBitsIgnoreComptime(),1376 => 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,
1379 .ErrorUnion => {1379 .ErrorUnion => {
1380 const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime();1380 const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime();
1381 const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime();1381 const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime();
...@@ -4326,7 +4326,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index, is_ptr: bool) !WValue {...@@ -4326,7 +4326,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index, is_ptr: bool) !WValue {
4326 try self.addDbgInfoTypeReloc(op_ty);4326 try self.addDbgInfoTypeReloc(op_ty);
4327 dbg_info.appendSliceAssumeCapacity(name);4327 dbg_info.appendSliceAssumeCapacity(name);
4328 dbg_info.appendAssumeCapacity(0);4328 dbg_info.appendAssumeCapacity(0);
4329 try return WValue{ .none = {} };4329 return WValue{ .none = {} };
4330}4330}
43314331
4332fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue {4332fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !WValue {
src/link/Dwarf.zig+101-5
...@@ -851,6 +851,10 @@ pub fn commitDeclState(...@@ -851,6 +851,10 @@ pub fn commitDeclState(
851 const file_pos = debug_line_sect.offset + src_fn.off;851 const file_pos = debug_line_sect.offset + src_fn.off;
852 try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);852 try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
853 },853 },
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 },
854 else => unreachable,858 else => unreachable,
855 }859 }
856 // TODO Look at the free list before appending at the end.860 // TODO Look at the free list before appending at the end.
...@@ -972,9 +976,16 @@ pub fn commitDeclState(...@@ -972,9 +976,16 @@ pub fn commitDeclState(
972 mem.set(u8, debug_line.items[segment.size..], 0);976 mem.set(u8, debug_line.items[segment.size..], 0);
973 }977 }
974 segment.size = needed_size;978 segment.size = needed_size;
979 debug_line.items.len = needed_size;
975 }980 }
976 const offset = segment.offset + src_fn.off;981 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 );
978 },989 },
979 else => unreachable,990 else => unreachable,
980 }991 }
...@@ -1114,7 +1125,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3...@@ -1114,7 +1125,8 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
1114 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);1125 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
1115 },1126 },
1116 .wasm => {1127 .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);
1118 },1130 },
1119 else => unreachable,1131 else => unreachable,
1120 }1132 }
...@@ -1253,9 +1265,17 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co...@@ -1253,9 +1265,17 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
1253 mem.set(u8, debug_info.items[segment.size..], 0);1265 mem.set(u8, debug_info.items[segment.size..], 0);
1254 }1266 }
1255 segment.size = needed_size;1267 segment.size = needed_size;
1268 debug_info.items.len = needed_size;
1256 }1269 }
1257 const offset = segment.offset + atom.off;1270 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 );
1259 },1279 },
1260 else => unreachable,1280 else => unreachable,
1261 }1281 }
...@@ -1643,7 +1663,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6...@@ -1643,7 +1663,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
1643 },1663 },
1644 .wasm => {1664 .wasm => {
1645 const wasm_file = file.cast(File.Wasm).?;1665 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);
1647 },1667 },
1648 else => unreachable,1668 else => unreachable,
1649 }1669 }
...@@ -1738,6 +1758,45 @@ fn pwriteDbgLineNops(...@@ -1738,6 +1758,45 @@ fn pwriteDbgLineNops(
1738 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);1758 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
1739}1759}
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
1741/// Writes to the file a buffer, prefixed and suffixed by the specified number of1800/// Writes to the file a buffer, prefixed and suffixed by the specified number of
1742/// bytes of padding.1801/// bytes of padding.
1743fn pwriteDbgInfoNops(1802fn pwriteDbgInfoNops(
...@@ -1810,6 +1869,38 @@ fn pwriteDbgInfoNops(...@@ -1810,6 +1869,38 @@ fn pwriteDbgInfoNops(
1810 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);1869 try file.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
1811}1870}
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
1813pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {1904pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
1814 const target_endian = self.target.cpu.arch.endian();1905 const target_endian = self.target.cpu.arch.endian();
1815 const init_len_size: usize = if (self.tag == .macho)1906 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 {...@@ -1909,6 +2000,11 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
1909 const file_pos = debug_aranges_sect.offset;2000 const file_pos = debug_aranges_sect.offset;
1910 try d_sym.file.pwriteAll(di_buf.items, file_pos);2001 try d_sym.file.pwriteAll(di_buf.items, file_pos);
1911 },2002 },
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 },
1912 else => unreachable,2008 else => unreachable,
1913 }2009 }
1914}2010}
...@@ -2030,7 +2126,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {...@@ -2030,7 +2126,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
2030 },2126 },
2031 .wasm => {2127 .wasm => {
2032 const wasm_file = file.cast(File.Wasm).?;2128 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);
2034 },2130 },
2035 else => unreachable,2131 else => unreachable,
2036 }2132 }
src/link/Wasm.zig+13-4
...@@ -97,6 +97,8 @@ debug_info: std.ArrayListUnmanaged(u8) = .{},...@@ -97,6 +97,8 @@ debug_info: std.ArrayListUnmanaged(u8) = .{},
97debug_line: std.ArrayListUnmanaged(u8) = .{},97debug_line: std.ArrayListUnmanaged(u8) = .{},
98/// Contains all bytes for the '.debug_abbrev' section98/// Contains all bytes for the '.debug_abbrev' section
99debug_abbrev: std.ArrayListUnmanaged(u8) = .{},99debug_abbrev: std.ArrayListUnmanaged(u8) = .{},
100/// Contains all bytes for the '.debug_ranges' section
101debug_aranges: std.ArrayListUnmanaged(u8) = .{},
100102
101// Output sections103// Output sections
102/// Output type section104/// Output type section
...@@ -513,6 +515,7 @@ pub fn deinit(self: *Wasm) void {...@@ -513,6 +515,7 @@ pub fn deinit(self: *Wasm) void {
513 self.debug_info.deinit(gpa);515 self.debug_info.deinit(gpa);
514 self.debug_line.deinit(gpa);516 self.debug_line.deinit(gpa);
515 self.debug_abbrev.deinit(gpa);517 self.debug_abbrev.deinit(gpa);
518 self.debug_aranges.deinit(gpa);
516}519}
517520
518pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {521pub 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...@@ -1928,6 +1931,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
1928 }1931 }
19291932
1930 // Code section1933 // Code section
1934 var code_section_size: u32 = 0;
1931 if (self.code_section_index) |code_index| {1935 if (self.code_section_index) |code_index| {
1932 const header_offset = try reserveVecSectionHeader(file);1936 const header_offset = try reserveVecSectionHeader(file);
1933 const writer = file.writer();1937 const writer = file.writer();
...@@ -1940,11 +1944,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1940,11 +1944,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
1940 try writer.writeAll(atom.code.items);1944 try writer.writeAll(atom.code.items);
1941 atom = atom.next orelse break;1945 atom = atom.next orelse break;
1942 }1946 }
1947
1948 code_section_size = @intCast(u32, (try file.getPos()) - header_offset - header_size);
1943 try writeVecSectionHeader(1949 try writeVecSectionHeader(
1944 file,1950 file,
1945 header_offset,1951 header_offset,
1946 .code,1952 .code,
1947 @intCast(u32, (try file.getPos()) - header_offset - header_size),1953 code_section_size,
1948 @intCast(u32, self.functions.items.len),1954 @intCast(u32, self.functions.items.len),
1949 );1955 );
1950 code_section_index = section_count;1956 code_section_index = section_count;
...@@ -2032,13 +2038,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2032,13 +2038,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2032 } else if (!self.base.options.strip) {2038 } else if (!self.base.options.strip) {
2033 if (self.dwarf) |*dwarf| {2039 if (self.dwarf) |*dwarf| {
2034 if (self.debug_info_index != null) {2040 if (self.debug_info_index != null) {
2035 _ = dwarf;
2036 try dwarf.writeDbgAbbrev(&self.base);2041 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);
2038 try dwarf.writeDbgLineHeader(&self.base, mod);2046 try dwarf.writeDbgLineHeader(&self.base, mod);
20392047
2040 try emitDebugSection(file, self.debug_info.items, ".debug_info");2048 try emitDebugSection(file, self.debug_info.items, ".debug_info");
2041 try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev"); // TODO2049 try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges");
2050 try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev");
2042 try emitDebugSection(file, self.debug_line.items, ".debug_line");2051 try emitDebugSection(file, self.debug_line.items, ".debug_line");
2043 try emitDebugSection(file, dwarf.strtab.items, ".debug_str");2052 try emitDebugSection(file, dwarf.strtab.items, ".debug_str");
2044 }2053 }
test/behavior/ptrcast.zig+2
...@@ -134,6 +134,7 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {...@@ -134,6 +134,7 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields138 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields
138139
139 // Test lowering a field ptr140 // Test lowering a field ptr
...@@ -158,6 +159,7 @@ test "lower reinterpreted comptime field ptr" {...@@ -158,6 +159,7 @@ test "lower reinterpreted comptime field ptr" {
158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
161163
162 // Test lowering a field ptr164 // Test lowering a field ptr
163 comptime var bytes align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };165 comptime var bytes align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };