diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 0c259d404407d396e80ceaf329bf69a0abf055cf..7f18b297730f166451eb8826c1d222079ed4ccc6 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -249,6 +249,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { }; const is_obj = comp.config.output_mode == .Obj; const allow_undefined = is_obj or wasm.import_symbols; + const zcu_references = if (comp.zcu) |zcu| try zcu.resolveReferences() else null; const entry_name = if (wasm.entry_resolution.isNavOrUnresolved(wasm)) wasm.entry_name else .none; @@ -1223,6 +1224,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { try emitTagIndexFunction(wasm, binary_bytes, ip_index); }, else => { + if (!zcu_references.?.contains(.wrap(.{ .func = ip_index }))) { + try binary_bytes.appendSlice(gpa, &.{ + 0, // no locals + @backingInt(std.wasm.Opcode.@"unreachable"), + @backingInt(std.wasm.Opcode.end), + }); + continue; + } const func = i.value(wasm).function; const mir: Mir = .{ .instructions = wasm.mir_instructions.slice().subslice(func.instructions_off, func.instructions_len), diff --git a/test/incremental/remove_function_with_changed_callee b/test/incremental/remove_function_with_changed_callee new file mode 100644 index 0000000000000000000000000000000000000000..31e962124dfb10374fd9b0dd70bc743edde143bd --- /dev/null +++ b/test/incremental/remove_function_with_changed_callee @@ -0,0 +1,50 @@ +#update=initial version +#file=main.zig +const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.io(); + +const A = enum(u32) { + zero, + one, +}; + +fn foo() !void { + try bar(.zero); +} + +fn bar(a: A) !void { + const msg = switch (a) { + .zero => "0", + .one => "1", + }; + try std.Io.File.stdout().writeStreamingAll(io, msg); +} + +pub fn main() !void { + try foo(); +} +#expect_stdout="0" +#update=remove foo and change bar wasm function type +#file=main.zig +//! This update must preserve `bar` `InternPool.Index` value, while changing its wasm function type. +//! If `foo` code is preserved in the binary without any changes, wasm type checking will fail. +const std = @import("std"); +const io = std.Io.Threaded.global_single_threaded.io(); + +const A = enum(u64) { + zero, + one, +}; + +fn bar(a: A) !void { + const msg = switch (a) { + .zero => "0", + .one => "1", + }; + try std.Io.File.stdout().writeStreamingAll(io, msg); +} + +pub fn main() !void { + try bar(.one); +} +#expect_stdout="1"