authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-17 19:41:05+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-19 19:58:49+02:00
logbe08d2bdbd2f64ccb9ef0f985a57a4bf89b9aebb
tree727d36adc443701b6aa8221797dc082f3670a290
parent2193f7c4a2b56f67bf07d27c3f715cf3969c392f
signature Commit is signed but in an unrecognized format.

wasm: Fix unreachable paths

When the last instruction is a debug instruction, the type of it is void. Similarly for 'noreturn' emit an 'unreachable' instruction to tell the wasm-validator the path cannot be reached. Also respect the '--strip' flag in the self-hosted wasm linker and not emit a 'name' section when the flag is set to `true`.

3 files changed, 37 insertions(+), 4 deletions(-)

lib/std/debug.zig+34-2
...@@ -113,11 +113,14 @@ pub fn detectTTYConfig() TTY.Config {...@@ -113,11 +113,14 @@ pub fn detectTTYConfig() TTY.Config {
113/// TODO multithreaded awareness113/// TODO multithreaded awareness
114pub fn dumpCurrentStackTrace(start_addr: ?usize) void {114pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
115 nosuspend {115 nosuspend {
116 const stderr = io.getStdErr().writer();
117 if (comptime builtin.target.isWasm()) {116 if (comptime builtin.target.isWasm()) {
118 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;117 if (native_os == .wasi) {
118 const stderr = io.getStdErr().writer();
119 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
120 }
119 return;121 return;
120 }122 }
123 const stderr = io.getStdErr().writer();
121 if (builtin.strip_debug_info) {124 if (builtin.strip_debug_info) {
122 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;125 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
123 return;126 return;
...@@ -138,6 +141,13 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {...@@ -138,6 +141,13 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
138/// TODO multithreaded awareness141/// TODO multithreaded awareness
139pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {142pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
140 nosuspend {143 nosuspend {
144 if (comptime builtin.target.isWasm()) {
145 if (native_os == .wasi) {
146 const stderr = io.getStdErr().writer();
147 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
148 }
149 return;
150 }
141 const stderr = io.getStdErr().writer();151 const stderr = io.getStdErr().writer();
142 if (builtin.strip_debug_info) {152 if (builtin.strip_debug_info) {
143 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;153 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
...@@ -208,6 +218,13 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT...@@ -208,6 +218,13 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
208/// TODO multithreaded awareness218/// TODO multithreaded awareness
209pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {219pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
210 nosuspend {220 nosuspend {
221 if (comptime builtin.target.isWasm()) {
222 if (native_os == .wasi) {
223 const stderr = io.getStdErr().writer();
224 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
225 }
226 return;
227 }
211 const stderr = io.getStdErr().writer();228 const stderr = io.getStdErr().writer();
212 if (builtin.strip_debug_info) {229 if (builtin.strip_debug_info) {
213 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;230 stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
...@@ -1138,6 +1155,8 @@ pub const DebugInfo = struct {...@@ -1138,6 +1155,8 @@ pub const DebugInfo = struct {
1138 return self.lookupModuleWin32(address);1155 return self.lookupModuleWin32(address);
1139 } else if (native_os == .haiku) {1156 } else if (native_os == .haiku) {
1140 return self.lookupModuleHaiku(address);1157 return self.lookupModuleHaiku(address);
1158 } else if (comptime builtin.target.isWasm()) {
1159 return self.lookupModuleWasm(address);
1141 } else {1160 } else {
1142 return self.lookupModuleDl(address);1161 return self.lookupModuleDl(address);
1143 }1162 }
...@@ -1353,6 +1372,12 @@ pub const DebugInfo = struct {...@@ -1353,6 +1372,12 @@ pub const DebugInfo = struct {
1353 _ = address;1372 _ = address;
1354 @panic("TODO implement lookup module for Haiku");1373 @panic("TODO implement lookup module for Haiku");
1355 }1374 }
1375
1376 fn lookupModuleWasm(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1377 _ = self;
1378 _ = address;
1379 @panic("TODO implement lookup module for Wasm");
1380 }
1356};1381};
13571382
1358pub const ModuleDebugInfo = switch (native_os) {1383pub const ModuleDebugInfo = switch (native_os) {
...@@ -1632,6 +1657,13 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1632,6 +1657,13 @@ pub const ModuleDebugInfo = switch (native_os) {
1632 return getSymbolFromDwarf(relocated_address, &self.dwarf);1657 return getSymbolFromDwarf(relocated_address, &self.dwarf);
1633 }1658 }
1634 },1659 },
1660 .wasi => struct {
1661 pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
1662 _ = self;
1663 _ = address;
1664 return SymbolInfo{};
1665 }
1666 },
1635 else => DW.DwarfInfo,1667 else => DW.DwarfInfo,
1636};1668};
16371669
src/arch/wasm/CodeGen.zig+2-1
...@@ -871,7 +871,8 @@ fn genFunc(self: *Self) InnerError!void {...@@ -871,7 +871,8 @@ fn genFunc(self: *Self) InnerError!void {
871 // we emit an unreachable instruction to tell the stack validator that part will never be reached.871 // we emit an unreachable instruction to tell the stack validator that part will never be reached.
872 if (func_type.returns.len != 0 and self.air.instructions.len > 0) {872 if (func_type.returns.len != 0 and self.air.instructions.len > 0) {
873 const inst = @intCast(u32, self.air.instructions.len - 1);873 const inst = @intCast(u32, self.air.instructions.len - 1);
874 if (self.air.typeOfIndex(inst).isNoReturn()) {874 const last_inst_ty = self.air.typeOfIndex(inst);
875 if (!last_inst_ty.hasRuntimeBitsIgnoreComptime() or last_inst_ty.isNoReturn()) {
875 try self.addTag(.@"unreachable");876 try self.addTag(.@"unreachable");
876 }877 }
877 }878 }
src/link/Wasm.zig+1-1
...@@ -1897,7 +1897,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1897,7 +1897,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
1897 if (data_section_index) |data_index| {1897 if (data_section_index) |data_index| {
1898 try self.emitDataRelocations(file, arena, data_index, symbol_table);1898 try self.emitDataRelocations(file, arena, data_index, symbol_table);
1899 }1899 }
1900 } else {1900 } else if (!self.base.options.strip) {
1901 try self.emitNameSection(file, arena);1901 try self.emitNameSection(file, arena);
1902 }1902 }
1903}1903}