diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bac4d4e8..32c85156 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v1 with: - version: 0.9.1 + version: master - run: zig build test testsuite: runs-on: ubuntu-latest @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v1 with: - version: 0.9.1 + version: master - run: zig build --build-file test/build.zig --prefix ./ - run: cp bin/testrunner testrunner - run: cp test/testsuite-generated/* ./ @@ -101,5 +101,5 @@ jobs: - uses: actions/checkout@v2 - uses: goto-bus-stop/setup-zig@v1 with: - version: 0.9.1 + version: master - run: zig fmt --check src/*.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4c82b07c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +zig-cache +zig-out diff --git a/README.md b/README.md index f8870627..63043794 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ pub fn main() !void { ### Compile-time -- Zig 0.9.1 +- Zig 0.10.0 ### Run-time @@ -93,4 +93,4 @@ zig build --build-file test/build.zig --prefix ./ ``` sh test/run-generated.sh -``` \ No newline at end of file +``` diff --git a/examples/fib/src/fib.wasm b/examples/fib/src/fib.wasm new file mode 100644 index 00000000..55f4ed90 Binary files /dev/null and b/examples/fib/src/fib.wasm differ diff --git a/examples/fib/src/fib.zig b/examples/fib/src/fib.zig index 64e22cff..985a9a84 100644 --- a/examples/fib/src/fib.zig +++ b/examples/fib/src/fib.zig @@ -15,7 +15,7 @@ pub fn main() !void { const alloc = arena.allocator(); - const bytes = @embedFile("../../../test/fib.wasm"); + const bytes = @embedFile("fib.wasm"); var store: Store = Store.init(alloc); diff --git a/src/function.zig b/src/function.zig index 3d209300..2562a21d 100644 --- a/src/function.zig +++ b/src/function.zig @@ -47,7 +47,7 @@ pub const Function = union(enum) { instance: usize, }, host_function: struct { - func: fn (*Interpreter) WasmError!void, + func: *const fn (*Interpreter) WasmError!void, params: []const ValueType, results: []const ValueType, }, diff --git a/src/instruction.zig b/src/instruction.zig index 2768de73..dbb7f7f9 100644 --- a/src/instruction.zig +++ b/src/instruction.zig @@ -566,8 +566,8 @@ pub const ParseIterator = struct { if (block_type >= 0) { const func_type = self.module.types.list.items[@intCast(usize, block_type)]; - block_params = try math.cast(u16, func_type.params.len); - block_returns = try math.cast(u16, func_type.results.len); + block_params = math.cast(u16, func_type.params.len) orelse return error.FailedCast; + block_returns = math.cast(u16, func_type.results.len) orelse return error.FailedCast; try self.validator.validateBlock(func_type.params, func_type.results); } else { if (block_type == -0x40) { @@ -599,8 +599,8 @@ pub const ParseIterator = struct { var block_returns: u16 = if (block_type == -0x40) 0 else 1; if (block_type >= 0) { const func_type = self.module.types.list.items[@intCast(usize, block_type)]; - block_params = try math.cast(u16, func_type.params.len); - block_returns = try math.cast(u16, func_type.results.len); + block_params = math.cast(u16, func_type.params.len) orelse return error.FailedCast; + block_returns = math.cast(u16, func_type.results.len) orelse return error.FailedCast; try self.validator.validateLoop(func_type.params, func_type.results); } else { if (block_type == -0x40) { @@ -621,7 +621,7 @@ pub const ParseIterator = struct { .loop = .{ .param_arity = block_params, .return_arity = block_params, - .branch_target = try math.cast(u32, self.code_ptr), + .branch_target = math.cast(u32, self.code_ptr) orelse return error.FailedCast, }, }; }, @@ -637,8 +637,8 @@ pub const ParseIterator = struct { var block_returns: u16 = if (block_type == -0x40) 0 else 1; if (block_type >= 0) { const func_type = self.module.types.list.items[@intCast(usize, block_type)]; - block_params = try math.cast(u16, func_type.params.len); - block_returns = try math.cast(u16, func_type.results.len); + block_params = math.cast(u16, func_type.params.len) orelse return error.FailedCast; + block_returns = math.cast(u16, func_type.results.len) orelse return error.FailedCast; try self.validator.validateIf(func_type.params, func_type.results); } else { if (block_type == -0x40) { @@ -673,7 +673,7 @@ pub const ParseIterator = struct { .param_arity = b.param_arity, .return_arity = b.return_arity, .branch_target = 0, - .else_ip = try math.cast(u32, self.code_ptr + 1), + .else_ip = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, }, }; }, @@ -688,16 +688,16 @@ pub const ParseIterator = struct { const parsed_code_offset = try self.popContinuationStack(); switch (self.parsed.items[parsed_code_offset]) { - .block => |*b| b.branch_target = try math.cast(u32, self.code_ptr + 1), + .block => |*b| b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, .loop => {}, .@"if" => |*b| { - b.branch_target = try math.cast(u32, self.code_ptr + 1); + b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, .if_no_else => |*b| { // We have an if with no else, check that this works arity-wise and replace with fast if if (b.param_arity -% b.return_arity != 0) return error.ValidatorElseBranchExpected; - b.branch_target = try math.cast(u32, self.code_ptr + 1); + b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, else => return error.UnexpectedInstruction, } diff --git a/src/interpreter.zig b/src/interpreter.zig index d8ceaff6..6656965c 100644 --- a/src/interpreter.zig +++ b/src/interpreter.zig @@ -83,7 +83,7 @@ pub const Interpreter = struct { } fn nop(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn block(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -98,7 +98,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn loop(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -114,7 +114,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"if"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -130,13 +130,13 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, if (condition == 0) meta.else_ip else ip + 1, code, err }); + return dispatch(self, if (condition == 0) meta.else_ip else ip + 1, code, err); } fn @"else"(self: *Interpreter, _: usize, code: []Instruction, err: *?WasmError) void { const label = self.popLabel(); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, label.branch_target, code, err }); + return dispatch(self, label.branch_target, code, err); } fn if_no_else(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -144,7 +144,7 @@ pub const Interpreter = struct { const condition = self.popOperand(u32); if (condition == 0) { - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, meta.branch_target, code, err }); + return dispatch(self, meta.branch_target, code, err); } else { // We are inside the if branch self.pushLabel(Label{ @@ -155,20 +155,20 @@ pub const Interpreter = struct { err.* = e; return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } } fn end(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { _ = self.popLabel(); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn br(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const next_ip = self.branch(code[ip].br); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, next_ip, code, err }); + return dispatch(self, next_ip, code, err); } fn br_if(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -176,7 +176,7 @@ pub const Interpreter = struct { const next_ip = if (condition == 0) ip + 1 else self.branch(code[ip].br_if); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, next_ip, code, err }); + return dispatch(self, next_ip, code, err); } fn br_table(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -187,7 +187,7 @@ pub const Interpreter = struct { const next_ip = if (i >= ls.len) self.branch(meta.ln) else self.branch(ls[i]); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, next_ip, code, err }); + return dispatch(self, next_ip, code, err); } fn @"return"(self: *Interpreter, _: usize, _: []Instruction, err: *?WasmError) void { @@ -213,7 +213,7 @@ pub const Interpreter = struct { const previous_frame = self.peekFrame(); self.inst = previous_frame.inst; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, label.branch_target, previous_frame.inst.module.parsed_code.items, err }); + return dispatch(self, label.branch_target, previous_frame.inst.module.parsed_code.items, err); } fn call(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -273,7 +273,7 @@ pub const Interpreter = struct { }, } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, next_ip, self.inst.module.parsed_code.items, err }); + return dispatch(self, next_ip, self.inst.module.parsed_code.items, err); } fn call_indirect(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -362,7 +362,7 @@ pub const Interpreter = struct { }, } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, next_ip, self.inst.module.parsed_code.items, err }); + return dispatch(self, next_ip, self.inst.module.parsed_code.items, err); } fn fast_call(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -398,12 +398,12 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, f.start, code, err }); + return dispatch(self, f.start, code, err); } fn drop(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { _ = self.popAnyOperand(); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn select(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -417,7 +417,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c2); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"local.get"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -427,7 +427,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, frame.locals[local_index]); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"local.set"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -436,7 +436,7 @@ pub const Interpreter = struct { const frame = self.peekFrame(); frame.locals[local_index] = self.popOperand(u64); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"local.tee"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -445,7 +445,7 @@ pub const Interpreter = struct { const frame = self.peekFrame(); frame.locals[local_index] = self.peekOperand(); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"global.get"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -458,7 +458,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, global.value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"global.set"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -472,7 +472,7 @@ pub const Interpreter = struct { global.value = value; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.load"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -493,7 +493,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -514,7 +514,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.load"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -535,7 +535,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.load"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -556,7 +556,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.load8_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -577,7 +577,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.load8_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -598,7 +598,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.load16_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -619,7 +619,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.load16_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -640,7 +640,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load8_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -661,7 +661,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load8_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -682,7 +682,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load16_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -703,7 +703,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load16_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -724,7 +724,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -745,7 +745,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.load32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -766,7 +766,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, value); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.store"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -786,7 +786,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.store"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -806,7 +806,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.store"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -826,7 +826,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.store"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -846,7 +846,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.store8"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -866,7 +866,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.store16"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -886,7 +886,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.store8"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -906,7 +906,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.store16"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -926,7 +926,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.store32"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -946,7 +946,7 @@ pub const Interpreter = struct { return; }; - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"memory.size"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -957,7 +957,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @intCast(u32, memory.data.items.len)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"memory.grow"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -973,7 +973,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.const"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -981,7 +981,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, instr.@"i32.const"); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.const"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -989,7 +989,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, instr.@"i64.const"); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.const"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -997,7 +997,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, instr.@"f32.const"); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.const"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1005,7 +1005,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, instr.@"f64.const"); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.eqz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1013,7 +1013,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 == 0) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.eq"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1022,7 +1022,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 == c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.ne"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1031,7 +1031,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 != c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.lt_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1040,7 +1040,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.lt_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1049,7 +1049,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.gt_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1058,7 +1058,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.gt_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1067,7 +1067,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.le_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1076,7 +1076,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.le_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1085,7 +1085,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.ge_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1094,7 +1094,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.ge_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1103,7 +1103,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.eqz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1111,7 +1111,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 == 0) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.eq"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1120,7 +1120,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.ne"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1129,7 +1129,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.lt_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1138,7 +1138,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.lt_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1147,7 +1147,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.gt_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1156,7 +1156,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.gt_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1165,7 +1165,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.le_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1174,7 +1174,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.le_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1183,7 +1183,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.ge_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1192,7 +1192,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.ge_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1201,7 +1201,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.eq"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1210,7 +1210,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.ne"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1219,7 +1219,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.lt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1228,7 +1228,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.gt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1237,7 +1237,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.le"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1246,7 +1246,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.ge"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1255,7 +1255,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.eq"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1264,7 +1264,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.ne"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1273,7 +1273,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.lt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1282,7 +1282,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.gt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1291,7 +1291,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.le"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1300,7 +1300,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.ge"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1309,28 +1309,28 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.clz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u32); - self.pushOperandNoCheck(u32, @clz(u32, c1)); + self.pushOperandNoCheck(u32, @clz(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.ctz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u32); - self.pushOperandNoCheck(u32, @ctz(u32, c1)); + self.pushOperandNoCheck(u32, @ctz(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.popcnt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u32); - self.pushOperandNoCheck(u32, @popCount(u32, c1)); + self.pushOperandNoCheck(u32, @popCount(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.add"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1339,7 +1339,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 +% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.sub"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1348,7 +1348,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 -% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.mul"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1357,7 +1357,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 *% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.div_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1371,7 +1371,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, div); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.div_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1385,7 +1385,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, div); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.rem_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1404,7 +1404,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, rem); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.rem_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1418,7 +1418,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, rem); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.and"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1427,7 +1427,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 & c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.or"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1436,7 +1436,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 | c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.xor"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1445,7 +1445,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, c1 ^ c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.shl"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1454,7 +1454,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, math.shl(u32, c1, c2 % 32)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.shr_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1468,7 +1468,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, math.shr(i32, c1, mod)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.shr_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1477,7 +1477,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, math.shr(u32, c1, c2 % 32)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.rotl"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1486,7 +1486,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, math.rotl(u32, c1, c2 % 32)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.rotr"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1495,28 +1495,28 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, math.rotr(u32, c1, c2 % 32)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.clz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u64); - self.pushOperandNoCheck(u64, @clz(u64, c1)); + self.pushOperandNoCheck(u64, @clz(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.ctz"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u64); - self.pushOperandNoCheck(u64, @ctz(u64, c1)); + self.pushOperandNoCheck(u64, @ctz(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.popcnt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { const c1 = self.popOperand(u64); - self.pushOperandNoCheck(u64, @popCount(u64, c1)); + self.pushOperandNoCheck(u64, @popCount(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.add"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1525,7 +1525,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 +% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.sub"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1534,7 +1534,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 -% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.mul"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1543,7 +1543,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 *% c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.div_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1557,7 +1557,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, div); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.div_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1571,7 +1571,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, div); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.rem_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1590,7 +1590,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, rem); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.rem_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1604,7 +1604,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, rem); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.and"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1613,7 +1613,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 & c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.or"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1622,7 +1622,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 | c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.xor"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1631,7 +1631,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, c1 ^ c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.shl"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1640,7 +1640,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, math.shl(u64, c1, c2 % 64)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.shr_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1654,7 +1654,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, math.shr(i64, c1, mod)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.shr_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1663,7 +1663,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, math.shr(u64, c1, c2 % 64)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.rotl"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1672,7 +1672,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, math.rotl(u64, c1, c2 % 64)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.rotr"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1681,7 +1681,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, math.rotr(u64, c1, c2 % 64)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.abs"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1689,7 +1689,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, math.fabs(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.neg"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1697,7 +1697,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, -c1); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.ceil"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1705,7 +1705,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @ceil(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.floor"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1713,7 +1713,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @floor(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.trunc"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1721,7 +1721,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @trunc(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.nearest"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1739,7 +1739,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @round(c1)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.sqrt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1747,7 +1747,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, math.sqrt(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.add"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1756,7 +1756,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, c1 + c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.sub"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1765,7 +1765,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, c1 - c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.mul"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1774,7 +1774,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, c1 * c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.div"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1783,7 +1783,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, c1 / c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.min"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1792,11 +1792,11 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (c1 == 0.0 and c2 == 0.0) { @@ -1809,7 +1809,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, math.min(c1, c2)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.max"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1818,11 +1818,11 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (c1 == 0.0 and c2 == 0.0) { @@ -1835,7 +1835,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, math.max(c1, c2)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.copysign"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1848,7 +1848,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, math.fabs(c1)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.abs"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1856,7 +1856,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, math.fabs(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.neg"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1864,7 +1864,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, -c1); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.ceil"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1872,7 +1872,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @ceil(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.floor"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1880,7 +1880,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @floor(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.trunc"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1888,7 +1888,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @trunc(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.nearest"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1906,7 +1906,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @round(c1)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.sqrt"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1914,7 +1914,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, math.sqrt(c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.add"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1923,7 +1923,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, c1 + c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.sub"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1932,7 +1932,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, c1 - c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.mul"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1941,7 +1941,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, c1 * c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.div"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1950,7 +1950,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, c1 / c2); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.min"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1959,11 +1959,11 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(f64, math.nan_f64); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (c1 == 0.0 and c2 == 0.0) { @@ -1976,7 +1976,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, math.min(c1, c2)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.max"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -1985,11 +1985,11 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(f64, math.nan_f64); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (c1 == 0.0 and c2 == 0.0) { @@ -2002,7 +2002,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, math.max(c1, c2)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.copysign"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2015,7 +2015,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, math.fabs(c1)); } - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.wrap_i64"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2023,7 +2023,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @truncate(i32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.trunc_f32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2048,7 +2048,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @floatToInt(i32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.trunc_f32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2073,7 +2073,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @floatToInt(u32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.trunc_f64_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2098,7 +2098,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @floatToInt(i32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.trunc_f64_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2123,7 +2123,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u32, @floatToInt(u32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.extend_i32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2131,7 +2131,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @truncate(i32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.extend_i32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2139,7 +2139,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @truncate(u32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.trunc_f32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2164,7 +2164,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @floatToInt(i64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.trunc_f32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2189,7 +2189,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @floatToInt(u64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.trunc_f64_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2214,7 +2214,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @floatToInt(i64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.trunc_f64_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2239,7 +2239,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(u64, @floatToInt(u64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.convert_i32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2247,7 +2247,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @intToFloat(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.convert_i32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2255,7 +2255,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @intToFloat(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.convert_i64_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2263,7 +2263,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @intToFloat(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.convert_i64_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2271,7 +2271,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @intToFloat(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.demote_f64"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2279,7 +2279,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @floatCast(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.convert_i32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2287,7 +2287,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @intToFloat(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.convert_i32_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2295,7 +2295,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @intToFloat(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.convert_i64_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2303,7 +2303,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @intToFloat(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.convert_i64_u"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2311,7 +2311,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @intToFloat(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.promote_f32"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2319,7 +2319,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @floatCast(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.reinterpret_f32"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2327,7 +2327,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @bitCast(i32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.reinterpret_f64"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2335,7 +2335,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @bitCast(i64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f32.reinterpret_i32"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2343,7 +2343,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f32, @bitCast(f32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"f64.reinterpret_i64"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2351,7 +2351,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(f64, @bitCast(f64, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.extend8_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2359,7 +2359,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @truncate(i8, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i32.extend16_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2367,7 +2367,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i32, @truncate(i16, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.extend8_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2375,7 +2375,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @truncate(i8, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.extend16_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2383,7 +2383,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @truncate(i16, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn @"i64.extend32_s"(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2391,7 +2391,7 @@ pub const Interpreter = struct { self.pushOperandNoCheck(i64, @truncate(i32, c1)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } fn trunc_sat(self: *Interpreter, ip: usize, code: []Instruction, err: *?WasmError) void { @@ -2404,20 +2404,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f32, std.math.maxInt(i32))) { self.pushOperandNoCheck(i32, @bitCast(i32, @as(u32, 0x7fffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f32, std.math.minInt(i32))) { self.pushOperandNoCheck(i32, @bitCast(i32, @as(u32, 0x80000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(i32, @floatToInt(i32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 1 => { const c1 = self.popOperand(f32); @@ -2425,20 +2425,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f32, std.math.maxInt(u32))) { self.pushOperandNoCheck(u32, @bitCast(u32, @as(u32, 0xffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f32, std.math.minInt(u32))) { self.pushOperandNoCheck(u32, @bitCast(u32, @as(u32, 0x00000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(u32, @floatToInt(u32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 2 => { const c1 = self.popOperand(f64); @@ -2446,20 +2446,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f64, std.math.maxInt(i32))) { self.pushOperandNoCheck(i32, @bitCast(i32, @as(u32, 0x7fffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f64, std.math.minInt(i32))) { self.pushOperandNoCheck(i32, @bitCast(i32, @as(u32, 0x80000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(i32, @floatToInt(i32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 3 => { const c1 = self.popOperand(f64); @@ -2467,20 +2467,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f64, std.math.maxInt(u32))) { self.pushOperandNoCheck(u32, @bitCast(u32, @as(u32, 0xffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f64, std.math.minInt(u32))) { self.pushOperandNoCheck(u32, @bitCast(u32, @as(u32, 0x00000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(u32, @floatToInt(u32, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 4 => { const c1 = self.popOperand(f32); @@ -2488,20 +2488,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f32, std.math.maxInt(i64))) { self.pushOperandNoCheck(i64, @bitCast(i64, @as(u64, 0x7fffffffffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f32, std.math.minInt(i64))) { self.pushOperandNoCheck(i64, @bitCast(i64, @as(u64, 0x8000000000000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(i64, @floatToInt(i64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 5 => { const c1 = self.popOperand(f32); @@ -2509,20 +2509,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f32, std.math.maxInt(u64))) { self.pushOperandNoCheck(u64, @bitCast(u64, @as(u64, 0xffffffffffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f32, std.math.minInt(u64))) { self.pushOperandNoCheck(u64, @bitCast(u64, @as(u64, 0x0000000000000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(u64, @floatToInt(u64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 6 => { const c1 = self.popOperand(f64); @@ -2530,20 +2530,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f64, std.math.maxInt(i64))) { self.pushOperandNoCheck(i64, @bitCast(i64, @as(u64, 0x7fffffffffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f64, std.math.minInt(i64))) { self.pushOperandNoCheck(i64, @bitCast(i64, @as(u64, 0x8000000000000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(i64, @floatToInt(i64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, 7 => { const c1 = self.popOperand(f64); @@ -2551,20 +2551,20 @@ pub const Interpreter = struct { if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc >= @intToFloat(f64, std.math.maxInt(u64))) { self.pushOperandNoCheck(u64, @bitCast(u64, @as(u64, 0xffffffffffffffff))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } if (trunc < @intToFloat(f64, std.math.minInt(u64))) { self.pushOperandNoCheck(u64, @bitCast(u64, @as(u64, 0x0000000000000000))); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); } self.pushOperandNoCheck(u64, @floatToInt(u64, trunc)); - return @call(.{ .modifier = .always_tail }, dispatch, .{ self, ip + 1, code, err }); + return dispatch(self, ip + 1, code, err); }, else => { err.* = error.Trap; @@ -2573,7 +2573,7 @@ pub const Interpreter = struct { } } - const InstructionFunction = fn (*Interpreter, usize, []Instruction, *?WasmError) void; + const InstructionFunction = *const fn (*Interpreter, usize, []Instruction, *?WasmError) void; const lookup = [256]InstructionFunction{ @"unreachable", nop, block, loop, @"if", @"else", if_no_else, impl_ni, impl_ni, impl_ni, impl_ni, end, br, br_if, br_table, @"return", diff --git a/src/main.zig b/src/main.zig index b0b9d925..7d8f78dd 100644 --- a/src/main.zig +++ b/src/main.zig @@ -8,7 +8,7 @@ pub const Memory = @import("memory.zig").Memory; pub const ValueType = @import("common.zig").ValueType; pub const WasmError = @import("function.zig").WasmError; -test "" { +test { _ = @import("validator.zig"); _ = @import("interpreter.zig"); _ = @import("module.zig"); diff --git a/src/module.zig b/src/module.zig index ab152fb1..a53f2412 100644 --- a/src/module.zig +++ b/src/module.zig @@ -948,7 +948,7 @@ test "module loading (simple add function)" { const alloc = arena.allocator(); - const bytes = @embedFile("../test/test.wasm"); + const bytes = @embedFile("test/test.wasm"); var store: Store = Store.init(alloc); @@ -973,7 +973,7 @@ test "module loading (fib)" { const alloc = arena.allocator(); - const bytes = @embedFile("../test/fib.wasm"); + const bytes = @embedFile("test/fib.wasm"); var store: Store = Store.init(alloc); @@ -1022,7 +1022,7 @@ test "module loading (fact)" { const alloc = arena.allocator(); - const bytes = @embedFile("../test/fact.wasm"); + const bytes = @embedFile("test/fact.wasm"); var store: Store = Store.init(alloc); diff --git a/src/table.zig b/src/table.zig index a37df8e5..6164dc17 100644 --- a/src/table.zig +++ b/src/table.zig @@ -7,8 +7,11 @@ pub const Table = struct { max: ?u32, pub fn init(alloc: mem.Allocator, min: u32, max: ?u32) !Table { + const data = try alloc.alloc(?usize, min); + mem.set(?usize, data, null); + return Table{ - .data = try alloc.alloc(?usize, min), + .data = data, .min = min, .max = max, }; diff --git a/src/test/fact.wasm b/src/test/fact.wasm new file mode 100644 index 00000000..30f46bdd Binary files /dev/null and b/src/test/fact.wasm differ diff --git a/src/test/fib.wasm b/src/test/fib.wasm new file mode 100644 index 00000000..55f4ed90 Binary files /dev/null and b/src/test/fib.wasm differ diff --git a/src/test/test.wasm b/src/test/test.wasm new file mode 100644 index 00000000..357f72da Binary files /dev/null and b/src/test/test.wasm differ diff --git a/test/src/testrunner.zig b/test/src/testrunner.zig index 56bfd446..4555aed0 100644 --- a/test/src/testrunner.zig +++ b/test/src/testrunner.zig @@ -76,7 +76,7 @@ pub fn main() anyerror!void { // 1. Get .json file from command line var args = process.args(); _ = args.skip(); - const filename = args.nextPosix() orelse return error.NoFilename; + const filename = args.next() orelse return error.NoFilename; std.log.info("testing: {s}", .{filename}); var arena = ArenaAllocator.init(gpa.allocator()); @@ -87,8 +87,15 @@ pub fn main() anyerror!void { // 2. Parse json and find .wasm file const json_string = try fs.cwd().readFileAlloc(alloc, filename, 0xFFFFFFF); - @setEvalBranchQuota(10000); - const r = try json.parse(Wast, &json.TokenStream.init(json_string), json.ParseOptions{ .allocator = alloc }); + // See https://github.com/ziglang/zig/issues/12624 + comptime { + @setEvalBranchQuota(100000); + _ = json.ParseError([]const Command); + _ = json.ParseError(Wast); + } + + var ts = json.TokenStream.init(json_string); + const r = try json.parse(Wast, &ts, json.ParseOptions{ .allocator = alloc }); // 2.a. Find the wasm file var wasm_filename: []const u8 = undefined;