From f70b9c55bba669d2f764da713a5aa99129837093 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 22 Jan 2023 22:29:05 +0000 Subject: [PATCH 01/16] Dispatch directly with function pointer address instead of lookup through table --- src/instance/vm.zig | 908 +++++++++++++++++++++--------------------- src/module.zig | 13 + src/module/parser.zig | 3 + 3 files changed, 471 insertions(+), 453 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index e351550e..0a9e8139 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -84,14 +84,16 @@ pub const VirtualMachine = struct { } pub fn invoke(self: *VirtualMachine, ip: usize) !void { - const instr = self.inst.module.parsed_code.items[ip]; + const instr = self.inst.module.instructions.items[ip]; - try @call(.auto, lookup[@intFromEnum(instr)], .{ self, ip, self.inst.module.parsed_code.items }); + try @call(.{}, instr, .{ self, ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)) }); } - const InstructionFunction = *const fn (*VirtualMachine, usize, []Rr) WasmError!void; + // To avoid a recursive definition, define similar function pointer type we will cast to / from + pub const Instruction = *const fn (*VirtualMachine, usize, []Rr, []*void) WasmError!void; + pub const InstructionFunction = *const fn (*VirtualMachine, usize, []Rr, []Instruction) WasmError!void; - const lookup = [256]InstructionFunction{ + pub 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", call, call_indirect, fast_call, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, drop, select, select, impl_ni, impl_ni, impl_ni, @"local.get", @"local.set", @"local.tee", @"global.get", @"global.set", @"table.get", @"table.set", impl_ni, @"i32.load", @"i64.load", @"f32.load", @"f64.load", @"i32.load8_s", @"i32.load8_u", @"i32.load16_s", @"i32.load16_u", @@ -110,27 +112,27 @@ pub const VirtualMachine = struct { impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, misc, impl_ni, impl_ni, impl_ni, }; - inline fn dispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { - const next_instr = code[next_ip]; + inline fn dispatch(self: *VirtualMachine, next_ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + const next_fn = instructions[next_ip]; - return try @call(.always_tail, lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); + return try @call(.always_tail, @as(InstructionFunction, @ptrCast(next_fn)), .{ self, next_ip, code, instructions }); } pub const REF_NULL: u64 = 0xFFFF_FFFF_FFFF_FFFF; - fn impl_ni(_: *VirtualMachine, _: usize, _: []Rr) WasmError!void { + pub fn impl_ni(_: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { return error.NotImplemented; } - fn @"unreachable"(_: *VirtualMachine, _: usize, _: []Rr) WasmError!void { + pub fn @"unreachable"(_: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { return error.TrapUnreachable; } - fn nop(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { - return dispatch(self, ip + 1, code); + pub fn nop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + return dispatch(self, ip + 1, code, instructions); } - fn block(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn block(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].block; try self.pushLabel(Label{ @@ -139,10 +141,10 @@ pub const VirtualMachine = struct { .branch_target = meta.branch_target, }); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn loop(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn loop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].loop; try self.pushLabel(Label{ @@ -152,10 +154,10 @@ pub const VirtualMachine = struct { .branch_target = meta.branch_target, }); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"if"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"if"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"if"; const condition = self.popOperand(u32); @@ -165,21 +167,21 @@ pub const VirtualMachine = struct { .branch_target = meta.branch_target, }); - return dispatch(self, if (condition == 0) meta.else_ip else ip + 1, code); + return dispatch(self, if (condition == 0) meta.else_ip else ip + 1, code, instructions); } - fn @"else"(self: *VirtualMachine, _: usize, code: []Rr) WasmError!void { + pub fn @"else"(self: *VirtualMachine, _: usize, code: []Rr, instructions: []Instruction) WasmError!void { const label = self.popLabel(); - return dispatch(self, label.branch_target, code); + return dispatch(self, label.branch_target, code, instructions); } - fn if_no_else(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn if_no_else(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].if_no_else; const condition = self.popOperand(u32); if (condition == 0) { - return dispatch(self, meta.branch_target, code); + return dispatch(self, meta.branch_target, code, instructions); } else { // We are inside the if branch try self.pushLabel(Label{ @@ -188,31 +190,31 @@ pub const VirtualMachine = struct { .branch_target = meta.branch_target, }); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } } - fn end(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn end(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { _ = self.popLabel(); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn br(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn br(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const next_ip = self.branch(code[ip].br); - return dispatch(self, next_ip, code); + return dispatch(self, next_ip, code, instructions); } - fn br_if(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn br_if(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const condition = self.popOperand(u32); const next_ip = if (condition == 0) ip + 1 else self.branch(code[ip].br_if); - return dispatch(self, next_ip, code); + return dispatch(self, next_ip, code, instructions); } - fn br_table(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn br_table(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].br_table; const i = self.popOperand(u32); @@ -220,10 +222,10 @@ pub const VirtualMachine = struct { const next_ip = if (i >= ls.len) self.branch(meta.ln) else self.branch(ls[i]); - return dispatch(self, next_ip, code); + return dispatch(self, next_ip, code, instructions); } - fn @"return"(self: *VirtualMachine, _: usize, _: []Rr) WasmError!void { + pub fn @"return"(self: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { const frame = self.peekFrame(); const n = frame.return_arity; @@ -246,10 +248,10 @@ pub const VirtualMachine = struct { const previous_frame = self.peekFrame(); self.inst = previous_frame.inst; - return dispatch(self, label.branch_target, previous_frame.inst.module.parsed_code.items); + return dispatch(self, label.branch_target, previous_frame.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items))); } - fn call(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn call(self: *VirtualMachine, ip: usize, code: []Rr, _: []Instruction) WasmError!void { const funcidx = code[ip].call; const function = try self.inst.getFunc(funcidx); @@ -288,10 +290,10 @@ pub const VirtualMachine = struct { }, } - return dispatch(self, next_ip, self.inst.module.parsed_code.items); + return dispatch(self, next_ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items))); } - fn call_indirect(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn call_indirect(self: *VirtualMachine, ip: usize, code: []Rr, _: []Instruction) WasmError!void { const call_indirect_instruction = code[ip].call_indirect; var module = self.inst.module; @@ -344,10 +346,10 @@ pub const VirtualMachine = struct { }, } - return dispatch(self, next_ip, self.inst.module.parsed_code.items); + return dispatch(self, next_ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items))); } - fn fast_call(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn fast_call(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const f = code[ip].fast_call; // Check we have enough stack space @@ -371,15 +373,15 @@ pub const VirtualMachine = struct { .branch_target = ip + 1, }); - return dispatch(self, f.start, code); + return dispatch(self, f.start, code, instructions); } - fn drop(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn drop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { _ = self.popAnyOperand(); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn select(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn select(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const condition = self.popOperand(u32); const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -390,48 +392,48 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, c2); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"local.get"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"local.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const localidx = code[ip].@"local.get"; const frame = self.peekFrame(); self.pushOperandNoCheck(u64, frame.locals[localidx]); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"local.set"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"local.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const localidx = code[ip].@"local.set"; const frame = self.peekFrame(); frame.locals[localidx] = self.popOperand(u64); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"local.tee"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"local.tee"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const localidx = code[ip].@"local.tee"; const frame = self.peekFrame(); frame.locals[localidx] = self.peekOperand(); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"global.get"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"global.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const globalidx = code[ip].@"global.get"; const global = try self.inst.getGlobal(globalidx); self.pushOperandNoCheck(u64, global.value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"global.set"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"global.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const globalidx = code[ip].@"global.set"; const value = self.popAnyOperand(); @@ -439,10 +441,10 @@ pub const VirtualMachine = struct { global.value = value; - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.get"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const tableidx = code[ip].@"table.get"; const table = try self.inst.getTable(tableidx); @@ -455,10 +457,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, REF_NULL); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.set"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const tableidx = code[ip].@"table.set"; const table = try self.inst.getTable(tableidx); @@ -467,10 +469,10 @@ pub const VirtualMachine = struct { try table.set(index, ref); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.load"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.load"; const memory = try self.inst.getMemory(0); @@ -479,10 +481,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load"; const memory = try self.inst.getMemory(0); @@ -491,10 +493,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.load"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"f32.load"; const memory = try self.inst.getMemory(0); @@ -503,10 +505,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.load"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"f64.load"; const memory = try self.inst.getMemory(0); @@ -515,10 +517,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.load8_s"; const memory = try self.inst.getMemory(0); @@ -527,10 +529,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.load8_u"; const memory = try self.inst.getMemory(0); @@ -539,10 +541,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.load16_s"; const memory = try self.inst.getMemory(0); @@ -551,10 +553,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.load16_u"; const memory = try self.inst.getMemory(0); @@ -563,10 +565,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load8_s"; const memory = try self.inst.getMemory(0); @@ -575,10 +577,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load8_u"; const memory = try self.inst.getMemory(0); @@ -587,10 +589,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load16_s"; const memory = try self.inst.getMemory(0); @@ -599,10 +601,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load16_u"; const memory = try self.inst.getMemory(0); @@ -611,10 +613,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load32_s"; const memory = try self.inst.getMemory(0); @@ -623,10 +625,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.load32_u"; const memory = try self.inst.getMemory(0); @@ -635,10 +637,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.store"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.store"; const memory = try self.inst.getMemory(0); @@ -647,10 +649,10 @@ pub const VirtualMachine = struct { try memory.write(u32, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.store"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.store"; const memory = try self.inst.getMemory(0); @@ -659,10 +661,10 @@ pub const VirtualMachine = struct { try memory.write(u64, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.store"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"f32.store"; const memory = try self.inst.getMemory(0); @@ -671,10 +673,10 @@ pub const VirtualMachine = struct { try memory.write(f32, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.store"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"f64.store"; const memory = try self.inst.getMemory(0); @@ -683,10 +685,10 @@ pub const VirtualMachine = struct { try memory.write(f64, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.store8"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.store8"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.store8"; const memory = try self.inst.getMemory(0); @@ -695,10 +697,10 @@ pub const VirtualMachine = struct { try memory.write(u8, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.store16"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.store16"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i32.store16"; const memory = try self.inst.getMemory(0); @@ -707,10 +709,10 @@ pub const VirtualMachine = struct { try memory.write(u16, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.store8"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.store8"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.store8"; const memory = try self.inst.getMemory(0); @@ -719,10 +721,10 @@ pub const VirtualMachine = struct { try memory.write(u8, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.store16"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.store16"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.store16"; const memory = try self.inst.getMemory(0); @@ -731,10 +733,10 @@ pub const VirtualMachine = struct { try memory.write(u16, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.store32"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.store32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].@"i64.store32"; const memory = try self.inst.getMemory(0); @@ -743,18 +745,18 @@ pub const VirtualMachine = struct { try memory.write(u32, meta.offset, address, value); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"memory.size"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"memory.size"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const memory = try self.inst.getMemory(0); self.pushOperandNoCheck(u32, @as(u32, @intCast(memory.size()))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"memory.grow"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const memory = try self.inst.getMemory(0); const num_pages = self.popOperand(u32); @@ -764,394 +766,394 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.const"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const instr = code[ip]; self.pushOperandNoCheck(i32, instr.@"i32.const"); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.const"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const instr = code[ip]; self.pushOperandNoCheck(i64, instr.@"i64.const"); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.const"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const instr = code[ip]; self.pushOperandNoCheck(f32, instr.@"f32.const"); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.const"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const instr = code[ip]; self.pushOperandNoCheck(f64, instr.@"f64.const"); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.eqz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.eq"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.ne"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.le_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.le_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.le_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.le_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.eqz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.eqz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.eq"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.ne"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.le_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.le_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.le_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.le_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.eq"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.ne"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.lt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.lt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.gt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.gt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.le"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.le"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.ge"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.ge"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.eq"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.ne"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.lt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.lt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.gt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.gt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.le"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.le"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.ge"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.ge"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.clz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.clz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @clz(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.ctz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.ctz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @ctz(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @popCount(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.add"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 +% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.sub"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 -% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.mul"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 *% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.div_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.div_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1159,10 +1161,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, div); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.div_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.div_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1170,10 +1172,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, div); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1182,10 +1184,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, rem); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1193,46 +1195,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, rem); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.and"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.and"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 & c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.or"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.or"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 | c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.xor"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.xor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 ^ c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.shl"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.shl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1240,85 +1242,85 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, math.shr(i32, c1, mod)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.rotl"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.rotl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.rotr"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.rotr"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.clz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.clz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @clz(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.ctz"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.ctz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @ctz(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @popCount(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.add"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 +% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.sub"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 -% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.mul"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 *% c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.div_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.div_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1326,10 +1328,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, div); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.div_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.div_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1337,10 +1339,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, div); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1349,10 +1351,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, rem); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1360,46 +1362,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, rem); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.and"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.and"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 & c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.or"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.or"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 | c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.xor"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.xor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 ^ c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.shl"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.shl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1407,77 +1409,77 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, math.shr(i64, c1, mod)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.rotl"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.rotl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.rotr"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.rotr"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.abs"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.abs"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.fabs(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.neg"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.neg"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, -c1); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.ceil"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.ceil"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @ceil(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.floor"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.floor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @floor(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.trunc"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.trunc"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @trunc(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.nearest"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.nearest"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1492,64 +1494,64 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @round(c1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.sqrt(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.add"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 + c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.sub"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 - c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.mul"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 * c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.div"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.div"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 / c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.min"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.min"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1562,20 +1564,20 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @min(c1, c2)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.max"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.max"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1588,10 +1590,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @max(c1, c2)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.copysign"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.copysign"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); @@ -1601,50 +1603,50 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, math.fabs(c1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.abs"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.abs"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.fabs(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.neg"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.neg"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, -c1); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.ceil"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.ceil"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @ceil(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.floor"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.floor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @floor(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.trunc"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.trunc"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @trunc(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.nearest"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.nearest"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1659,60 +1661,60 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @round(c1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.sqrt(c1)); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.add"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 + c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.sub"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 - c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.mul"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 * c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.div"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.div"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 / c2); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.min"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.min"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1725,16 +1727,16 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @min(c1, c2)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.max"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.max"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1747,10 +1749,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @max(c1, c2)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.copysign"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.copysign"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); @@ -1760,18 +1762,18 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, math.fabs(c1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i32, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1783,10 +1785,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1798,10 +1800,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1813,10 +1815,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1828,26 +1830,26 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u32, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1859,10 +1861,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1874,10 +1876,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1889,10 +1891,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1904,168 +1906,168 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f32, @as(f32, @floatCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f64, @as(f64, @floatCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(i32, @as(i32, @bitCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(i64, @as(i64, @bitCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @bitCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @bitCast(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"ref.null"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"ref.null"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { self.pushOperandNoCheck(u64, REF_NULL); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"ref.is_null"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const value = self.popOperand(u64); if (value == REF_NULL) { @@ -2074,21 +2076,21 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, 0); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"ref.func"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"ref.func"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const funcidx = code[ip].@"ref.func"; const ref = self.inst.funcaddrs.items[funcidx]; // Not sure about this at all, this could still coincidentally be zero? self.pushOperandNoCheck(u64, ref); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn misc(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { - return miscDispatch(self, ip, code); + pub fn misc(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + return miscDispatch(self, ip, code, instructions); } const misc_lookup = [18]InstructionFunction{ @@ -2096,189 +2098,189 @@ pub const VirtualMachine = struct { @"table.size", @"table.fill", }; - inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, code: []Rr) WasmError!void { + inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const next_instr = code[next_ip].misc; - return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code }); + return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code, instructions }); } - fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"memory.init"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"memory.init"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"memory.init"; const n = self.popOperand(u32); @@ -2292,7 +2294,7 @@ pub const VirtualMachine = struct { if (@as(u33, src) + @as(u33, n) > data.data.len) return error.OutOfBoundsMemoryAccess; if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } if (data.dropped) return error.OutOfBoundsMemoryAccess; @@ -2302,18 +2304,18 @@ pub const VirtualMachine = struct { try memory.write(u8, 0, dest + i, data.data[src + i]); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"data.drop"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"data.drop"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const dataidx = code[ip].misc.@"data.drop"; const data = try self.inst.getData(dataidx); data.dropped = true; - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"memory.copy"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"memory.copy"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const n = self.popOperand(u32); const src = self.popOperand(u32); const dest = self.popOperand(u32); @@ -2325,7 +2327,7 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } // FIXME: move initial bounds check into Memory implementation @@ -2336,10 +2338,10 @@ pub const VirtualMachine = struct { memory.uncheckedCopyBackwards(dest, data[src .. src + n]); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"memory.fill"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"memory.fill"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const n = self.popOperand(u32); const value = self.popOperand(u32); const dest = self.popOperand(u32); @@ -2349,15 +2351,15 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } memory.uncheckedFill(dest, n, @as(u8, @truncate(value))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.init"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.init"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"table.init"; const tableidx = meta.tableidx; const elemidx = meta.elemidx; @@ -2383,19 +2385,19 @@ pub const VirtualMachine = struct { try table.set(d + i, elem.elem[s + i]); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"elem.drop"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"elem.drop"; const elemidx = meta.elemidx; const elem = try self.inst.getElem(elemidx); elem.dropped = true; - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.copy"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.copy"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"table.copy"; const dest_tableidx = meta.dest_tableidx; const src_tableidx = meta.src_tableidx; @@ -2426,10 +2428,10 @@ pub const VirtualMachine = struct { } } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.grow"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.grow"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"table.grow"; const tableidx = meta.tableidx; @@ -2448,10 +2450,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.size"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.size"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"table.size"; const tableidx = meta.tableidx; @@ -2459,10 +2461,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intCast(table.size()))); - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } - fn @"table.fill"(self: *VirtualMachine, ip: usize, code: []Rr) WasmError!void { + pub fn @"table.fill"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { const meta = code[ip].misc.@"table.fill"; const tableidx = meta.tableidx; @@ -2482,7 +2484,7 @@ pub const VirtualMachine = struct { try table.set(d + i, ref); } - return dispatch(self, ip + 1, code); + return dispatch(self, ip + 1, code, instructions); } // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-control-mathsf-br-l @@ -2556,11 +2558,11 @@ pub const VirtualMachine = struct { return self.op_stack[self.op_ptr - 1]; } - fn peekOperand(self: *VirtualMachine) u64 { + pub fn peekOperand(self: *VirtualMachine) u64 { return self.op_stack[self.op_ptr - 1]; } - fn peekNthOperand(self: *VirtualMachine, index: u32) u64 { + pub fn peekNthOperand(self: *VirtualMachine, index: u32) u64 { return self.op_stack[self.op_ptr - index - 1]; } @@ -2584,7 +2586,7 @@ pub const VirtualMachine = struct { return self.frame_stack[self.frame_ptr - 1]; } - fn peekFrame(self: *VirtualMachine) *Frame { + pub fn peekFrame(self: *VirtualMachine) *Frame { return &self.frame_stack[self.frame_ptr - 1]; } @@ -2606,7 +2608,7 @@ pub const VirtualMachine = struct { // // Returns nth label on the Label stack relative to the top of the stack // - fn peekNthLabel(self: *VirtualMachine, index: u32) *Label { + pub fn peekNthLabel(self: *VirtualMachine, index: u32) *Label { return &self.label_stack[self.label_ptr - index - 1]; } diff --git a/src/module.zig b/src/module.zig index d41584f7..a17f48f0 100644 --- a/src/module.zig +++ b/src/module.zig @@ -4,6 +4,7 @@ const leb = std.leb; const math = std.math; const unicode = std.unicode; const ArrayList = std.ArrayList; +const VirtualMachine = @import("instance/vm.zig").VirtualMachine; const Rr = @import("rr.zig").Rr; const RrOpcode = @import("rr.zig").RrOpcode; const Instance = @import("instance.zig").Instance; @@ -35,6 +36,7 @@ pub const Module = struct { data_count: ?u32 = null, element_init_offsets: ArrayList(usize), parsed_code: ArrayList(Rr), + instructions: ArrayList(VirtualMachine.InstructionFunction), local_types: ArrayList(LocalType), br_table_indices: ArrayList(u32), references: ArrayList(u32), @@ -57,6 +59,7 @@ pub const Module = struct { .datas = Section(DataSegment).init(alloc), .element_init_offsets = ArrayList(usize).init(alloc), .parsed_code = ArrayList(Rr).init(alloc), + .instructions = ArrayList(VirtualMachine.InstructionFunction).init(alloc), .local_types = ArrayList(LocalType).init(alloc), .br_table_indices = ArrayList(u32).init(alloc), .references = ArrayList(u32).init(alloc), @@ -78,6 +81,7 @@ pub const Module = struct { self.element_init_offsets.deinit(); self.parsed_code.deinit(); + self.instructions.deinit(); self.local_types.deinit(); self.br_table_indices.deinit(); self.references.deinit(); @@ -97,6 +101,7 @@ pub const Module = struct { // track the end of a function to use its return on invoke // See https://github.com/malcolmstill/zware/pull/133 try self.parsed_code.append(.@"return"); + try self.instructions.append(VirtualMachine.@"return"); var i: usize = 0; while (true) : (i += 1) { @@ -476,7 +481,9 @@ pub const Module = struct { const init_offset = self.parsed_code.items.len; try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(VirtualMachine.@"ref.func"); try self.parsed_code.append(Rr.@"return"); + try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -507,7 +514,9 @@ pub const Module = struct { const init_offset = self.parsed_code.items.len; try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(VirtualMachine.@"ref.func"); try self.parsed_code.append(Rr.@"return"); + try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -540,7 +549,9 @@ pub const Module = struct { const init_offset = self.parsed_code.items.len; try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(VirtualMachine.@"ref.func"); try self.parsed_code.append(Rr.@"return"); + try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -570,7 +581,9 @@ pub const Module = struct { const init_offset = self.parsed_code.items.len; try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(VirtualMachine.@"ref.func"); try self.parsed_code.append(Rr.@"return"); + try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } diff --git a/src/module/parser.zig b/src/module/parser.zig index 0c8f8d24..a7210e6e 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -13,6 +13,7 @@ const RefType = @import("../valtype.zig").RefType; const Range = @import("../rr.zig").Range; const Rr = @import("../rr.zig").Rr; const MiscRr = @import("../rr.zig").MiscRr; +const VirtualMachine = @import("../instance/vm.zig").VirtualMachine; pub const Parsed = struct { start: usize, @@ -59,6 +60,7 @@ pub const Parser = struct { while (try self.next()) |instr| { try self.module.parsed_code.append(instr); + try self.module.instructions.append(VirtualMachine.lookup[@enumToInt(instr)]); } const bytes_read = self.bytesRead(); @@ -101,6 +103,7 @@ pub const Parser = struct { else => return error.ValidatorConstantExpressionRequired, } try self.module.parsed_code.append(instr); + try self.module.instructions.append(VirtualMachine.lookup[@enumToInt(instr)]); } const bytes_read = self.bytesRead(); From 779d9c4d64ad06910168c7a948ab755d15ff8ae8 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 22 Jan 2023 23:07:03 +0000 Subject: [PATCH 02/16] Also patch for instructions --- src/module/parser.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/module/parser.zig b/src/module/parser.zig index a7210e6e..ed3d3131 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -68,6 +68,7 @@ pub const Parser = struct { // Patch last end so that it is return self.module.parsed_code.items[self.module.parsed_code.items.len - 1] = .@"return"; + self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; } @@ -111,6 +112,7 @@ pub const Parser = struct { // Patch last end so that it is return self.module.parsed_code.items[self.module.parsed_code.items.len - 1] = .@"return"; + self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; } From 5a2ebec11301537efddba9610abe3025bbed6f6b Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 22 Jan 2023 23:08:44 +0000 Subject: [PATCH 03/16] More patching --- src/module/parser.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/module/parser.zig b/src/module/parser.zig index ed3d3131..8cee9863 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -305,6 +305,7 @@ pub const Parser = struct { .else_ip = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, }, }; + self.module.instructions.items[parsed_code_offset] = VirtualMachine.@"if"; }, else => return error.UnexpectedInstruction, } From 5cd499a9f8d966e526e4b84f89a8330cfa0c117f Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 23 Jul 2023 20:08:43 +0100 Subject: [PATCH 04/16] Fixes --- src/module/parser.zig | 4 ++-- src/store/elem.zig | 4 ++-- src/store/memory.zig | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/module/parser.zig b/src/module/parser.zig index 8cee9863..c8077dbf 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -60,7 +60,7 @@ pub const Parser = struct { while (try self.next()) |instr| { try self.module.parsed_code.append(instr); - try self.module.instructions.append(VirtualMachine.lookup[@enumToInt(instr)]); + try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); } const bytes_read = self.bytesRead(); @@ -104,7 +104,7 @@ pub const Parser = struct { else => return error.ValidatorConstantExpressionRequired, } try self.module.parsed_code.append(instr); - try self.module.instructions.append(VirtualMachine.lookup[@enumToInt(instr)]); + try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); } const bytes_read = self.bytesRead(); diff --git a/src/store/elem.zig b/src/store/elem.zig index 071a22a2..71ed4331 100644 --- a/src/store/elem.zig +++ b/src/store/elem.zig @@ -3,7 +3,7 @@ const mem = std.mem; const RefType = @import("../valtype.zig").RefType; pub const Elem = struct { - @"type": RefType, + type: RefType, elem: []u32, alloc: mem.Allocator, dropped: bool = false, @@ -12,7 +12,7 @@ pub const Elem = struct { const elem = try alloc.alloc(u32, count); return Elem{ - .@"type" = reftype, + .type = reftype, .elem = elem, .alloc = alloc, }; diff --git a/src/store/memory.zig b/src/store/memory.zig index 0895e430..984fefe1 100644 --- a/src/store/memory.zig +++ b/src/store/memory.zig @@ -55,7 +55,7 @@ pub const Memory = struct { mem.copy(u8, self.data.items[address .. address + data.len], data); } - pub fn uncheckedFill(self: *Memory, dst_address: u32, n: u32, value: u8) void { + pub fn uncheckedFill(self: *Memory, dst_address: u32, n: u32, value: u8) void { @memset(self.data.items[dst_address .. dst_address + n], value); } @@ -76,7 +76,6 @@ pub const Memory = struct { const effective_address = @as(u33, offset) + @as(u33, address); if (effective_address + @sizeOf(T) - 1 >= self.data.items.len) return error.OutOfBoundsMemoryAccess; - switch (T) { u8, u16, From 0879aa2e6835f09773601afd020af582d5195b03 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 23 Jul 2023 20:10:57 +0100 Subject: [PATCH 05/16] @call(.auto, ...) --- src/instance/vm.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 0a9e8139..1e9596d4 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -86,7 +86,7 @@ pub const VirtualMachine = struct { pub fn invoke(self: *VirtualMachine, ip: usize) !void { const instr = self.inst.module.instructions.items[ip]; - try @call(.{}, instr, .{ self, ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)) }); + try @call(.auto, instr, .{ self, ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)) }); } // To avoid a recursive definition, define similar function pointer type we will cast to / from From ab7a333a872b019750e3dc98597e1a344bcfd5bb Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Sun, 30 Jul 2023 18:41:18 +0100 Subject: [PATCH 06/16] WIP immediates --- src/instance/vm.zig | 1218 +++++++++++++++++++++++-------------------- src/module.zig | 6 + src/rr.zig | 2 +- 3 files changed, 663 insertions(+), 563 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 1e9596d4..5fa2babb 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -85,13 +85,14 @@ pub const VirtualMachine = struct { pub fn invoke(self: *VirtualMachine, ip: usize) !void { const instr = self.inst.module.instructions.items[ip]; + const imm = self.inst.module.immediates_offset.items[ip]; - try @call(.auto, instr, .{ self, ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)) }); + try @call(.auto, instr, .{ self, ip, imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), self.inst.module.immediates.items }); } // To avoid a recursive definition, define similar function pointer type we will cast to / from - pub const Instruction = *const fn (*VirtualMachine, usize, []Rr, []*void) WasmError!void; - pub const InstructionFunction = *const fn (*VirtualMachine, usize, []Rr, []Instruction) WasmError!void; + pub const Instruction = *const fn (*VirtualMachine, usize, usize, []*void, []u32) WasmError!void; + pub const InstructionFunction = *const fn (*VirtualMachine, usize, usize, []Instruction, []u32) WasmError!void; pub 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", @@ -112,120 +113,138 @@ pub const VirtualMachine = struct { impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, misc, impl_ni, impl_ni, impl_ni, }; - inline fn dispatch(self: *VirtualMachine, next_ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + inline fn dispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const next_fn = instructions[next_ip]; - return try @call(.always_tail, @as(InstructionFunction, @ptrCast(next_fn)), .{ self, next_ip, code, instructions }); + return try @call(.always_tail, @as(InstructionFunction, @ptrCast(next_fn)), .{ self, next_ip, imm, instructions, immediates }); } pub const REF_NULL: u64 = 0xFFFF_FFFF_FFFF_FFFF; - pub fn impl_ni(_: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { + pub fn impl_ni(_: *VirtualMachine, _: usize, _: usize, _: []Instruction, _: []u32) WasmError!void { return error.NotImplemented; } - pub fn @"unreachable"(_: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { + pub fn @"unreachable"(_: *VirtualMachine, _: usize, _: usize, _: []Instruction, _: []u32) WasmError!void { return error.TrapUnreachable; } - pub fn nop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - return dispatch(self, ip + 1, code, instructions); + pub fn nop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn block(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].block; + pub fn block(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].block; + const param_arity = immediates[imm]; + const return_arity = immediates[imm + 1]; + const branch_target = immediates[imm + 2]; try self.pushLabel(Label{ - .return_arity = meta.return_arity, - .op_stack_len = self.op_ptr - meta.param_arity, - .branch_target = meta.branch_target, + .return_arity = return_arity, + .op_stack_len = self.op_ptr - param_arity, + .branch_target = branch_target, }); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 3, instructions, immediates); } - pub fn loop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].loop; + pub fn loop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const param_arity = immediates[imm]; + const return_arity = immediates[imm + 1]; + _ = return_arity; + const branch_target = immediates[imm + 2]; try self.pushLabel(Label{ // note that we use block_params rather than block_returns for return arity: - .return_arity = meta.param_arity, - .op_stack_len = self.op_ptr - meta.param_arity, - .branch_target = meta.branch_target, + .return_arity = param_arity, + .op_stack_len = self.op_ptr - param_arity, + .branch_target = branch_target, }); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 3, instructions, immediates); } - pub fn @"if"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"if"; + pub fn @"if"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const param_arity = immediates[imm]; + const return_arity = immediates[imm + 1]; + const branch_target = immediates[imm + 2]; + const else_ip = immediates[imm + 3]; + const condition = self.popOperand(u32); try self.pushLabel(Label{ - .return_arity = meta.return_arity, - .op_stack_len = self.op_ptr - meta.param_arity, - .branch_target = meta.branch_target, + .return_arity = return_arity, + .op_stack_len = self.op_ptr - param_arity, + .branch_target = branch_target, }); - return dispatch(self, if (condition == 0) meta.else_ip else ip + 1, code, instructions); + return dispatch(self, if (condition == 0) else_ip else ip + 1, imm + 4, instructions, immediates); } - pub fn @"else"(self: *VirtualMachine, _: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"else"(self: *VirtualMachine, _: usize, _: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const label = self.popLabel(); - return dispatch(self, label.branch_target, code, instructions); + return dispatch(self, label.branch_target, @panic("lookup offset array"), instructions, immediates); } - pub fn if_no_else(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].if_no_else; + pub fn if_no_else(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].if_no_else; + const param_arity = immediates[imm]; + const return_arity = immediates[imm + 1]; + const branch_target = immediates[imm + 2]; + const condition = self.popOperand(u32); if (condition == 0) { - return dispatch(self, meta.branch_target, code, instructions); + return dispatch(self, branch_target, @panic("Lookup offset array"), instructions, immediates); } else { // We are inside the if branch try self.pushLabel(Label{ - .return_arity = meta.return_arity, - .op_stack_len = self.op_ptr - meta.param_arity, - .branch_target = meta.branch_target, + .return_arity = return_arity, + .op_stack_len = self.op_ptr - param_arity, + .branch_target = branch_target, }); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 3, instructions, immediates); } } - pub fn end(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn end(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { _ = self.popLabel(); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn br(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const next_ip = self.branch(code[ip].br); + pub fn br(self: *VirtualMachine, _: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const next_ip = self.branch(immediates[imm]); - return dispatch(self, next_ip, code, instructions); + return dispatch(self, next_ip, imm + 1, instructions, immediates); } - pub fn br_if(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn br_if(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const condition = self.popOperand(u32); - const next_ip = if (condition == 0) ip + 1 else self.branch(code[ip].br_if); + const next_ip = if (condition == 0) ip + 1 else self.branch(immediates[imm]); + const next_offset = if (condition == 0) imm + 1 else self.branch(@panic("Lookup offset for new instruction")); - return dispatch(self, next_ip, code, instructions); + return dispatch(self, next_ip, next_offset, instructions, immediates); } - pub fn br_table(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].br_table; + pub fn br_table(self: *VirtualMachine, _: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const ls_ptr = immediates[imm]; + const ls_len = immediates[imm + 1]; + const ln = immediates[imm + 2]; const i = self.popOperand(u32); - const ls = self.inst.module.br_table_indices.items[meta.ls.offset .. meta.ls.offset + meta.ls.count]; + const ls = self.inst.module.br_table_indices.items[ls_ptr .. ls_ptr + ls_len]; - const next_ip = if (i >= ls.len) self.branch(meta.ln) else self.branch(ls[i]); + const next_ip = if (i >= ls.len) self.branch(ln) else self.branch(ls[i]); + const next_imm = if (true) @panic("Lookup correct offset"); - return dispatch(self, next_ip, code, instructions); + return dispatch(self, next_ip, next_imm, instructions, immediates); } - pub fn @"return"(self: *VirtualMachine, _: usize, _: []Rr, _: []Instruction) WasmError!void { + pub fn @"return"(self: *VirtualMachine, _: usize, _: usize, _: []Instruction, immediates: []u32) WasmError!void { const frame = self.peekFrame(); const n = frame.return_arity; @@ -248,14 +267,17 @@ pub const VirtualMachine = struct { const previous_frame = self.peekFrame(); self.inst = previous_frame.inst; - return dispatch(self, label.branch_target, previous_frame.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items))); + // FIXME: probably reference previous frame + return dispatch(self, label.branch_target, label.branch_target_immediate, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items)), immediates); } - pub fn call(self: *VirtualMachine, ip: usize, code: []Rr, _: []Instruction) WasmError!void { - const funcidx = code[ip].call; + pub fn call(self: *VirtualMachine, ip: usize, imm: usize, _: []Instruction, immediates: []u32) WasmError!void { + // const funcidx = code[ip].call; + const funcidx = immediates[imm]; const function = try self.inst.getFunc(funcidx); var next_ip = ip; + var next_imm = imm; switch (function.subtype) { .function => |f| { @@ -283,22 +305,25 @@ pub const VirtualMachine = struct { }); next_ip = f.start; + next_imm = @panic("FIXME"); }, .host_function => |hf| { try hf.func(self); next_ip = ip + 1; + next_imm = imm + 1; }, } - return dispatch(self, next_ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items))); + // FIXME: + return dispatch(self, next_ip, next_imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), immediates); } - pub fn call_indirect(self: *VirtualMachine, ip: usize, code: []Rr, _: []Instruction) WasmError!void { - const call_indirect_instruction = code[ip].call_indirect; + pub fn call_indirect(self: *VirtualMachine, ip: usize, imm: usize, _: []Instruction, immediates: []u32) WasmError!void { + // const call_indirect_instruction = code[ip].call_indirect; var module = self.inst.module; - const typeidx = call_indirect_instruction.typeidx; - const tableidx = call_indirect_instruction.tableidx; + const typeidx = immediates[imm]; + const tableidx = immediates[imm + 1]; // Read lookup index from stack const lookup_index = self.popOperand(u32); @@ -311,6 +336,7 @@ pub const VirtualMachine = struct { try function.checkSignatures(call_indirect_func_type); var next_ip = ip; + var next_imm = imm; switch (function.subtype) { .function => |func| { @@ -343,45 +369,51 @@ pub const VirtualMachine = struct { try host_func.func(self); next_ip = ip + 1; + next_imm = imm + 1; }, } - return dispatch(self, next_ip, self.inst.module.parsed_code.items, @as([]Instruction, @ptrCast(self.inst.module.instructions.items))); + return dispatch(self, next_ip, next_imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), immediates); } - pub fn fast_call(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const f = code[ip].fast_call; + pub fn fast_call(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const f = code[ip].fast_call; + const start = immediates[imm]; + const locals = immediates[imm + 1]; + const params = immediates[imm + 2]; + const results = immediates[imm + 3]; + const required_stack_space = immediates[imm + 4]; // Check we have enough stack space - try self.checkStackSpace(f.required_stack_space + f.locals); + try self.checkStackSpace(required_stack_space + locals); // Make space for locals (again, params already on stack) - self.op_ptr += f.locals; + self.op_ptr += locals; // Consume parameters from the stack try self.pushFrame(Frame{ - .op_stack_len = self.op_ptr - f.params - f.locals, + .op_stack_len = self.op_ptr - params - locals, .label_stack_len = self.label_ptr, - .return_arity = f.results, + .return_arity = results, .inst = self.inst, - }, f.locals + f.params); + }, locals + params); // Our continuation is the code after call try self.pushLabel(Label{ - .return_arity = f.results, - .op_stack_len = self.op_ptr - f.params - f.locals, + .return_arity = results, + .op_stack_len = self.op_ptr - params - locals, .branch_target = ip + 1, }); - return dispatch(self, f.start, code, instructions); + return dispatch(self, start, imm + 5, instructions, immediates); } - pub fn drop(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn drop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { _ = self.popAnyOperand(); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn select(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn select(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const condition = self.popOperand(u32); const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -392,60 +424,60 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, c2); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"local.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const localidx = code[ip].@"local.get"; + pub fn @"local.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const localidx = immediates[imm]; const frame = self.peekFrame(); self.pushOperandNoCheck(u64, frame.locals[localidx]); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"local.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const localidx = code[ip].@"local.set"; + pub fn @"local.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const localidx = immediates[imm]; const frame = self.peekFrame(); frame.locals[localidx] = self.popOperand(u64); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"local.tee"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const localidx = code[ip].@"local.tee"; + pub fn @"local.tee"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const localidx = immediates[imm]; const frame = self.peekFrame(); frame.locals[localidx] = self.peekOperand(); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"global.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const globalidx = code[ip].@"global.get"; + pub fn @"global.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const globalidx = immediates[imm]; const global = try self.inst.getGlobal(globalidx); self.pushOperandNoCheck(u64, global.value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"global.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const globalidx = code[ip].@"global.set"; + pub fn @"global.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const globalidx = immediates[imm]; const value = self.popAnyOperand(); const global = try self.inst.getGlobal(globalidx); global.value = value; - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.get"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const tableidx = code[ip].@"table.get"; + pub fn @"table.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const tableidx = immediates[imm]; const table = try self.inst.getTable(tableidx); const index = self.popOperand(u32); @@ -457,11 +489,11 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, REF_NULL); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.set"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const tableidx = code[ip].@"table.set"; + pub fn @"table.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const tableidx = immediates[imm]; const table = try self.inst.getTable(tableidx); const ref = self.popOperand(u64); @@ -469,294 +501,340 @@ pub const VirtualMachine = struct { try table.set(index, ref); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"i32.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.load"; + pub fn @"i32.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u32, meta.offset, address); + const value = try memory.read(u32, offset, address); self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load"; + pub fn @"i64.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u64, meta.offset, address); + const value = try memory.read(u64, offset, address); self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"f32.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"f32.load"; + pub fn @"f32.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(f32, meta.offset, address); + const value = try memory.read(f32, offset, address); self.pushOperandNoCheck(f32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"f64.load"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"f64.load"; + pub fn @"f64.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(f64, meta.offset, address); + const value = try memory.read(f64, offset, address); self.pushOperandNoCheck(f64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.load8_s"; + pub fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(i8, meta.offset, address); + const value = try memory.read(i8, offset, address); self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.load8_u"; + pub fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u8, meta.offset, address); + const value = try memory.read(u8, offset, address); self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.load16_s"; + pub fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(i16, meta.offset, address); + const value = try memory.read(i16, offset, address); self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.load16_u"; + pub fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u16, meta.offset, address); + const value = try memory.read(u16, offset, address); self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load8_s"; + pub fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(i8, meta.offset, address); + const value = try memory.read(i8, offset, address); self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load8_u"; + pub fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u8, meta.offset, address); + const value = try memory.read(u8, offset, address); self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load16_s"; + pub fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(i16, meta.offset, address); + const value = try memory.read(i16, offset, address); self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load16_u"; + pub fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u16, meta.offset, address); + const value = try memory.read(u16, offset, address); self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load32_s"; + pub fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(i32, meta.offset, address); + const value = try memory.read(i32, offset, address); self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.load32_u"; + pub fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); - const value = try memory.read(u32, meta.offset, address); + const value = try memory.read(u32, offset, address); self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.store"; + pub fn @"i32.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value = self.popOperand(u32); const address = self.popOperand(u32); - try memory.write(u32, meta.offset, address, value); + try memory.write(u32, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.store"; + pub fn @"i64.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value = self.popOperand(u64); const address = self.popOperand(u32); - try memory.write(u64, meta.offset, address, value); + try memory.write(u64, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"f32.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"f32.store"; + pub fn @"f32.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value = self.popOperand(f32); const address = self.popOperand(u32); - try memory.write(f32, meta.offset, address, value); + try memory.write(f32, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"f64.store"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"f64.store"; + pub fn @"f64.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value = self.popOperand(f64); const address = self.popOperand(u32); - try memory.write(f64, meta.offset, address, value); + try memory.write(f64, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.store8"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.store8"; + pub fn @"i32.store8"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value: u8 = @truncate(self.popOperand(u32)); const address = self.popOperand(u32); - try memory.write(u8, meta.offset, address, value); + try memory.write(u8, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i32.store16"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i32.store16"; + pub fn @"i32.store16"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value: u16 = @truncate(self.popOperand(u32)); const address = self.popOperand(u32); - try memory.write(u16, meta.offset, address, value); + try memory.write(u16, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.store8"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.store8"; + pub fn @"i64.store8"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value: u8 = @truncate(self.popOperand(u64)); const address = self.popOperand(u32); - try memory.write(u8, meta.offset, address, value); + try memory.write(u8, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.store16"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.store16"; + pub fn @"i64.store16"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value: u16 = @truncate(self.popOperand(u64)); const address = self.popOperand(u32); - try memory.write(u16, meta.offset, address, value); + try memory.write(u16, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"i64.store32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].@"i64.store32"; + pub fn @"i64.store32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const alignment = immediates[imm]; + _ = alignment; + const offset = immediates[imm + 1]; const memory = try self.inst.getMemory(0); const value: u32 = @truncate(self.popOperand(u64)); const address = self.popOperand(u32); - try memory.write(u32, meta.offset, address, value); + try memory.write(u32, offset, address, value); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"memory.size"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"memory.size"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const memory = try self.inst.getMemory(0); self.pushOperandNoCheck(u32, @as(u32, @intCast(memory.size()))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const memory = try self.inst.getMemory(0); const num_pages = self.popOperand(u32); @@ -766,394 +844,398 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const instr = code[ip]; + pub fn @"i32.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const literal = @as(i32, @intCast(immediates[imm])); - self.pushOperandNoCheck(i32, instr.@"i32.const"); + self.pushOperandNoCheck(i32, literal); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"i64.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const instr = code[ip]; + pub fn @"i64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const lower = immediates[imm]; + const upper = immediates[imm + 1]; + const literal: u64 = upper << @as(u6, 32) + lower; - self.pushOperandNoCheck(i64, instr.@"i64.const"); + self.pushOperandNoCheck(i64, literal); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"f32.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const instr = code[ip]; + pub fn @"f32.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const literal = @as(f32, @floatFromInt(immediates[imm])); - self.pushOperandNoCheck(f32, instr.@"f32.const"); + self.pushOperandNoCheck(f32, literal); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"f64.const"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const instr = code[ip]; + pub fn @"f64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const lower = immediates[imm]; + const upper = immediates[imm + 1]; + const literal: u64 = upper << @as(u6, 32) + lower; - self.pushOperandNoCheck(f64, instr.@"f64.const"); + self.pushOperandNoCheck(f64, literal); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.le_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.le_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.le_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.le_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.eqz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.eqz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.le_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.le_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.le_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.le_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.lt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.lt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.gt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.gt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.le"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.le"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.ge"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.ge"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.eq"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.ne"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.lt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.lt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.gt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.gt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.le"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.le"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.ge"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.ge"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.clz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.clz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @clz(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.ctz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.ctz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @ctz(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @popCount(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 +% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 -% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 *% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.div_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.div_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1161,10 +1243,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, div); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.div_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.div_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1172,10 +1254,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, div); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1184,10 +1266,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, rem); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1195,46 +1277,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, rem); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.and"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.and"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 & c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.or"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.or"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 | c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.xor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.xor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 ^ c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.shl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.shl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1242,85 +1324,85 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, math.shr(i32, c1, mod)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.rotl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.rotl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.rotr"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.rotr"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.clz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.clz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @clz(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.ctz"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.ctz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @ctz(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @popCount(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 +% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 -% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 *% c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.div_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.div_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1328,10 +1410,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, div); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.div_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.div_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1339,10 +1421,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, div); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1351,10 +1433,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, rem); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1362,46 +1444,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, rem); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.and"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.and"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 & c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.or"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.or"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 | c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.xor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.xor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 ^ c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.shl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.shl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1409,77 +1491,77 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, math.shr(i64, c1, mod)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.rotl"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.rotl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.rotr"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.rotr"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.abs"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.abs"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.fabs(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.neg"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.neg"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, -c1); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.ceil"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.ceil"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @ceil(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.floor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.floor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @floor(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.trunc"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.trunc"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @trunc(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.nearest"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.nearest"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1494,64 +1576,64 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @round(c1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.sqrt(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 + c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 - c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 * c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.div"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.div"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 / c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.min"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.min"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (c1 == 0.0 and c2 == 0.0) { @@ -1564,20 +1646,20 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @min(c1, c2)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.max"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.max"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (c1 == 0.0 and c2 == 0.0) { @@ -1590,10 +1672,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @max(c1, c2)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.copysign"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.copysign"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); @@ -1603,50 +1685,50 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, math.fabs(c1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.abs"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.abs"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.fabs(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.neg"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.neg"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, -c1); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.ceil"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.ceil"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @ceil(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.floor"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.floor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @floor(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.trunc"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.trunc"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @trunc(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.nearest"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.nearest"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1661,60 +1743,60 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @round(c1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.sqrt(c1)); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.add"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 + c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.sub"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 - c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.mul"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 * c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.div"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.div"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 / c2); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.min"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.min"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (c1 == 0.0 and c2 == 0.0) { @@ -1727,16 +1809,16 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @min(c1, c2)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.max"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.max"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (c1 == 0.0 and c2 == 0.0) { @@ -1749,10 +1831,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @max(c1, c2)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.copysign"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.copysign"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); @@ -1762,18 +1844,18 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, math.fabs(c1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i32, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1785,10 +1867,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1800,10 +1882,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1815,10 +1897,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1830,26 +1912,26 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u32, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1861,10 +1943,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1876,10 +1958,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1891,10 +1973,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1906,168 +1988,168 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f32, @as(f32, @floatCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f64, @as(f64, @floatCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(i32, @as(i32, @bitCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(i64, @as(i64, @bitCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @bitCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @bitCast(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"ref.null"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"ref.null"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { self.pushOperandNoCheck(u64, REF_NULL); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const value = self.popOperand(u64); if (value == REF_NULL) { @@ -2076,21 +2158,21 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, 0); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"ref.func"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const funcidx = code[ip].@"ref.func"; + pub fn @"ref.func"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const funcidx = immediates[imm]; const ref = self.inst.funcaddrs.items[funcidx]; // Not sure about this at all, this could still coincidentally be zero? self.pushOperandNoCheck(u64, ref); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn misc(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - return miscDispatch(self, ip, code, instructions); + pub fn misc(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + return miscDispatch(self, ip, imm, instructions, immediates); } const misc_lookup = [18]InstructionFunction{ @@ -2098,203 +2180,207 @@ pub const VirtualMachine = struct { @"table.size", @"table.fill", }; - inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const next_instr = code[next_ip].misc; + inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const next_instr = code[next_ip].misc; + const next_instr = immediates[imm]; + const next_offset = if (true) @panic("FIXME"); - return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, code, instructions }); + return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, next_offset, instructions, immediates }); } - pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f32, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f32, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f64, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f64, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f32, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f32, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f64, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } if (trunc < @as(f64, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm, instructions, immediates); } - pub fn @"memory.init"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"memory.init"; + pub fn @"memory.init"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].misc.@"memory.init"; + const memidx = immediates[imm]; + const dataidx = immediates[imm + 1]; const n = self.popOperand(u32); const src = self.popOperand(u32); const dest = self.popOperand(u32); - const memory = try self.inst.getMemory(meta.memidx); + const memory = try self.inst.getMemory(memidx); const mem_size = memory.sizeBytes(); - const data = try self.inst.getData(meta.dataidx); + const data = try self.inst.getData(dataidx); if (@as(u33, src) + @as(u33, n) > data.data.len) return error.OutOfBoundsMemoryAccess; if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } if (data.dropped) return error.OutOfBoundsMemoryAccess; @@ -2304,18 +2390,25 @@ pub const VirtualMachine = struct { try memory.write(u8, 0, dest + i, data.data[src + i]); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"data.drop"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const dataidx = code[ip].misc.@"data.drop"; + pub fn @"data.drop"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const dataidx = code[ip].misc.@"data.drop"; + const dataidx = immediates[imm]; const data = try self.inst.getData(dataidx); data.dropped = true; - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"memory.copy"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"memory.copy"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // FIXME: use these when we support multiple memories + const src_memidx = immediates[imm]; + _ = src_memidx; + const dst_memidx = immediates[imm + 1]; + _ = dst_memidx; + const n = self.popOperand(u32); const src = self.popOperand(u32); const dest = self.popOperand(u32); @@ -2327,7 +2420,7 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } // FIXME: move initial bounds check into Memory implementation @@ -2338,10 +2431,12 @@ pub const VirtualMachine = struct { memory.uncheckedCopyBackwards(dest, data[src .. src + n]); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"memory.fill"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { + pub fn @"memory.fill"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + _ = immediates[imm]; + const n = self.popOperand(u32); const value = self.popOperand(u32); const dest = self.popOperand(u32); @@ -2351,18 +2446,18 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } memory.uncheckedFill(dest, n, @as(u8, @truncate(value))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.init"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"table.init"; - const tableidx = meta.tableidx; - const elemidx = meta.elemidx; + pub fn @"table.init"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].misc.@"table.init"; + const tableidx = immediates[imm]; + const elemidx = immediates[imm + 1]; const table = try self.inst.getTable(tableidx); const elem = try self.inst.getElem(elemidx); @@ -2385,24 +2480,26 @@ pub const VirtualMachine = struct { try table.set(d + i, elem.elem[s + i]); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"elem.drop"; - const elemidx = meta.elemidx; + pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].misc.@"elem.drop"; + const elemidx = immediates[imm]; const elem = try self.inst.getElem(elemidx); elem.dropped = true; - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.copy"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"table.copy"; - const dest_tableidx = meta.dest_tableidx; - const src_tableidx = meta.src_tableidx; + pub fn @"table.copy"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // const meta = code[ip].misc.@"table.copy"; + // const dest_tableidx = meta.dest_tableidx; + // const src_tableidx = meta.src_tableidx; + const dst_tableidx = immediates[imm]; + const src_tableidx = immediates[imm + 1]; - const dest_table = try self.inst.getTable(dest_tableidx); + const dest_table = try self.inst.getTable(dst_tableidx); const src_table = try self.inst.getTable(src_tableidx); const n = self.popOperand(u32); @@ -2428,12 +2525,11 @@ pub const VirtualMachine = struct { } } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } - pub fn @"table.grow"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"table.grow"; - const tableidx = meta.tableidx; + pub fn @"table.grow"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const tableidx = immediates[imm]; const table = try self.inst.getTable(tableidx); @@ -2450,23 +2546,21 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.size"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"table.size"; - const tableidx = meta.tableidx; + pub fn @"table.size"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const tableidx = immediates[imm]; const table = try self.inst.getTable(tableidx); self.pushOperandNoCheck(u32, @as(u32, @intCast(table.size()))); - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } - pub fn @"table.fill"(self: *VirtualMachine, ip: usize, code: []Rr, instructions: []Instruction) WasmError!void { - const meta = code[ip].misc.@"table.fill"; - const tableidx = meta.tableidx; + pub fn @"table.fill"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + const tableidx = immediates[imm]; const table = try self.inst.getTable(tableidx); @@ -2484,7 +2578,7 @@ pub const VirtualMachine = struct { try table.set(d + i, ref); } - return dispatch(self, ip + 1, code, instructions); + return dispatch(self, ip + 1, imm + 1, instructions, immediates); } // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-control-mathsf-br-l diff --git a/src/module.zig b/src/module.zig index a17f48f0..c87d651b 100644 --- a/src/module.zig +++ b/src/module.zig @@ -37,6 +37,8 @@ pub const Module = struct { element_init_offsets: ArrayList(usize), parsed_code: ArrayList(Rr), instructions: ArrayList(VirtualMachine.InstructionFunction), + immediates_offset: ArrayList(u32), + immediates: ArrayList(u32), local_types: ArrayList(LocalType), br_table_indices: ArrayList(u32), references: ArrayList(u32), @@ -60,6 +62,8 @@ pub const Module = struct { .element_init_offsets = ArrayList(usize).init(alloc), .parsed_code = ArrayList(Rr).init(alloc), .instructions = ArrayList(VirtualMachine.InstructionFunction).init(alloc), + .immediates_offset = ArrayList(u32).init(alloc), + .immediates = ArrayList(u32).init(alloc), .local_types = ArrayList(LocalType).init(alloc), .br_table_indices = ArrayList(u32).init(alloc), .references = ArrayList(u32).init(alloc), @@ -82,6 +86,8 @@ pub const Module = struct { self.element_init_offsets.deinit(); self.parsed_code.deinit(); self.instructions.deinit(); + self.immediates_offset.deinit(); + self.immediates.deinit(); self.local_types.deinit(); self.br_table_indices.deinit(); self.references.deinit(); diff --git a/src/rr.zig b/src/rr.zig index cf62a9fc..adc07795 100644 --- a/src/rr.zig +++ b/src/rr.zig @@ -222,7 +222,7 @@ pub const Rr = union(RrOpcode) { ln: u32, }, @"return": void, - call: usize, // u32? + call: u32, // u32? call_indirect: struct { typeidx: u32, tableidx: u32, From aec72df18e7ac8eb346f02f68a306380df4970df Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 01:00:49 +0100 Subject: [PATCH 07/16] Working fib --- src/instance/vm.zig | 24 +- src/module.zig | 37 +- src/module/parser.zig | 958 ++++++++++++++++++++++++------------------ src/rr.zig | 6 +- 4 files changed, 579 insertions(+), 446 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 5fa2babb..62a72bbf 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -95,7 +95,7 @@ pub const VirtualMachine = struct { pub const InstructionFunction = *const fn (*VirtualMachine, usize, usize, []Instruction, []u32) WasmError!void; pub 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", + @"unreachable", nop, block, loop, @"if", @"else", if_with_else, impl_ni, impl_ni, impl_ni, impl_ni, end, br, br_if, br_table, @"return", call, call_indirect, fast_call, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, drop, select, select, impl_ni, impl_ni, impl_ni, @"local.get", @"local.set", @"local.tee", @"global.get", @"global.set", @"table.get", @"table.set", impl_ni, @"i32.load", @"i64.load", @"f32.load", @"f64.load", @"i32.load8_s", @"i32.load8_u", @"i32.load16_s", @"i32.load16_u", @"i64.load8_s", @"i64.load8_u", @"i64.load16_s", @"i64.load16_u", @"i64.load32_s", @"i64.load32_u", @"i32.store", @"i64.store", @"f32.store", @"f64.store", @"i32.store8", @"i32.store16", @"i64.store8", @"i64.store16", @"i64.store32", @"memory.size", @@ -164,7 +164,7 @@ pub const VirtualMachine = struct { return dispatch(self, ip + 1, imm + 3, instructions, immediates); } - pub fn @"if"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn if_with_else(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const param_arity = immediates[imm]; const return_arity = immediates[imm + 1]; const branch_target = immediates[imm + 2]; @@ -187,16 +187,19 @@ pub const VirtualMachine = struct { return dispatch(self, label.branch_target, @panic("lookup offset array"), instructions, immediates); } - pub fn if_no_else(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + // if_no_else + pub fn @"if"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { // const meta = code[ip].if_no_else; const param_arity = immediates[imm]; const return_arity = immediates[imm + 1]; const branch_target = immediates[imm + 2]; + _ = immediates[imm + 3]; const condition = self.popOperand(u32); if (condition == 0) { - return dispatch(self, branch_target, @panic("Lookup offset array"), instructions, immediates); + const next_imm = self.inst.module.immediates_offset.items[branch_target]; + return dispatch(self, branch_target, next_imm, instructions, immediates); } else { // We are inside the if branch try self.pushLabel(Label{ @@ -205,7 +208,7 @@ pub const VirtualMachine = struct { .branch_target = branch_target, }); - return dispatch(self, ip + 1, imm + 3, instructions, immediates); + return dispatch(self, ip + 1, imm + 4, instructions, immediates); } } @@ -268,7 +271,8 @@ pub const VirtualMachine = struct { self.inst = previous_frame.inst; // FIXME: probably reference previous frame - return dispatch(self, label.branch_target, label.branch_target_immediate, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items)), immediates); + const branch_target_immediate_offset = self.inst.module.immediates_offset.items[label.branch_target]; + return dispatch(self, label.branch_target, branch_target_immediate_offset, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items)), immediates); } pub fn call(self: *VirtualMachine, ip: usize, imm: usize, _: []Instruction, immediates: []u32) WasmError!void { @@ -305,7 +309,7 @@ pub const VirtualMachine = struct { }); next_ip = f.start; - next_imm = @panic("FIXME"); + next_imm = self.inst.module.immediates_offset.items[f.start]; }, .host_function => |hf| { try hf.func(self); @@ -858,7 +862,7 @@ pub const VirtualMachine = struct { pub fn @"i64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const lower = immediates[imm]; const upper = immediates[imm + 1]; - const literal: u64 = upper << @as(u6, 32) + lower; + const literal = @as(i64, @intCast((@as(u64, upper) << 32) + lower)); self.pushOperandNoCheck(i64, literal); @@ -876,11 +880,11 @@ pub const VirtualMachine = struct { pub fn @"f64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const lower = immediates[imm]; const upper = immediates[imm + 1]; - const literal: u64 = upper << @as(u6, 32) + lower; + const literal = @as(f64, @floatFromInt((@as(u64, upper) << 32) + lower)); self.pushOperandNoCheck(f64, literal); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, imm + 2, instructions, immediates); } pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { diff --git a/src/module.zig b/src/module.zig index c87d651b..fbd4a181 100644 --- a/src/module.zig +++ b/src/module.zig @@ -35,7 +35,7 @@ pub const Module = struct { function_index_start: ?usize = null, data_count: ?u32 = null, element_init_offsets: ArrayList(usize), - parsed_code: ArrayList(Rr), + // parsed_code: ArrayList(Rr), instructions: ArrayList(VirtualMachine.InstructionFunction), immediates_offset: ArrayList(u32), immediates: ArrayList(u32), @@ -60,7 +60,7 @@ pub const Module = struct { .codes = Section(Code).init(alloc), .datas = Section(DataSegment).init(alloc), .element_init_offsets = ArrayList(usize).init(alloc), - .parsed_code = ArrayList(Rr).init(alloc), + // .parsed_code = ArrayList(Rr).init(alloc), .instructions = ArrayList(VirtualMachine.InstructionFunction).init(alloc), .immediates_offset = ArrayList(u32).init(alloc), .immediates = ArrayList(u32).init(alloc), @@ -84,7 +84,7 @@ pub const Module = struct { self.datas.deinit(); self.element_init_offsets.deinit(); - self.parsed_code.deinit(); + // self.parsed_code.deinit(); self.instructions.deinit(); self.immediates_offset.deinit(); self.immediates.deinit(); @@ -106,8 +106,8 @@ pub const Module = struct { // Push an initial return instruction so we don't have to // track the end of a function to use its return on invoke // See https://github.com/malcolmstill/zware/pull/133 - try self.parsed_code.append(.@"return"); try self.instructions.append(VirtualMachine.@"return"); + try self.immediates_offset.append(0); var i: usize = 0; while (true) : (i += 1) { @@ -485,10 +485,10 @@ pub const Module = struct { try self.references.append(funcidx); - const init_offset = self.parsed_code.items.len; - try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + const init_offset = self.instructions.items.len; + // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(VirtualMachine.@"ref.func"); - try self.parsed_code.append(Rr.@"return"); + // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -518,10 +518,10 @@ pub const Module = struct { try self.references.append(funcidx); - const init_offset = self.parsed_code.items.len; - try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + const init_offset = self.instructions.items.len; + // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(VirtualMachine.@"ref.func"); - try self.parsed_code.append(Rr.@"return"); + // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -553,10 +553,10 @@ pub const Module = struct { try self.references.append(funcidx); - const init_offset = self.parsed_code.items.len; - try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + const init_offset = self.instructions.items.len; + // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(VirtualMachine.@"ref.func"); - try self.parsed_code.append(Rr.@"return"); + // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -585,10 +585,10 @@ pub const Module = struct { try self.references.append(funcidx); - const init_offset = self.parsed_code.items.len; - try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + const init_offset = self.instructions.items.len; + // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(VirtualMachine.@"ref.func"); - try self.parsed_code.append(Rr.@"return"); + // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(VirtualMachine.@"return"); try self.element_init_offsets.append(init_offset); } @@ -634,7 +634,7 @@ pub const Module = struct { var j: usize = 0; while (j < expr_count) : (j += 1) { - const init_offset = self.parsed_code.items.len; + const init_offset = self.instructions.items.len; _ = try self.readConstantExpression(.FuncRef); try self.element_init_offsets.append(init_offset); } @@ -681,7 +681,8 @@ pub const Module = struct { const count = try self.readULEB128(u32); self.codes.count = count; - try self.parsed_code.ensureTotalCapacity(count * 32); + // FIXME: better heuristic + also ensure immediates_offset + immediates + try self.instructions.ensureTotalCapacity(count * 32); if (count == 0) return; diff --git a/src/module/parser.zig b/src/module/parser.zig index c8077dbf..795c1d28 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -11,7 +11,7 @@ const Type = @import("validator.zig").Type; const ValType = @import("../valtype.zig").ValType; const RefType = @import("../valtype.zig").RefType; const Range = @import("../rr.zig").Range; -const Rr = @import("../rr.zig").Rr; +const RrOpcode = @import("../rr.zig").RrOpcode; const MiscRr = @import("../rr.zig").MiscRr; const VirtualMachine = @import("../instance/vm.zig").VirtualMachine; @@ -20,6 +20,8 @@ pub const Parsed = struct { max_depth: usize, }; +const ContinuationStackEntry = struct { offset: usize, opcode: RrOpcode }; + pub const Parser = struct { function: []const u8 = undefined, code: []const u8 = undefined, @@ -28,14 +30,14 @@ pub const Parser = struct { validator: Validator = undefined, params: ?[]const ValType, locals: ?[]LocalType, - continuation_stack: [1024]usize = [_]usize{0} ** 1024, + continuation_stack: [1024]ContinuationStackEntry = undefined, continuation_stack_ptr: usize, is_constant: bool = false, scope: usize, pub fn init(module: *Module) Parser { return Parser{ - .code_ptr = module.parsed_code.items.len, + .code_ptr = module.instructions.items.len, .module = module, .params = null, .locals = null, @@ -54,20 +56,20 @@ pub const Parser = struct { self.function = code; self.code = code; - const code_start = self.module.parsed_code.items.len; + const code_start = self.module.instructions.items.len; try self.pushFunction(locals, funcidx); while (try self.next()) |instr| { - try self.module.parsed_code.append(instr); - try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); + _ = instr; + // try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); } const bytes_read = self.bytesRead(); _ = try self.module.readSlice(bytes_read); + // FIXME: might setting .block in ControlFrame mean we don't have to replace final end with return? // Patch last end so that it is return - self.module.parsed_code.items[self.module.parsed_code.items.len - 1] = .@"return"; self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; @@ -79,7 +81,7 @@ pub const Parser = struct { self.function = code; self.code = code; - const code_start = self.module.parsed_code.items.len; + const code_start = self.module.instructions.items.len; const in: [0]ValType = [_]ValType{} ** 0; const out: [1]ValType = [_]ValType{valtype} ** 1; @@ -103,15 +105,14 @@ pub const Parser = struct { => {}, else => return error.ValidatorConstantExpressionRequired, } - try self.module.parsed_code.append(instr); - try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); + // try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); } const bytes_read = self.bytesRead(); _ = try self.module.readSlice(bytes_read); + // FIXME: might setting .block in ControlFrame mean we don't have to replace final end with return? // Patch last end so that it is return - self.module.parsed_code.items[self.module.parsed_code.items.len - 1] = .@"return"; self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; @@ -126,25 +127,26 @@ pub const Parser = struct { self.locals = locals; try self.validator.pushControlFrame( + // FIXME: might setting this as block mean we don't have to replace final end with return? .nop, // block? functype.params[0..0], functype.results, ); } - fn pushContinuationStack(self: *Parser, offset: usize) !void { + fn pushContinuationStack(self: *Parser, offset: usize, opcode: RrOpcode) !void { defer self.continuation_stack_ptr += 1; if (self.continuation_stack_ptr >= self.continuation_stack.len) return error.ContinuationStackOverflow; - self.continuation_stack[self.continuation_stack_ptr] = offset; + self.continuation_stack[self.continuation_stack_ptr] = .{ .offset = offset, .opcode = opcode }; } - fn peekContinuationStack(self: *Parser) !usize { + fn peekContinuationStack(self: *Parser) !ContinuationStackEntry { if (self.continuation_stack_ptr <= 0) return error.ContinuationStackUnderflow; // No test covering this return self.continuation_stack[self.continuation_stack_ptr - 1]; } - fn popContinuationStack(self: *Parser) !usize { + fn popContinuationStack(self: *Parser) !ContinuationStackEntry { if (self.continuation_stack_ptr <= 0) return error.ContinuationStackUnderflow; self.continuation_stack_ptr -= 1; @@ -155,7 +157,7 @@ pub const Parser = struct { return self.function.len - self.code.len; } - pub fn next(self: *Parser) !?Rr { + pub fn next(self: *Parser) !?Opcode { defer self.code_ptr += 1; if (self.scope > 0 and self.code.len == 0) return error.CouldntFindEnd; @@ -166,12 +168,16 @@ pub const Parser = struct { const instr = std.meta.intToEnum(Opcode, self.code[0]) catch return error.IllegalOpcode; self.code = self.code[1..]; - var rr: Rr = undefined; + // Record the start of this instruction's immediates + const immediates_count = std.math.cast(u32, self.module.immediates.items.len) orelse return error.TooManyImmediates; // FIXME: error or assert + try self.module.immediates_offset.append(immediates_count); + + // std.debug.print("instr[{}] = {}, immediate offset = {}\n", .{ self.code_ptr, instr, immediates_count }); // 2. Find the start of the next instruction switch (instr) { - .@"unreachable" => rr = Rr.@"unreachable", - .nop => rr = Rr.nop, + .@"unreachable" => {}, + .nop => {}, .block => { const block_type = try self.readILEB128Mem(i32); @@ -200,16 +206,20 @@ pub const Parser = struct { } } - try self.pushContinuationStack(self.code_ptr); + try self.pushContinuationStack(self.code_ptr, .block); self.scope += 1; - rr = Rr{ - .block = .{ - .param_arity = block_params, - .return_arity = block_returns, - .branch_target = 0, - }, - }; + try self.module.immediates.append(block_params); + try self.module.immediates.append(block_returns); + try self.module.immediates.append(0); + + // Rr{ + // .block = .{ + // .param_arity = block_params, + // .return_arity = block_returns, + // .branch_target = 0, + // }, + // }; }, .loop => { const block_type = try self.readILEB128Mem(i32); @@ -238,16 +248,20 @@ pub const Parser = struct { } } - try self.pushContinuationStack(self.code_ptr); + try self.pushContinuationStack(self.code_ptr, .loop); self.scope += 1; - rr = Rr{ - .loop = .{ - .param_arity = block_params, - .return_arity = block_params, - .branch_target = math.cast(u32, self.code_ptr) orelse return error.FailedCast, - }, - }; + try self.module.immediates.append(block_params); + try self.module.immediates.append(block_params); + try self.module.immediates.append(math.cast(u32, self.code_ptr) orelse return error.FailedCast); + + // rr = Rr{ + // .loop = .{ + // .param_arity = block_params, + // .return_arity = block_params, + // .branch_target = math.cast(u32, self.code_ptr) orelse return error.FailedCast, + // }, + // }; }, .@"if" => { const block_type = try self.readILEB128Mem(i32); @@ -281,73 +295,88 @@ pub const Parser = struct { } } - try self.pushContinuationStack(self.code_ptr); + try self.pushContinuationStack(self.code_ptr, .@"if"); self.scope += 1; - rr = Rr{ - .if_no_else = .{ - .param_arity = block_params, - .return_arity = block_returns, - .branch_target = 0, - }, - }; + try self.module.immediates.append(block_params); + try self.module.immediates.append(block_returns); + try self.module.immediates.append(0); + // an if with no else only has 3 immediates, but we push a fourth here + // so we can exchange the if with an if_with_else + try self.module.immediates.append(0); + + // FIXME: we have found an if, but we were actually pushing an if_no_else + // i.e. we assume we don't have an else until we find one (and if we + // do we replace the if_no_else with a plain if). We could turn this + // around, so that e.g. if means if-no-else and then have a if-with-else + // instruction + // + // rr = Rr{ + // .if_no_else = .{ + // .param_arity = block_params, + // .return_arity = block_returns, + // .branch_target = 0, + // }, + // }; }, .@"else" => { - const parsed_code_offset = try self.peekContinuationStack(); - - switch (self.module.parsed_code.items[parsed_code_offset]) { - .if_no_else => |*b| { - self.module.parsed_code.items[parsed_code_offset] = Rr{ - .@"if" = .{ - .param_arity = b.param_arity, - .return_arity = b.return_arity, - .branch_target = 0, - .else_ip = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, - }, - }; - self.module.instructions.items[parsed_code_offset] = VirtualMachine.@"if"; + const pushed_instruction = try self.peekContinuationStack(); + const immediates_offset = self.module.immediates_offset.items[pushed_instruction.offset]; + + switch (pushed_instruction.opcode) { + .@"if" => { + self.module.immediates.items[immediates_offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + self.module.instructions.items[pushed_instruction.offset] = VirtualMachine.if_with_else; }, else => return error.UnexpectedInstruction, } - rr = Rr.@"else"; + // rr = Rr.@"else"; }, .end => { self.scope -= 1; // If we're not looking at the `end` of a function if (self.scope != 0) { - const parsed_code_offset = try self.popContinuationStack(); + const pushed_instruction = try self.popContinuationStack(); + const immediate_offset = self.module.immediates_offset.items[pushed_instruction.offset]; + // std.debug.print("instr[{}]: end immediate_offset = {}\n", .{ pushed_instruction.offset, immediate_offset }); - switch (self.module.parsed_code.items[parsed_code_offset]) { - .block => |*b| b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, + switch (pushed_instruction.opcode) { + .block => self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, .loop => {}, - .@"if" => |*b| { - b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + .if_with_else => { + self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, - .if_no_else => |*b| { + .@"if" => { + const param_arity = self.module.immediates.items[immediate_offset]; + const return_arity = self.module.immediates.items[immediate_offset + 1]; // 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; + if (param_arity -% return_arity != 0) return error.ValidatorElseBranchExpected; - b.branch_target = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, else => return error.UnexpectedInstruction, } } - rr = Rr.end; + // rr = Rr.end; }, .br => { const label = try self.readULEB128Mem(u32); try self.validator.validateBr(label); - rr = Rr{ .br = label }; + + try self.module.immediates.append(label); + // rr = Rr{ .br = label }; }, .br_if => { const label = try self.readULEB128Mem(u32); try self.validator.validateBrIf(label); - rr = Rr{ .br_if = label }; + + try self.module.immediates.append(label); + // rr = Rr{ .br_if = label }; }, .br_table => { - const label_start = self.module.br_table_indices.items.len; + const label_start = math.cast(u32, self.module.br_table_indices.items.len) orelse return error.TooManyBrTableIndices; const label_count = try self.readULEB128Mem(u32); var j: usize = 0; @@ -360,14 +389,18 @@ pub const Parser = struct { try self.validator.validateBrTable(l_star, ln); - rr = Rr{ - .br_table = .{ - .ls = Range{ .offset = label_start, .count = label_count }, - .ln = ln, - }, - }; + try self.module.immediates.append(label_start); + try self.module.immediates.append(label_count); + try self.module.immediates.append(ln); + + // rr = Rr{ + // .br_table = .{ + // .ls = Range{ .offset = label_start, .count = label_count }, + // .ln = ln, + // }, + // }; }, - .@"return" => rr = Rr.@"return", + .@"return" => {}, .call => { const funcidx = try self.readULEB128Mem(u32); const func = try self.module.functions.lookup(funcidx); @@ -375,7 +408,9 @@ pub const Parser = struct { try self.validator.validateCall(functype); - rr = Rr{ .call = funcidx }; + try self.module.immediates.append(funcidx); + + // rr = Rr{ .call = funcidx }; // TODO: do the replacement at instantiate-time for a fastcall if in same module? // rr = Rr{ .fast_call = .{ .ip_start = 0, .params = 1, .locals = 0, .results = 1 } }; }, @@ -388,15 +423,18 @@ pub const Parser = struct { try self.validator.validateCallIndirect(functype); - rr = Rr{ - .call_indirect = .{ - .typeidx = typeidx, - .tableidx = tableidx, - }, - }; + try self.module.immediates.append(typeidx); + try self.module.immediates.append(tableidx); + + // rr = Rr{ + // .call_indirect = .{ + // .typeidx = typeidx, + // .tableidx = tableidx, + // }, + // }; }, - .drop => rr = Rr.drop, - .select => rr = Rr.select, + .drop => {}, + .select => {}, .select_t => { const type_count = try self.readULEB128Mem(u32); if (type_count != 1) return error.OnlyOneSelectTTypeSupported; // Future versions may support more than one @@ -404,8 +442,6 @@ pub const Parser = struct { const valuetype = try std.meta.intToEnum(ValType, valuetype_raw); try self.validator.validateSelectT(valuetype); - - rr = Rr.select; }, .@"global.get" => { const globalidx = try self.readULEB128Mem(u32); @@ -413,7 +449,9 @@ pub const Parser = struct { try self.validator.validateGlobalGet(global); - rr = Rr{ .@"global.get" = globalidx }; + try self.module.immediates.append(globalidx); + + // rr = Rr{ .@"global.get" = globalidx }; }, .@"global.set" => { const globalidx = try self.readULEB128Mem(u32); @@ -421,7 +459,8 @@ pub const Parser = struct { try self.validator.validateGlobalSet(global); - rr = Rr{ .@"global.set" = globalidx }; + try self.module.immediates.append(globalidx); + // rr = Rr{ .@"global.set" = globalidx }; }, .@"table.get" => { const tableidx = try self.readULEB128Mem(u32); @@ -435,7 +474,8 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); _ = try self.validator.pushOperand(Type{ .Known = reftype }); - rr = Rr{ .@"table.get" = tableidx }; + try self.module.immediates.append(tableidx); + // rr = Rr{ .@"table.get" = tableidx }; }, .@"table.set" => { const tableidx = try self.readULEB128Mem(u32); @@ -449,7 +489,8 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); - rr = Rr{ .@"table.set" = tableidx }; + try self.module.immediates.append(tableidx); + // rr = Rr{ .@"table.set" = tableidx }; }, .@"local.get" => { const localidx = try self.readULEB128Mem(u32); @@ -477,7 +518,8 @@ pub const Parser = struct { } } - rr = Rr{ .@"local.get" = localidx }; + try self.module.immediates.append(localidx); + // rr = Rr{ .@"local.get" = localidx }; }, .@"local.set" => { const localidx = try self.readULEB128Mem(u32); @@ -506,7 +548,9 @@ pub const Parser = struct { } } - rr = Rr{ .@"local.set" = localidx }; + try self.module.immediates.append(localidx); + + // rr = Rr{ .@"local.set" = localidx }; }, .@"local.tee" => { const localidx = try self.readULEB128Mem(u32); @@ -535,37 +579,53 @@ pub const Parser = struct { } } - rr = Rr{ .@"local.tee" = localidx }; + try self.module.immediates.append(localidx); + // rr = Rr{ .@"local.tee" = localidx }; }, .@"memory.size" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; const memidx = try self.readByte(); if (memidx != 0) return error.MalformedMemoryReserved; - rr = Rr{ .@"memory.size" = memidx }; + try self.module.immediates.append(memidx); + // rr = Rr{ .@"memory.size" = memidx }; }, .@"memory.grow" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; const memidx = try self.readByte(); if (memidx != 0) return error.MalformedMemoryReserved; - rr = Rr{ .@"memory.grow" = memidx }; + try self.module.immediates.append(memidx); + // rr = Rr{ .@"memory.grow" = memidx }; }, .@"i32.const" => { const i32_const = try self.readILEB128Mem(i32); - rr = Rr{ .@"i32.const" = i32_const }; + + try self.module.immediates.append(@as(u32, @bitCast(i32_const))); + // rr = Rr{ .@"i32.const" = i32_const }; }, .@"i64.const" => { const i64_const = try self.readILEB128Mem(i64); - rr = Rr{ .@"i64.const" = i64_const }; + const u64_const = @as(u64, @bitCast(i64_const)); + + try self.module.immediates.append(@as(u32, @truncate(u64_const & 0xFFFFFFFF))); + try self.module.immediates.append(@as(u32, @truncate(u64_const >> 32))); + // rr = Rr{ .@"i64.const" = i64_const }; }, .@"f32.const" => { const float_const: f32 = @bitCast(try self.readU32()); - rr = Rr{ .@"f32.const" = float_const }; + + try self.module.immediates.append(@as(u32, @bitCast(float_const))); + // rr = Rr{ .@"f32.const" = float_const }; }, .@"f64.const" => { const float_const: f64 = @bitCast(try self.readU64()); - rr = Rr{ .@"f64.const" = float_const }; + const u64_float = @as(u64, @bitCast(float_const)); + + try self.module.immediates.append(@as(u32, @truncate(u64_float & 0xFFFF))); + try self.module.immediates.append(@as(u32, @truncate(u64_float >> 32))); + + // rr = Rr{ .@"f64.const" = float_const }; }, .@"i32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -575,12 +635,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"i32.load" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.load" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -589,12 +651,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"f32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -603,12 +667,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"f32.load" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"f32.load" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"f64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -617,12 +683,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - rr = Rr{ - .@"f64.load" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"f64.load" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -631,12 +699,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i32.load8_s" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.load8_s" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -645,12 +715,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i32.load8_u" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.load8_u" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -659,12 +731,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i32.load16_s" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.load16_s" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -673,12 +747,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i32.load16_u" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.load16_u" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -687,12 +763,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load8_s" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load8_s" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -701,12 +779,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load8_u" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load8_u" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -715,12 +795,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load16_s" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load16_s" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -729,12 +811,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load16_u" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load16_u" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load32_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -743,12 +827,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load32_s" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load32_s" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.load32_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -757,12 +843,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"i64.load32_u" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.load32_u" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -771,12 +859,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"i32.store" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.store" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -785,12 +875,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - rr = Rr{ - .@"i64.store" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.store" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"f32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -799,12 +891,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"f32.store" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"f32.store" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"f64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -813,12 +907,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - rr = Rr{ - .@"f64.store" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"f64.store" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -827,12 +923,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i32.store8" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.store8" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i32.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -841,12 +939,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i32.store16" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i32.store16" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -855,12 +955,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - rr = Rr{ - .@"i64.store8" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.store8" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -869,12 +971,14 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - rr = Rr{ - .@"i64.store16" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.store16" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, .@"i64.store32" => { const alignment = try self.readULEB128Mem(u32); @@ -882,149 +986,153 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - rr = Rr{ - .@"i64.store32" = .{ - .alignment = alignment, - .offset = offset, - }, - }; + try self.module.immediates.append(alignment); + try self.module.immediates.append(offset); + // rr = Rr{ + // .@"i64.store32" = .{ + // .alignment = alignment, + // .offset = offset, + // }, + // }; }, - .@"i32.eqz" => rr = Rr.@"i32.eqz", - .@"i32.eq" => rr = Rr.@"i32.eq", - .@"i32.ne" => rr = Rr.@"i32.ne", - .@"i32.lt_s" => rr = Rr.@"i32.lt_s", - .@"i32.lt_u" => rr = Rr.@"i32.lt_u", - .@"i32.gt_s" => rr = Rr.@"i32.gt_s", - .@"i32.gt_u" => rr = Rr.@"i32.gt_u", - .@"i32.le_s" => rr = Rr.@"i32.le_s", - .@"i32.le_u" => rr = Rr.@"i32.le_u", - .@"i32.ge_s" => rr = Rr.@"i32.ge_s", - .@"i32.ge_u" => rr = Rr.@"i32.ge_u", - .@"i64.eqz" => rr = Rr.@"i64.eqz", - .@"i64.eq" => rr = Rr.@"i64.eq", - .@"i64.ne" => rr = Rr.@"i64.ne", - .@"i64.lt_s" => rr = Rr.@"i64.lt_s", - .@"i64.lt_u" => rr = Rr.@"i64.lt_u", - .@"i64.gt_s" => rr = Rr.@"i64.gt_s", - .@"i64.gt_u" => rr = Rr.@"i64.gt_u", - .@"i64.le_s" => rr = Rr.@"i64.le_s", - .@"i64.le_u" => rr = Rr.@"i64.le_u", - .@"i64.ge_s" => rr = Rr.@"i64.ge_s", - .@"i64.ge_u" => rr = Rr.@"i64.ge_u", - .@"f32.eq" => rr = Rr.@"f32.eq", - .@"f32.ne" => rr = Rr.@"f32.ne", - .@"f32.lt" => rr = Rr.@"f32.lt", - .@"f32.gt" => rr = Rr.@"f32.gt", - .@"f32.le" => rr = Rr.@"f32.le", - .@"f32.ge" => rr = Rr.@"f32.ge", - .@"f64.eq" => rr = Rr.@"f64.eq", - .@"f64.ne" => rr = Rr.@"f64.ne", - .@"f64.lt" => rr = Rr.@"f64.lt", - .@"f64.gt" => rr = Rr.@"f64.gt", - .@"f64.le" => rr = Rr.@"f64.le", - .@"f64.ge" => rr = Rr.@"f64.ge", - .@"i32.clz" => rr = Rr.@"i32.clz", - .@"i32.ctz" => rr = Rr.@"i32.ctz", - .@"i32.popcnt" => rr = Rr.@"i32.popcnt", - .@"i32.add" => rr = Rr.@"i32.add", - .@"i32.sub" => rr = Rr.@"i32.sub", - .@"i32.mul" => rr = Rr.@"i32.mul", - .@"i32.div_s" => rr = Rr.@"i32.div_s", - .@"i32.div_u" => rr = Rr.@"i32.div_u", - .@"i32.rem_s" => rr = Rr.@"i32.rem_s", - .@"i32.rem_u" => rr = Rr.@"i32.rem_u", - .@"i32.and" => rr = Rr.@"i32.and", - .@"i32.or" => rr = Rr.@"i32.or", - .@"i32.xor" => rr = Rr.@"i32.xor", - .@"i32.shl" => rr = Rr.@"i32.shl", - .@"i32.shr_s" => rr = Rr.@"i32.shr_s", - .@"i32.shr_u" => rr = Rr.@"i32.shr_u", - .@"i32.rotl" => rr = Rr.@"i32.rotl", - .@"i32.rotr" => rr = Rr.@"i32.rotr", - .@"i64.clz" => rr = Rr.@"i64.clz", - .@"i64.ctz" => rr = Rr.@"i64.ctz", - .@"i64.popcnt" => rr = Rr.@"i64.popcnt", - .@"i64.add" => rr = Rr.@"i64.add", - .@"i64.sub" => rr = Rr.@"i64.sub", - .@"i64.mul" => rr = Rr.@"i64.mul", - .@"i64.div_s" => rr = Rr.@"i64.div_s", - .@"i64.div_u" => rr = Rr.@"i64.div_u", - .@"i64.rem_s" => rr = Rr.@"i64.rem_s", - .@"i64.rem_u" => rr = Rr.@"i64.rem_u", - .@"i64.and" => rr = Rr.@"i64.and", - .@"i64.or" => rr = Rr.@"i64.or", - .@"i64.xor" => rr = Rr.@"i64.xor", - .@"i64.shl" => rr = Rr.@"i64.shl", - .@"i64.shr_s" => rr = Rr.@"i64.shr_s", - .@"i64.shr_u" => rr = Rr.@"i64.shr_u", - .@"i64.rotl" => rr = Rr.@"i64.rotl", - .@"i64.rotr" => rr = Rr.@"i64.rotr", - .@"f32.abs" => rr = Rr.@"f32.abs", - .@"f32.neg" => rr = Rr.@"f32.neg", - .@"f32.ceil" => rr = Rr.@"f32.ceil", - .@"f32.floor" => rr = Rr.@"f32.floor", - .@"f32.trunc" => rr = Rr.@"f32.trunc", - .@"f32.nearest" => rr = Rr.@"f32.nearest", - .@"f32.sqrt" => rr = Rr.@"f32.sqrt", - .@"f32.add" => rr = Rr.@"f32.add", - .@"f32.sub" => rr = Rr.@"f32.sub", - .@"f32.mul" => rr = Rr.@"f32.mul", - .@"f32.div" => rr = Rr.@"f32.div", - .@"f32.min" => rr = Rr.@"f32.min", - .@"f32.max" => rr = Rr.@"f32.max", - .@"f32.copysign" => rr = Rr.@"f32.copysign", - .@"f64.abs" => rr = Rr.@"f64.abs", - .@"f64.neg" => rr = Rr.@"f64.neg", - .@"f64.ceil" => rr = Rr.@"f64.ceil", - .@"f64.floor" => rr = Rr.@"f64.floor", - .@"f64.trunc" => rr = Rr.@"f64.trunc", - .@"f64.nearest" => rr = Rr.@"f64.nearest", - .@"f64.sqrt" => rr = Rr.@"f64.sqrt", - .@"f64.add" => rr = Rr.@"f64.add", - .@"f64.sub" => rr = Rr.@"f64.sub", - .@"f64.mul" => rr = Rr.@"f64.mul", - .@"f64.div" => rr = Rr.@"f64.div", - .@"f64.min" => rr = Rr.@"f64.min", - .@"f64.max" => rr = Rr.@"f64.max", - .@"f64.copysign" => rr = Rr.@"f64.copysign", - .@"i32.wrap_i64" => rr = Rr.@"i32.wrap_i64", - .@"i32.trunc_f32_s" => rr = Rr.@"i32.trunc_f32_s", - .@"i32.trunc_f32_u" => rr = Rr.@"i32.trunc_f32_u", - .@"i32.trunc_f64_s" => rr = Rr.@"i32.trunc_f64_s", - .@"i32.trunc_f64_u" => rr = Rr.@"i32.trunc_f64_u", - .@"i64.extend_i32_s" => rr = Rr.@"i64.extend_i32_s", - .@"i64.extend_i32_u" => rr = Rr.@"i64.extend_i32_u", - .@"i64.trunc_f32_s" => rr = Rr.@"i64.trunc_f32_s", - .@"i64.trunc_f32_u" => rr = Rr.@"i64.trunc_f32_u", - .@"i64.trunc_f64_s" => rr = Rr.@"i64.trunc_f64_s", - .@"i64.trunc_f64_u" => rr = Rr.@"i64.trunc_f64_u", - .@"f32.convert_i32_s" => rr = Rr.@"f32.convert_i32_s", - .@"f32.convert_i32_u" => rr = Rr.@"f32.convert_i32_u", - .@"f32.convert_i64_s" => rr = Rr.@"f32.convert_i64_s", - .@"f32.convert_i64_u" => rr = Rr.@"f32.convert_i64_u", - .@"f32.demote_f64" => rr = Rr.@"f32.demote_f64", - .@"f64.convert_i32_s" => rr = Rr.@"f64.convert_i32_s", - .@"f64.convert_i32_u" => rr = Rr.@"f64.convert_i32_u", - .@"f64.convert_i64_s" => rr = Rr.@"f64.convert_i64_s", - .@"f64.convert_i64_u" => rr = Rr.@"f64.convert_i64_u", - .@"f64.promote_f32" => rr = Rr.@"f64.promote_f32", - .@"i32.reinterpret_f32" => rr = Rr.@"i32.reinterpret_f32", - .@"i64.reinterpret_f64" => rr = Rr.@"i64.reinterpret_f64", - .@"f32.reinterpret_i32" => rr = Rr.@"f32.reinterpret_i32", - .@"f64.reinterpret_i64" => rr = Rr.@"f64.reinterpret_i64", - .@"i32.extend8_s" => rr = Rr.@"i32.extend8_s", - .@"i32.extend16_s" => rr = Rr.@"i32.extend16_s", - .@"i64.extend8_s" => rr = Rr.@"i64.extend8_s", - .@"i64.extend16_s" => rr = Rr.@"i64.extend16_s", - .@"i64.extend32_s" => rr = Rr.@"i64.extend32_s", + .@"i32.eqz" => {}, + .@"i32.eq" => {}, + .@"i32.ne" => {}, + .@"i32.lt_s" => {}, + .@"i32.lt_u" => {}, + .@"i32.gt_s" => {}, + .@"i32.gt_u" => {}, + .@"i32.le_s" => {}, + .@"i32.le_u" => {}, + .@"i32.ge_s" => {}, + .@"i32.ge_u" => {}, + .@"i64.eqz" => {}, + .@"i64.eq" => {}, + .@"i64.ne" => {}, + .@"i64.lt_s" => {}, + .@"i64.lt_u" => {}, + .@"i64.gt_s" => {}, + .@"i64.gt_u" => {}, + .@"i64.le_s" => {}, + .@"i64.le_u" => {}, + .@"i64.ge_s" => {}, + .@"i64.ge_u" => {}, + .@"f32.eq" => {}, + .@"f32.ne" => {}, + .@"f32.lt" => {}, + .@"f32.gt" => {}, + .@"f32.le" => {}, + .@"f32.ge" => {}, + .@"f64.eq" => {}, + .@"f64.ne" => {}, + .@"f64.lt" => {}, + .@"f64.gt" => {}, + .@"f64.le" => {}, + .@"f64.ge" => {}, + .@"i32.clz" => {}, + .@"i32.ctz" => {}, + .@"i32.popcnt" => {}, + .@"i32.add" => {}, + .@"i32.sub" => {}, + .@"i32.mul" => {}, + .@"i32.div_s" => {}, + .@"i32.div_u" => {}, + .@"i32.rem_s" => {}, + .@"i32.rem_u" => {}, + .@"i32.and" => {}, + .@"i32.or" => {}, + .@"i32.xor" => {}, + .@"i32.shl" => {}, + .@"i32.shr_s" => {}, + .@"i32.shr_u" => {}, + .@"i32.rotl" => {}, + .@"i32.rotr" => {}, + .@"i64.clz" => {}, + .@"i64.ctz" => {}, + .@"i64.popcnt" => {}, + .@"i64.add" => {}, + .@"i64.sub" => {}, + .@"i64.mul" => {}, + .@"i64.div_s" => {}, + .@"i64.div_u" => {}, + .@"i64.rem_s" => {}, + .@"i64.rem_u" => {}, + .@"i64.and" => {}, + .@"i64.or" => {}, + .@"i64.xor" => {}, + .@"i64.shl" => {}, + .@"i64.shr_s" => {}, + .@"i64.shr_u" => {}, + .@"i64.rotl" => {}, + .@"i64.rotr" => {}, + .@"f32.abs" => {}, + .@"f32.neg" => {}, + .@"f32.ceil" => {}, + .@"f32.floor" => {}, + .@"f32.trunc" => {}, + .@"f32.nearest" => {}, + .@"f32.sqrt" => {}, + .@"f32.add" => {}, + .@"f32.sub" => {}, + .@"f32.mul" => {}, + .@"f32.div" => {}, + .@"f32.min" => {}, + .@"f32.max" => {}, + .@"f32.copysign" => {}, + .@"f64.abs" => {}, + .@"f64.neg" => {}, + .@"f64.ceil" => {}, + .@"f64.floor" => {}, + .@"f64.trunc" => {}, + .@"f64.nearest" => {}, + .@"f64.sqrt" => {}, + .@"f64.add" => {}, + .@"f64.sub" => {}, + .@"f64.mul" => {}, + .@"f64.div" => {}, + .@"f64.min" => {}, + .@"f64.max" => {}, + .@"f64.copysign" => {}, + .@"i32.wrap_i64" => {}, + .@"i32.trunc_f32_s" => {}, + .@"i32.trunc_f32_u" => {}, + .@"i32.trunc_f64_s" => {}, + .@"i32.trunc_f64_u" => {}, + .@"i64.extend_i32_s" => {}, + .@"i64.extend_i32_u" => {}, + .@"i64.trunc_f32_s" => {}, + .@"i64.trunc_f32_u" => {}, + .@"i64.trunc_f64_s" => {}, + .@"i64.trunc_f64_u" => {}, + .@"f32.convert_i32_s" => {}, + .@"f32.convert_i32_u" => {}, + .@"f32.convert_i64_s" => {}, + .@"f32.convert_i64_u" => {}, + .@"f32.demote_f64" => {}, + .@"f64.convert_i32_s" => {}, + .@"f64.convert_i32_u" => {}, + .@"f64.convert_i64_s" => {}, + .@"f64.convert_i64_u" => {}, + .@"f64.promote_f32" => {}, + .@"i32.reinterpret_f32" => {}, + .@"i64.reinterpret_f64" => {}, + .@"f32.reinterpret_i32" => {}, + .@"f64.reinterpret_i64" => {}, + .@"i32.extend8_s" => {}, + .@"i32.extend16_s" => {}, + .@"i64.extend8_s" => {}, + .@"i64.extend16_s" => {}, + .@"i64.extend32_s" => {}, .@"ref.null" => { const rtype = try self.readULEB128Mem(i32); const reftype = std.meta.intToEnum(RefType, rtype) catch return error.MalformedRefType; try self.validator.validateRefNull(reftype); - rr = Rr{ .@"ref.null" = reftype }; + + try self.module.immediates.append(@as(u32, @intFromEnum(reftype))); + // rr = Rr{ .@"ref.null" = reftype }; }, - .@"ref.is_null" => rr = Rr.@"ref.is_null", + .@"ref.is_null" => {}, .@"ref.func" => { const funcidx = try self.readULEB128Mem(u32); if (funcidx >= self.module.functions.list.items.len) return error.ValidatorInvalidFunction; @@ -1044,7 +1152,8 @@ pub const Parser = struct { if (!in_references) return error.ValidatorUnreferencedFunction; } - rr = Rr{ .@"ref.func" = funcidx }; + try self.module.immediates.append(funcidx); + // rr = Rr{ .@"ref.func" = funcidx }; }, .misc => { const version = try self.readULEB128Mem(u32); @@ -1052,14 +1161,15 @@ pub const Parser = struct { try self.validator.validateMisc(misc_opcode); switch (misc_opcode) { - .@"i32.trunc_sat_f32_s" => rr = Rr{ .misc = MiscRr.@"i32.trunc_sat_f32_s" }, - .@"i32.trunc_sat_f32_u" => rr = Rr{ .misc = MiscRr.@"i32.trunc_sat_f32_u" }, - .@"i32.trunc_sat_f64_s" => rr = Rr{ .misc = MiscRr.@"i32.trunc_sat_f64_s" }, - .@"i32.trunc_sat_f64_u" => rr = Rr{ .misc = MiscRr.@"i32.trunc_sat_f64_u" }, - .@"i64.trunc_sat_f32_s" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f32_s" }, - .@"i64.trunc_sat_f32_u" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f32_u" }, - .@"i64.trunc_sat_f64_s" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f64_s" }, - .@"i64.trunc_sat_f64_u" => rr = Rr{ .misc = MiscRr.@"i64.trunc_sat_f64_u" }, + // FIXME: do I need to handle misc separately + .@"i32.trunc_sat_f32_s" => {}, + .@"i32.trunc_sat_f32_u" => {}, + .@"i32.trunc_sat_f64_s" => {}, + .@"i32.trunc_sat_f64_u" => {}, + .@"i64.trunc_sat_f32_s" => {}, + .@"i64.trunc_sat_f32_u" => {}, + .@"i64.trunc_sat_f64_s" => {}, + .@"i64.trunc_sat_f64_u" => {}, .@"memory.init" => { const dataidx = try self.readULEB128Mem(u32); const memidx = try self.readByte(); @@ -1068,14 +1178,17 @@ pub const Parser = struct { if (!(dataidx < data_count)) return error.InvalidDataIndex; if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - rr = Rr{ - .misc = MiscRr{ - .@"memory.init" = .{ - .dataidx = dataidx, - .memidx = memidx, - }, - }, - }; + + try self.module.immediates.append(dataidx); + try self.module.immediates.append(memidx); + // rr = Rr{ + // .misc = MiscRr{ + // .@"memory.init" = .{ + // .dataidx = dataidx, + // .memidx = memidx, + // }, + // }, + // }; }, .@"data.drop" => { const dataidx = try self.readULEB128Mem(u32); @@ -1083,24 +1196,28 @@ pub const Parser = struct { const data_count = self.module.data_count orelse return error.InstructionRequiresDataCountSection; if (!(dataidx < data_count)) return error.InvalidDataIndex; - rr = Rr{ .misc = MiscRr{ .@"data.drop" = dataidx } }; + try self.module.immediates.append(dataidx); + // rr = Rr{ .misc = MiscRr{ .@"data.drop" = dataidx } }; }, .@"memory.copy" => { const src_memidx = try self.readByte(); if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - const dest_memidx = try self.readByte(); + const dst_memidx = try self.readByte(); if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - rr = Rr{ .misc = MiscRr{ .@"memory.copy" = .{ - .src_memidx = src_memidx, - .dest_memidx = dest_memidx, - } } }; + try self.module.immediates.append(src_memidx); + try self.module.immediates.append(dst_memidx); + // rr = Rr{ .misc = MiscRr{ .@"memory.copy" = .{ + // .src_memidx = src_memidx, + // .dest_memidx = dest_memidx, + // } } }; }, .@"memory.fill" => { const memidx = try self.readByte(); if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - rr = Rr{ .misc = MiscRr{ .@"memory.fill" = memidx } }; + try self.module.immediates.append(memidx); + // rr = Rr{ .misc = MiscRr{ .@"memory.fill" = memidx } }; }, .@"table.init" => { const elemidx = try self.readULEB128Mem(u32); @@ -1111,31 +1228,36 @@ pub const Parser = struct { if (elemtype.reftype != tabletype.reftype) return error.MismatchedTypes; - rr = Rr{ .misc = MiscRr{ .@"table.init" = .{ - .elemidx = elemidx, - .tableidx = tableidx, - } } }; + try self.module.immediates.append(elemidx); + try self.module.immediates.append(tableidx); + // rr = Rr{ .misc = MiscRr{ .@"table.init" = .{ + // .elemidx = elemidx, + // .tableidx = tableidx, + // } } }; }, .@"elem.drop" => { const elemidx = try self.readULEB128Mem(u32); if (elemidx >= self.module.elements.list.items.len) return error.ValidatorInvalidElementIndex; - rr = Rr{ .misc = MiscRr{ .@"elem.drop" = .{ .elemidx = elemidx } } }; + try self.module.immediates.append(elemidx); + // rr = Rr{ .misc = MiscRr{ .@"elem.drop" = .{ .elemidx = elemidx } } }; }, .@"table.copy" => { - const dest_tableidx = try self.readULEB128Mem(u32); - const dest_tabletype = try self.module.tables.lookup(dest_tableidx); + const dst_tableidx = try self.readULEB128Mem(u32); + const dst_tabletype = try self.module.tables.lookup(dst_tableidx); const src_tableidx = try self.readULEB128Mem(u32); const src_tabletype = try self.module.tables.lookup(src_tableidx); - if (dest_tabletype.reftype != src_tabletype.reftype) return error.MismatchedTypes; + if (dst_tabletype.reftype != src_tabletype.reftype) return error.MismatchedTypes; - rr = Rr{ .misc = MiscRr{ .@"table.copy" = .{ - .dest_tableidx = dest_tableidx, - .src_tableidx = src_tableidx, - } } }; + try self.module.immediates.append(dst_tableidx); + try self.module.immediates.append(src_tableidx); + // rr = Rr{ .misc = MiscRr{ .@"table.copy" = .{ + // .dest_tableidx = dest_tableidx, + // .src_tableidx = src_tableidx, + // } } }; }, .@"table.grow" => { const tableidx = try self.readULEB128Mem(u32); @@ -1150,18 +1272,19 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); try self.validator.pushOperand(Type{ .Known = .I32 }); - - rr = Rr{ .misc = MiscRr{ .@"table.grow" = .{ - .tableidx = tableidx, - } } }; + try self.module.immediates.append(tableidx); + // rr = Rr{ .misc = MiscRr{ .@"table.grow" = .{ + // .tableidx = tableidx, + // } } }; }, .@"table.size" => { const tableidx = try self.readULEB128Mem(u32); if (tableidx >= self.module.tables.list.items.len) return error.ValidatorInvalidTableIndex; - rr = Rr{ .misc = MiscRr{ .@"table.size" = .{ - .tableidx = tableidx, - } } }; + try self.module.immediates.append(tableidx); + // rr = Rr{ .misc = MiscRr{ .@"table.size" = .{ + // .tableidx = tableidx, + // } } }; }, .@"table.fill" => { const tableidx = try self.readULEB128Mem(u32); @@ -1176,16 +1299,21 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); - rr = Rr{ .misc = MiscRr{ .@"table.fill" = .{ - .tableidx = tableidx, - } } }; + try self.module.immediates.append(tableidx); + // rr = Rr{ .misc = MiscRr{ .@"table.fill" = .{ + // .tableidx = tableidx, + // } } }; }, } }, } + // std.debug.print("immediates = {any}\nimmeoffset = {any}\n\n", .{ self.module.immediates.items, self.module.immediates_offset.items }); try self.validator.validate(instr); - return rr; + + try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); + + return instr; } pub fn readULEB128Mem(self: *Parser, comptime T: type) !T { diff --git a/src/rr.zig b/src/rr.zig index adc07795..072cea73 100644 --- a/src/rr.zig +++ b/src/rr.zig @@ -8,7 +8,7 @@ pub const RrOpcode = enum(u8) { loop = 0x03, @"if" = 0x04, @"else" = 0x05, - if_no_else = 0x06, + if_with_else = 0x06, end = 0x0b, br = 0x0c, br_if = 0x0d, @@ -206,13 +206,13 @@ pub const Rr = union(RrOpcode) { param_arity: u16, return_arity: u16, branch_target: u32, - else_ip: u32, }, @"else": void, - if_no_else: struct { + if_with_else: struct { param_arity: u16, return_arity: u16, branch_target: u32, + else_ip: u32, }, end: void, br: u32, From 896be6f870f93a2e2a4210b07e1145cd2922863d Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 10:15:59 +0100 Subject: [PATCH 08/16] fast_call patching --- src/instance/vm.zig | 16 ++++++++++++++-- src/module/parser.zig | 6 ++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 62a72bbf..19831a96 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -291,6 +291,17 @@ pub const VirtualMachine = struct { // Make space for locals (again, params already on stack) self.op_ptr += f.locals_count; + if (self.inst == f.instance) { + // Switch call with fast_call + self.inst.module.instructions.items[ip] = VirtualMachine.fast_call; + immediates[imm + 0] = @as(u32, @truncate(f.start)); + immediates[imm + 1] = @as(u32, @truncate(f.locals_count)); + immediates[imm + 2] = @as(u32, @truncate(function.params.len)); + immediates[imm + 3] = @as(u32, @truncate(function.results.len)); + immediates[imm + 4] = @as(u32, @truncate(f.required_stack_space)); + immediates[imm + 5] = self.inst.module.immediates_offset.items[f.start]; + } + self.inst = f.instance; // Consume parameters from the stack @@ -314,7 +325,7 @@ pub const VirtualMachine = struct { .host_function => |hf| { try hf.func(self); next_ip = ip + 1; - next_imm = imm + 1; + next_imm = imm + 6; }, } @@ -387,6 +398,7 @@ pub const VirtualMachine = struct { const params = immediates[imm + 2]; const results = immediates[imm + 3]; const required_stack_space = immediates[imm + 4]; + const next_imm = immediates[imm + 5]; // Check we have enough stack space try self.checkStackSpace(required_stack_space + locals); @@ -409,7 +421,7 @@ pub const VirtualMachine = struct { .branch_target = ip + 1, }); - return dispatch(self, start, imm + 5, instructions, immediates); + return dispatch(self, start, next_imm, instructions, immediates); } pub fn drop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { diff --git a/src/module/parser.zig b/src/module/parser.zig index 795c1d28..d3a5ead6 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -409,6 +409,12 @@ pub const Parser = struct { try self.validator.validateCall(functype); try self.module.immediates.append(funcidx); + // To allow swapping out a .call with a .fast_call we need enough space for all .fast_call immediates: + try self.module.immediates.append(0); + try self.module.immediates.append(0); + try self.module.immediates.append(0); + try self.module.immediates.append(0); + try self.module.immediates.append(0); // rr = Rr{ .call = funcidx }; // TODO: do the replacement at instantiate-time for a fastcall if in same module? From dabf6d6c35372ba1437eee7d7bc81ff229dbea0f Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 10:39:18 +0100 Subject: [PATCH 09/16] Remove panics --- src/instance/vm.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 19831a96..ff345bd0 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -184,7 +184,8 @@ pub const VirtualMachine = struct { pub fn @"else"(self: *VirtualMachine, _: usize, _: usize, instructions: []Instruction, immediates: []u32) WasmError!void { const label = self.popLabel(); - return dispatch(self, label.branch_target, @panic("lookup offset array"), instructions, immediates); + const next_imm = self.inst.module.immediates_offset.items[label.branch_target]; + return dispatch(self, label.branch_target, next_imm, instructions, immediates); } // if_no_else @@ -228,7 +229,7 @@ pub const VirtualMachine = struct { const condition = self.popOperand(u32); const next_ip = if (condition == 0) ip + 1 else self.branch(immediates[imm]); - const next_offset = if (condition == 0) imm + 1 else self.branch(@panic("Lookup offset for new instruction")); + const next_offset = self.inst.module.immediates_offset.items[next_ip]; return dispatch(self, next_ip, next_offset, instructions, immediates); } @@ -242,7 +243,7 @@ pub const VirtualMachine = struct { const ls = self.inst.module.br_table_indices.items[ls_ptr .. ls_ptr + ls_len]; const next_ip = if (i >= ls.len) self.branch(ln) else self.branch(ls[i]); - const next_imm = if (true) @panic("Lookup correct offset"); + const next_imm = self.inst.module.immediates_offset.items[next_ip]; return dispatch(self, next_ip, next_imm, instructions, immediates); } @@ -2199,7 +2200,7 @@ pub const VirtualMachine = struct { inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { // const next_instr = code[next_ip].misc; const next_instr = immediates[imm]; - const next_offset = if (true) @panic("FIXME"); + const next_offset = self.inst.module.immediates_offset.items[next_instr]; return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, next_offset, instructions, immediates }); } From 582990ea66cd3363e8dca876069b60b05a583294 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 10:49:45 +0100 Subject: [PATCH 10/16] Fix miscDispatch --- src/instance/vm.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index ff345bd0..792fe0fc 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -2202,7 +2202,7 @@ pub const VirtualMachine = struct { const next_instr = immediates[imm]; const next_offset = self.inst.module.immediates_offset.items[next_instr]; - return try @call(.always_tail, misc_lookup[@intFromEnum(next_instr)], .{ self, next_ip, next_offset, instructions, immediates }); + return try @call(.always_tail, misc_lookup[next_instr], .{ self, next_ip, next_offset, instructions, immediates }); } pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { From a77dfef766d9c17a0118cc6e33ac9a9f3626002e Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 10:54:06 +0100 Subject: [PATCH 11/16] Remove comment --- src/instance/vm.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 792fe0fc..08e15123 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -2198,7 +2198,6 @@ pub const VirtualMachine = struct { }; inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - // const next_instr = code[next_ip].misc; const next_instr = immediates[imm]; const next_offset = self.inst.module.immediates_offset.items[next_instr]; From a21a847d59faaea2d15ab68e6a62b4e45b86d7b5 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 18:17:36 +0100 Subject: [PATCH 12/16] Combine Instruction and Immediates array --- src/instance/vm.zig | 1147 ++++++++++++++++++++--------------------- src/module.zig | 29 +- src/module/parser.zig | 229 ++++---- 3 files changed, 690 insertions(+), 715 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 08e15123..e043ed8b 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -85,14 +85,13 @@ pub const VirtualMachine = struct { pub fn invoke(self: *VirtualMachine, ip: usize) !void { const instr = self.inst.module.instructions.items[ip]; - const imm = self.inst.module.immediates_offset.items[ip]; - try @call(.auto, instr, .{ self, ip, imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), self.inst.module.immediates.items }); + try @call(.auto, @as(InstructionFunction, @ptrFromInt(instr)), .{ self, ip, self.inst.module.instructions.items }); } // To avoid a recursive definition, define similar function pointer type we will cast to / from - pub const Instruction = *const fn (*VirtualMachine, usize, usize, []*void, []u32) WasmError!void; - pub const InstructionFunction = *const fn (*VirtualMachine, usize, usize, []Instruction, []u32) WasmError!void; + // pub const Instruction = *const fn (*VirtualMachine, usize, []u64) WasmError!void; + pub const InstructionFunction = *const fn (*VirtualMachine, usize, []u64) WasmError!void; pub const lookup = [256]InstructionFunction{ @"unreachable", nop, block, loop, @"if", @"else", if_with_else, impl_ni, impl_ni, impl_ni, impl_ni, end, br, br_if, br_table, @"return", @@ -113,31 +112,31 @@ pub const VirtualMachine = struct { impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, misc, impl_ni, impl_ni, impl_ni, }; - inline fn dispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + inline fn dispatch(self: *VirtualMachine, next_ip: usize, instructions: []u64) WasmError!void { const next_fn = instructions[next_ip]; - return try @call(.always_tail, @as(InstructionFunction, @ptrCast(next_fn)), .{ self, next_ip, imm, instructions, immediates }); + return try @call(.always_tail, @as(InstructionFunction, @ptrFromInt(next_fn)), .{ self, next_ip, instructions }); } pub const REF_NULL: u64 = 0xFFFF_FFFF_FFFF_FFFF; - pub fn impl_ni(_: *VirtualMachine, _: usize, _: usize, _: []Instruction, _: []u32) WasmError!void { + pub fn impl_ni(_: *VirtualMachine, _: usize, _: []u64) WasmError!void { return error.NotImplemented; } - pub fn @"unreachable"(_: *VirtualMachine, _: usize, _: usize, _: []Instruction, _: []u32) WasmError!void { + pub fn @"unreachable"(_: *VirtualMachine, _: usize, _: []u64) WasmError!void { return error.TrapUnreachable; } - pub fn nop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - return dispatch(self, ip + 1, imm, instructions, immediates); + pub fn nop(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + return dispatch(self, ip + 1, instructions); } - pub fn block(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn block(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].block; - const param_arity = immediates[imm]; - const return_arity = immediates[imm + 1]; - const branch_target = immediates[imm + 2]; + const param_arity = instructions[ip + 1]; + const return_arity = instructions[ip + 2]; + const branch_target = instructions[ip + 3]; try self.pushLabel(Label{ .return_arity = return_arity, @@ -145,14 +144,14 @@ pub const VirtualMachine = struct { .branch_target = branch_target, }); - return dispatch(self, ip + 1, imm + 3, instructions, immediates); + return dispatch(self, ip + 4, instructions); } - pub fn loop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const param_arity = immediates[imm]; - const return_arity = immediates[imm + 1]; + pub fn loop(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const param_arity = instructions[ip + 1]; + const return_arity = instructions[ip + 2]; _ = return_arity; - const branch_target = immediates[imm + 2]; + const branch_target = instructions[ip + 3]; try self.pushLabel(Label{ // note that we use block_params rather than block_returns for return arity: @@ -161,14 +160,14 @@ pub const VirtualMachine = struct { .branch_target = branch_target, }); - return dispatch(self, ip + 1, imm + 3, instructions, immediates); + return dispatch(self, ip + 4, instructions); } - pub fn if_with_else(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const param_arity = immediates[imm]; - const return_arity = immediates[imm + 1]; - const branch_target = immediates[imm + 2]; - const else_ip = immediates[imm + 3]; + pub fn if_with_else(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const param_arity = instructions[ip + 1]; + const return_arity = instructions[ip + 2]; + const branch_target = instructions[ip + 3]; + const else_ip = instructions[ip + 4]; const condition = self.popOperand(u32); @@ -178,29 +177,29 @@ pub const VirtualMachine = struct { .branch_target = branch_target, }); - return dispatch(self, if (condition == 0) else_ip else ip + 1, imm + 4, instructions, immediates); + return dispatch(self, if (condition == 0) else_ip else ip + 5, instructions); } - pub fn @"else"(self: *VirtualMachine, _: usize, _: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"else"(self: *VirtualMachine, _: usize, instructions: []u64) WasmError!void { const label = self.popLabel(); - const next_imm = self.inst.module.immediates_offset.items[label.branch_target]; - return dispatch(self, label.branch_target, next_imm, instructions, immediates); + return dispatch(self, label.branch_target, instructions); } // if_no_else - pub fn @"if"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"if"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].if_no_else; - const param_arity = immediates[imm]; - const return_arity = immediates[imm + 1]; - const branch_target = immediates[imm + 2]; - _ = immediates[imm + 3]; + const param_arity = instructions[ip + 1]; + const return_arity = instructions[ip + 2]; + const branch_target = instructions[ip + 3]; + const else_ip = instructions[ip + 4]; + _ = else_ip; + // std.debug.print("{}: if[{}, {}, {}, {}]\n", .{ ip, param_arity, return_arity, branch_target, else_ip }); const condition = self.popOperand(u32); if (condition == 0) { - const next_imm = self.inst.module.immediates_offset.items[branch_target]; - return dispatch(self, branch_target, next_imm, instructions, immediates); + return dispatch(self, branch_target, instructions); } else { // We are inside the if branch try self.pushLabel(Label{ @@ -209,46 +208,46 @@ pub const VirtualMachine = struct { .branch_target = branch_target, }); - return dispatch(self, ip + 1, imm + 4, instructions, immediates); + return dispatch(self, ip + 5, instructions); } } - pub fn end(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn end(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { _ = self.popLabel(); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn br(self: *VirtualMachine, _: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const next_ip = self.branch(immediates[imm]); + pub fn br(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const next_ip = self.branch(instructions[ip]); - return dispatch(self, next_ip, imm + 1, instructions, immediates); + return dispatch(self, next_ip, instructions); } - pub fn br_if(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn br_if(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const condition = self.popOperand(u32); - const next_ip = if (condition == 0) ip + 1 else self.branch(immediates[imm]); - const next_offset = self.inst.module.immediates_offset.items[next_ip]; + const next_ip = if (condition == 0) ip + 1 else self.branch(instructions[ip]); - return dispatch(self, next_ip, next_offset, instructions, immediates); + return dispatch(self, next_ip, instructions); } - pub fn br_table(self: *VirtualMachine, _: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const ls_ptr = immediates[imm]; - const ls_len = immediates[imm + 1]; - const ln = immediates[imm + 2]; + pub fn br_table(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const ls_ptr = instructions[ip + 1]; + const ls_len = instructions[ip + 2]; + const ln = instructions[ip + 3]; const i = self.popOperand(u32); const ls = self.inst.module.br_table_indices.items[ls_ptr .. ls_ptr + ls_len]; const next_ip = if (i >= ls.len) self.branch(ln) else self.branch(ls[i]); - const next_imm = self.inst.module.immediates_offset.items[next_ip]; - return dispatch(self, next_ip, next_imm, instructions, immediates); + return dispatch(self, next_ip, instructions); } - pub fn @"return"(self: *VirtualMachine, _: usize, _: usize, _: []Instruction, immediates: []u32) WasmError!void { + pub fn @"return"(self: *VirtualMachine, ip: usize, _: []u64) WasmError!void { + _ = ip; + // std.debug.print("{}: return[]\n", .{ip}); const frame = self.peekFrame(); const n = frame.return_arity; @@ -272,17 +271,15 @@ pub const VirtualMachine = struct { self.inst = previous_frame.inst; // FIXME: probably reference previous frame - const branch_target_immediate_offset = self.inst.module.immediates_offset.items[label.branch_target]; - return dispatch(self, label.branch_target, branch_target_immediate_offset, @as([]Instruction, @ptrCast(previous_frame.inst.module.instructions.items)), immediates); + return dispatch(self, label.branch_target, previous_frame.inst.module.instructions.items); } - pub fn call(self: *VirtualMachine, ip: usize, imm: usize, _: []Instruction, immediates: []u32) WasmError!void { + pub fn call(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const funcidx = code[ip].call; - const funcidx = immediates[imm]; + const funcidx = instructions[ip + 1]; const function = try self.inst.getFunc(funcidx); var next_ip = ip; - var next_imm = imm; switch (function.subtype) { .function => |f| { @@ -294,13 +291,12 @@ pub const VirtualMachine = struct { if (self.inst == f.instance) { // Switch call with fast_call - self.inst.module.instructions.items[ip] = VirtualMachine.fast_call; - immediates[imm + 0] = @as(u32, @truncate(f.start)); - immediates[imm + 1] = @as(u32, @truncate(f.locals_count)); - immediates[imm + 2] = @as(u32, @truncate(function.params.len)); - immediates[imm + 3] = @as(u32, @truncate(function.results.len)); - immediates[imm + 4] = @as(u32, @truncate(f.required_stack_space)); - immediates[imm + 5] = self.inst.module.immediates_offset.items[f.start]; + self.inst.module.instructions.items[ip] = @as(u64, @intFromPtr(&VirtualMachine.fast_call)); + instructions[ip + 1] = f.start; + instructions[ip + 2] = f.locals_count; + instructions[ip + 3] = function.params.len; + instructions[ip + 4] = function.results.len; + instructions[ip + 5] = f.required_stack_space; } self.inst = f.instance; @@ -317,29 +313,27 @@ pub const VirtualMachine = struct { try self.pushLabel(Label{ .return_arity = function.results.len, .op_stack_len = self.op_ptr - function.params.len - f.locals_count, - .branch_target = ip + 1, + .branch_target = ip + 6, }); next_ip = f.start; - next_imm = self.inst.module.immediates_offset.items[f.start]; }, .host_function => |hf| { try hf.func(self); - next_ip = ip + 1; - next_imm = imm + 6; + next_ip = ip + 6; }, } // FIXME: - return dispatch(self, next_ip, next_imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), immediates); + return dispatch(self, next_ip, @as([]u64, @ptrCast(self.inst.module.instructions.items))); } - pub fn call_indirect(self: *VirtualMachine, ip: usize, imm: usize, _: []Instruction, immediates: []u32) WasmError!void { + pub fn call_indirect(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const call_indirect_instruction = code[ip].call_indirect; var module = self.inst.module; - const typeidx = immediates[imm]; - const tableidx = immediates[imm + 1]; + const typeidx = instructions[ip + 1]; + const tableidx = instructions[ip + 2]; // Read lookup index from stack const lookup_index = self.popOperand(u32); @@ -352,7 +346,6 @@ pub const VirtualMachine = struct { try function.checkSignatures(call_indirect_func_type); var next_ip = ip; - var next_imm = imm; switch (function.subtype) { .function => |func| { @@ -376,7 +369,7 @@ pub const VirtualMachine = struct { try self.pushLabel(Label{ .return_arity = function.results.len, .op_stack_len = self.op_ptr - function.params.len - func.locals_count, - .branch_target = ip + 1, + .branch_target = ip + 3, }); next_ip = func.start; @@ -384,22 +377,20 @@ pub const VirtualMachine = struct { .host_function => |host_func| { try host_func.func(self); - next_ip = ip + 1; - next_imm = imm + 1; + next_ip = ip + 3; }, } - return dispatch(self, next_ip, next_imm, @as([]Instruction, @ptrCast(self.inst.module.instructions.items)), immediates); + return dispatch(self, next_ip, self.inst.module.instructions.items); } - pub fn fast_call(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn fast_call(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const f = code[ip].fast_call; - const start = immediates[imm]; - const locals = immediates[imm + 1]; - const params = immediates[imm + 2]; - const results = immediates[imm + 3]; - const required_stack_space = immediates[imm + 4]; - const next_imm = immediates[imm + 5]; + const start = instructions[ip + 1]; + const locals = instructions[ip + 2]; + const params = instructions[ip + 3]; + const results = instructions[ip + 4]; + const required_stack_space = instructions[ip + 5]; // Check we have enough stack space try self.checkStackSpace(required_stack_space + locals); @@ -419,18 +410,18 @@ pub const VirtualMachine = struct { try self.pushLabel(Label{ .return_arity = results, .op_stack_len = self.op_ptr - params - locals, - .branch_target = ip + 1, + .branch_target = ip + 6, }); - return dispatch(self, start, next_imm, instructions, immediates); + return dispatch(self, start, instructions); } - pub fn drop(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn drop(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { _ = self.popAnyOperand(); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn select(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn select(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const condition = self.popOperand(u32); const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -441,60 +432,61 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, c2); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"local.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const localidx = immediates[imm]; + pub fn @"local.get"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const localidx = instructions[ip + 1]; + // std.debug.print("{}: local.get[{}]\n", .{ ip, localidx }); const frame = self.peekFrame(); self.pushOperandNoCheck(u64, frame.locals[localidx]); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"local.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const localidx = immediates[imm]; + pub fn @"local.set"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const localidx = instructions[ip + 1]; const frame = self.peekFrame(); frame.locals[localidx] = self.popOperand(u64); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"local.tee"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const localidx = immediates[imm]; + pub fn @"local.tee"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const localidx = instructions[ip + 1]; const frame = self.peekFrame(); frame.locals[localidx] = self.peekOperand(); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"global.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const globalidx = immediates[imm]; + pub fn @"global.get"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const globalidx = instructions[ip + 1]; const global = try self.inst.getGlobal(globalidx); self.pushOperandNoCheck(u64, global.value); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"global.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const globalidx = immediates[imm]; + pub fn @"global.set"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const globalidx = instructions[ip + 1]; const value = self.popAnyOperand(); const global = try self.inst.getGlobal(globalidx); global.value = value; - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.get"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const tableidx = immediates[imm]; + pub fn @"table.get"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const tableidx = instructions[ip + 1]; const table = try self.inst.getTable(tableidx); const index = self.popOperand(u32); @@ -506,11 +498,11 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, REF_NULL); } - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.set"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const tableidx = immediates[imm]; + pub fn @"table.set"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const tableidx = instructions[ip + 1]; const table = try self.inst.getTable(tableidx); const ref = self.popOperand(u64); @@ -518,13 +510,13 @@ pub const VirtualMachine = struct { try table.set(index, ref); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"i32.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.load"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -532,13 +524,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -546,13 +538,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"f32.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"f32.load"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -560,13 +552,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"f64.load"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"f64.load"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -574,13 +566,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.load8_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -588,13 +580,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.load8_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -602,13 +594,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.load16_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -616,13 +608,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.load16_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -630,13 +622,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load8_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -644,13 +636,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load8_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -658,13 +650,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load16_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -672,13 +664,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load16_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -686,13 +678,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -700,13 +692,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.load32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const address = self.popOperand(u32); @@ -714,13 +706,13 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.store"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value = self.popOperand(u32); @@ -728,13 +720,13 @@ pub const VirtualMachine = struct { try memory.write(u32, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.store"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value = self.popOperand(u64); @@ -742,13 +734,13 @@ pub const VirtualMachine = struct { try memory.write(u64, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"f32.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"f32.store"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value = self.popOperand(f32); @@ -756,13 +748,13 @@ pub const VirtualMachine = struct { try memory.write(f32, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"f64.store"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"f64.store"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value = self.popOperand(f64); @@ -770,13 +762,13 @@ pub const VirtualMachine = struct { try memory.write(f64, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.store8"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.store8"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value: u8 = @truncate(self.popOperand(u32)); @@ -784,13 +776,13 @@ pub const VirtualMachine = struct { try memory.write(u8, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i32.store16"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i32.store16"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value: u16 = @truncate(self.popOperand(u32)); @@ -798,13 +790,13 @@ pub const VirtualMachine = struct { try memory.write(u16, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.store8"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.store8"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value: u8 = @truncate(self.popOperand(u64)); @@ -812,13 +804,13 @@ pub const VirtualMachine = struct { try memory.write(u8, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.store16"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.store16"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value: u16 = @truncate(self.popOperand(u64)); @@ -826,13 +818,13 @@ pub const VirtualMachine = struct { try memory.write(u16, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"i64.store32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const alignment = immediates[imm]; + pub fn @"i64.store32"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const alignment = @as(u32, @intCast(instructions[ip + 1])); _ = alignment; - const offset = immediates[imm + 1]; + const offset = @as(u32, @intCast(instructions[ip + 2])); const memory = try self.inst.getMemory(0); const value: u32 = @truncate(self.popOperand(u64)); @@ -840,18 +832,18 @@ pub const VirtualMachine = struct { try memory.write(u32, offset, address, value); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"memory.size"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"memory.size"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const memory = try self.inst.getMemory(0); self.pushOperandNoCheck(u32, @as(u32, @intCast(memory.size()))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const memory = try self.inst.getMemory(0); const num_pages = self.popOperand(u32); @@ -861,398 +853,396 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const literal = @as(i32, @intCast(immediates[imm])); + pub fn @"i32.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const literal = @as(i32, @intCast(instructions[ip + 1])); + // std.debug.print("{}: i32.const[{}]\n", .{ ip, literal }); self.pushOperandNoCheck(i32, literal); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"i64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const lower = immediates[imm]; - const upper = immediates[imm + 1]; - const literal = @as(i64, @intCast((@as(u64, upper) << 32) + lower)); + pub fn @"i64.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const literal = @as(i64, @intCast(instructions[ip + 1])); self.pushOperandNoCheck(i64, literal); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"f32.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const literal = @as(f32, @floatFromInt(immediates[imm])); + pub fn @"f32.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const literal = @as(f32, @floatFromInt(instructions[ip + 1])); self.pushOperandNoCheck(f32, literal); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"f64.const"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const lower = immediates[imm]; - const upper = immediates[imm + 1]; - const literal = @as(f64, @floatFromInt((@as(u64, upper) << 32) + lower)); + pub fn @"f64.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const literal = @as(f64, @floatFromInt(instructions[ip + 1])); self.pushOperandNoCheck(f64, literal); - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.eqz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.eq"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + // std.debug.print("{}: i32.eq[]\n", .{ip}); const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.ne"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.lt_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.lt_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.gt_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.gt_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.le_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.le_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.le_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.le_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.ge_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.ge_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @as(u32, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.eqz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.eqz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == 0) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.eq"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.ne"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.lt_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.lt_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.gt_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.gt_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.le_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.le_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.le_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.le_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.ge_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.ge_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.eq"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.ne"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.lt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.lt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.gt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.gt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.le"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.le"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.ge"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.ge"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.eq"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.eq"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 == c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.ne"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.ne"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 != c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.lt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.lt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 < c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.gt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.gt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 > c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.le"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.le"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 <= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.ge"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.ge"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(u64, @as(u64, if (c1 >= c2) 1 else 0)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.clz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.clz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @clz(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.ctz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.ctz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @ctz(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.popcnt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, @popCount(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.add"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 +% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.sub"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 -% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.mul"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 *% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.div_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.div_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1260,10 +1250,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, div); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.div_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.div_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1271,10 +1261,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, div); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.rem_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1283,10 +1273,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, rem); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.rem_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); @@ -1294,46 +1284,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, rem); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.and"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.and"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 & c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.or"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.or"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 | c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.xor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.xor"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, c1 ^ c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.shl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.shl"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.shr_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i32); const c1 = self.popOperand(i32); @@ -1341,85 +1331,85 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, math.shr(i32, c1, mod)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.shr_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.shr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.rotl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.rotl"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotl(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.rotr"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.rotr"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u32); const c1 = self.popOperand(u32); self.pushOperandNoCheck(u32, math.rotr(u32, c1, c2 % 32)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.clz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.clz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @clz(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.ctz"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.ctz"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @ctz(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.popcnt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @popCount(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.add"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 +% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.sub"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 -% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.mul"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 *% c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.div_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.div_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1427,10 +1417,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, div); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.div_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.div_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1438,10 +1428,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, div); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.rem_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1450,10 +1440,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, rem); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.rem_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); @@ -1461,46 +1451,46 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, rem); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.and"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.and"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 & c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.or"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.or"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 | c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.xor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.xor"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, c1 ^ c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.shl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.shl"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.shr_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(i64); const c1 = self.popOperand(i64); @@ -1508,77 +1498,77 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, math.shr(i64, c1, mod)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.shr_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.shr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.rotl"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.rotl"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotl(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.rotr"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.rotr"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(u64); const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, math.rotr(u64, c1, c2 % 64)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.abs"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.abs"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.fabs(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.neg"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.neg"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, -c1); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.ceil"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.ceil"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @ceil(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.floor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.floor"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @floor(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.trunc"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.trunc"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, @trunc(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.nearest"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.nearest"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1593,64 +1583,64 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @round(c1)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.sqrt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, math.sqrt(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.add"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 + c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.sub"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 - c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.mul"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 * c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.div"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.div"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); self.pushOperandNoCheck(f32, c1 / c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.min"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.min"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1663,20 +1653,20 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @min(c1, c2)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.max"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.max"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); if (math.isNan(c1)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (math.isNan(c2)) { self.pushOperandNoCheck(f32, math.nan_f32); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1689,10 +1679,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, @max(c1, c2)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.copysign"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.copysign"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f32); const c1 = self.popOperand(f32); @@ -1702,50 +1692,50 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f32, math.fabs(c1)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.abs"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.abs"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.fabs(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.neg"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.neg"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, -c1); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.ceil"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.ceil"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @ceil(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.floor"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.floor"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @floor(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.trunc"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.trunc"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, @trunc(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.nearest"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.nearest"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); const floor = @floor(c1); const ceil = @ceil(c1); @@ -1760,60 +1750,60 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @round(c1)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.sqrt"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, math.sqrt(c1)); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.add"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.add"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 + c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.sub"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.sub"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 - c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.mul"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.mul"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 * c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.div"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.div"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); self.pushOperandNoCheck(f64, c1 / c2); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.min"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.min"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1826,16 +1816,16 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @min(c1, c2)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.max"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.max"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); if (math.isNan(c1) or math.isNan(c2)) { self.pushOperandNoCheck(f64, math.nan_f64); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (c1 == 0.0 and c2 == 0.0) { @@ -1848,10 +1838,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, @max(c1, c2)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.copysign"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.copysign"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c2 = self.popOperand(f64); const c1 = self.popOperand(f64); @@ -1861,18 +1851,18 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(f64, math.fabs(c1)); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.wrap_i64"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i32, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_f32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1884,10 +1874,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_f32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1899,10 +1889,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_f64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1914,10 +1904,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_f64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1929,26 +1919,26 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.extend_i32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.extend_i32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(u64, @as(u32, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_f32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1960,10 +1950,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_f32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); if (math.isNan(c1)) return error.InvalidConversion; @@ -1975,10 +1965,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_f64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -1990,10 +1980,10 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_f64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); if (math.isNan(c1)) return error.InvalidConversion; @@ -2005,168 +1995,168 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.convert_i32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.convert_i32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.convert_i64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.convert_i64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f32, @as(f32, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.demote_f64"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(f32, @as(f32, @floatCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.convert_i32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.convert_i32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u32); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.convert_i64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.convert_i64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(u64); self.pushOperandNoCheck(f64, @as(f64, @floatFromInt(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.promote_f32"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(f64, @as(f64, @floatCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.reinterpret_f32"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); self.pushOperandNoCheck(i32, @as(i32, @bitCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.reinterpret_f64"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); self.pushOperandNoCheck(i64, @as(i64, @bitCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f32.reinterpret_i32"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(f32, @as(f32, @bitCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"f64.reinterpret_i64"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(f64, @as(f64, @bitCast(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.extend8_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.extend16_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i32); self.pushOperandNoCheck(i32, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.extend8_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i8, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.extend16_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i16, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.extend32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(i64); self.pushOperandNoCheck(i64, @as(i32, @truncate(c1))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"ref.null"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"ref.null"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { self.pushOperandNoCheck(u64, REF_NULL); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const value = self.popOperand(u64); if (value == REF_NULL) { @@ -2175,21 +2165,21 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u64, 0); } - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"ref.func"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const funcidx = immediates[imm]; + pub fn @"ref.func"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const funcidx = instructions[ip + 1]; const ref = self.inst.funcaddrs.items[funcidx]; // Not sure about this at all, this could still coincidentally be zero? self.pushOperandNoCheck(u64, ref); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn misc(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - return miscDispatch(self, ip, imm, instructions, immediates); + pub fn misc(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + return miscDispatch(self, ip, instructions); } const misc_lookup = [18]InstructionFunction{ @@ -2197,193 +2187,192 @@ pub const VirtualMachine = struct { @"table.size", @"table.fill", }; - inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const next_instr = immediates[imm]; - const next_offset = self.inst.module.immediates_offset.items[next_instr]; + inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, instructions: []u64) WasmError!void { + const next_instr = instructions[next_ip + 1]; - return try @call(.always_tail, misc_lookup[next_instr], .{ self, next_ip, next_offset, instructions, immediates }); + return try @call(.always_tail, misc_lookup[next_instr], .{ self, next_ip, instructions }); } - pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i32, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x7fffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(i32)))) { self.pushOperandNoCheck(i32, @as(i32, @bitCast(@as(u32, 0x80000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(i32, @as(i32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i32.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u32, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0xffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(u32)))) { self.pushOperandNoCheck(u32, @as(u32, @bitCast(@as(u32, 0x00000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(u32, @as(u32, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_sat_f32_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f32, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f32, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_sat_f64_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(i64, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x7fffffffffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(i64)))) { self.pushOperandNoCheck(i64, @as(i64, @bitCast(@as(u64, 0x8000000000000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(i64, @as(i64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"i64.trunc_sat_f64_u"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f64); const trunc = @trunc(c1); if (math.isNan(c1)) { self.pushOperandNoCheck(u64, 0); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc >= @as(f64, @floatFromInt(math.maxInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0xffffffffffffffff)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } if (trunc < @as(f64, @floatFromInt(math.minInt(u64)))) { self.pushOperandNoCheck(u64, @as(u64, @bitCast(@as(u64, 0x0000000000000000)))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } self.pushOperandNoCheck(u64, @as(u64, @intFromFloat(trunc))); - return dispatch(self, ip + 1, imm, instructions, immediates); + return dispatch(self, ip + 1, instructions); } - pub fn @"memory.init"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"memory.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"memory.init"; - const memidx = immediates[imm]; - const dataidx = immediates[imm + 1]; + const memidx = instructions[ip + 1]; + const dataidx = instructions[ip + 2]; const n = self.popOperand(u32); const src = self.popOperand(u32); @@ -2396,7 +2385,7 @@ pub const VirtualMachine = struct { if (@as(u33, src) + @as(u33, n) > data.data.len) return error.OutOfBoundsMemoryAccess; if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } if (data.dropped) return error.OutOfBoundsMemoryAccess; @@ -2406,23 +2395,23 @@ pub const VirtualMachine = struct { try memory.write(u8, 0, dest + i, data.data[src + i]); } - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"data.drop"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"data.drop"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const dataidx = code[ip].misc.@"data.drop"; - const dataidx = immediates[imm]; + const dataidx = instructions[ip + 1]; const data = try self.inst.getData(dataidx); data.dropped = true; - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"memory.copy"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"memory.copy"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // FIXME: use these when we support multiple memories - const src_memidx = immediates[imm]; + const src_memidx = instructions[ip + 1]; _ = src_memidx; - const dst_memidx = immediates[imm + 1]; + const dst_memidx = instructions[ip + 2]; _ = dst_memidx; const n = self.popOperand(u32); @@ -2436,7 +2425,7 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } // FIXME: move initial bounds check into Memory implementation @@ -2447,11 +2436,11 @@ pub const VirtualMachine = struct { memory.uncheckedCopyBackwards(dest, data[src .. src + n]); } - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"memory.fill"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - _ = immediates[imm]; + pub fn @"memory.fill"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + _ = instructions[ip + 1]; const n = self.popOperand(u32); const value = self.popOperand(u32); @@ -2462,18 +2451,18 @@ pub const VirtualMachine = struct { if (@as(u33, dest) + @as(u33, n) > mem_size) return error.OutOfBoundsMemoryAccess; if (n == 0) { - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } memory.uncheckedFill(dest, n, @as(u8, @truncate(value))); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.init"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"table.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"table.init"; - const tableidx = immediates[imm]; - const elemidx = immediates[imm + 1]; + const tableidx = instructions[ip + 1]; + const elemidx = instructions[ip + 2]; const table = try self.inst.getTable(tableidx); const elem = try self.inst.getElem(elemidx); @@ -2496,24 +2485,24 @@ pub const VirtualMachine = struct { try table.set(d + i, elem.elem[s + i]); } - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"elem.drop"; - const elemidx = immediates[imm]; + const elemidx = instructions[ip + 1]; const elem = try self.inst.getElem(elemidx); elem.dropped = true; - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.copy"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { + pub fn @"table.copy"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"table.copy"; // const dest_tableidx = meta.dest_tableidx; // const src_tableidx = meta.src_tableidx; - const dst_tableidx = immediates[imm]; - const src_tableidx = immediates[imm + 1]; + const dst_tableidx = instructions[ip + 1]; + const src_tableidx = instructions[ip + 2]; const dest_table = try self.inst.getTable(dst_tableidx); const src_table = try self.inst.getTable(src_tableidx); @@ -2541,11 +2530,11 @@ pub const VirtualMachine = struct { } } - return dispatch(self, ip + 1, imm + 2, instructions, immediates); + return dispatch(self, ip + 3, instructions); } - pub fn @"table.grow"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const tableidx = immediates[imm]; + pub fn @"table.grow"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const tableidx = instructions[ip + 1]; const table = try self.inst.getTable(tableidx); @@ -2562,21 +2551,21 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.size"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const tableidx = immediates[imm]; + pub fn @"table.size"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const tableidx = instructions[ip + 1]; const table = try self.inst.getTable(tableidx); self.pushOperandNoCheck(u32, @as(u32, @intCast(table.size()))); - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } - pub fn @"table.fill"(self: *VirtualMachine, ip: usize, imm: usize, instructions: []Instruction, immediates: []u32) WasmError!void { - const tableidx = immediates[imm]; + pub fn @"table.fill"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + const tableidx = instructions[ip + 1]; const table = try self.inst.getTable(tableidx); @@ -2594,11 +2583,11 @@ pub const VirtualMachine = struct { try table.set(d + i, ref); } - return dispatch(self, ip + 1, imm + 1, instructions, immediates); + return dispatch(self, ip + 2, instructions); } // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-control-mathsf-br-l - pub fn branch(self: *VirtualMachine, target: u32) usize { + pub fn branch(self: *VirtualMachine, target: u64) usize { const label = self.peekNthLabel(target); const n = label.return_arity; @@ -2718,7 +2707,7 @@ pub const VirtualMachine = struct { // // Returns nth label on the Label stack relative to the top of the stack // - pub fn peekNthLabel(self: *VirtualMachine, index: u32) *Label { + pub fn peekNthLabel(self: *VirtualMachine, index: u64) *Label { return &self.label_stack[self.label_ptr - index - 1]; } @@ -2728,7 +2717,7 @@ pub const VirtualMachine = struct { // // popLabels pops labels up to and including `target`. Returns the // the label at `target`. - pub fn popLabels(self: *VirtualMachine, target: u32) Label { + pub fn popLabels(self: *VirtualMachine, target: u64) Label { defer self.label_ptr = self.label_ptr - target - 1; return self.label_stack[self.label_stack.len - target - 1]; diff --git a/src/module.zig b/src/module.zig index fbd4a181..ec5bf8ea 100644 --- a/src/module.zig +++ b/src/module.zig @@ -36,9 +36,7 @@ pub const Module = struct { data_count: ?u32 = null, element_init_offsets: ArrayList(usize), // parsed_code: ArrayList(Rr), - instructions: ArrayList(VirtualMachine.InstructionFunction), - immediates_offset: ArrayList(u32), - immediates: ArrayList(u32), + instructions: ArrayList(u64), local_types: ArrayList(LocalType), br_table_indices: ArrayList(u32), references: ArrayList(u32), @@ -61,9 +59,7 @@ pub const Module = struct { .datas = Section(DataSegment).init(alloc), .element_init_offsets = ArrayList(usize).init(alloc), // .parsed_code = ArrayList(Rr).init(alloc), - .instructions = ArrayList(VirtualMachine.InstructionFunction).init(alloc), - .immediates_offset = ArrayList(u32).init(alloc), - .immediates = ArrayList(u32).init(alloc), + .instructions = ArrayList(u64).init(alloc), .local_types = ArrayList(LocalType).init(alloc), .br_table_indices = ArrayList(u32).init(alloc), .references = ArrayList(u32).init(alloc), @@ -86,8 +82,6 @@ pub const Module = struct { self.element_init_offsets.deinit(); // self.parsed_code.deinit(); self.instructions.deinit(); - self.immediates_offset.deinit(); - self.immediates.deinit(); self.local_types.deinit(); self.br_table_indices.deinit(); self.references.deinit(); @@ -106,8 +100,7 @@ pub const Module = struct { // Push an initial return instruction so we don't have to // track the end of a function to use its return on invoke // See https://github.com/malcolmstill/zware/pull/133 - try self.instructions.append(VirtualMachine.@"return"); - try self.immediates_offset.append(0); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); var i: usize = 0; while (true) : (i += 1) { @@ -487,9 +480,9 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try self.instructions.append(VirtualMachine.@"ref.func"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); // try self.parsed_code.append(Rr.@"return"); - try self.instructions.append(VirtualMachine.@"return"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); } @@ -520,9 +513,9 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try self.instructions.append(VirtualMachine.@"ref.func"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); // try self.parsed_code.append(Rr.@"return"); - try self.instructions.append(VirtualMachine.@"return"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); } @@ -555,9 +548,9 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try self.instructions.append(VirtualMachine.@"ref.func"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); // try self.parsed_code.append(Rr.@"return"); - try self.instructions.append(VirtualMachine.@"return"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); } @@ -587,9 +580,9 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); - try self.instructions.append(VirtualMachine.@"ref.func"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); // try self.parsed_code.append(Rr.@"return"); - try self.instructions.append(VirtualMachine.@"return"); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); } diff --git a/src/module/parser.zig b/src/module/parser.zig index d3a5ead6..837308f1 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -70,7 +70,7 @@ pub const Parser = struct { // FIXME: might setting .block in ControlFrame mean we don't have to replace final end with return? // Patch last end so that it is return - self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; + self.module.instructions.items[self.module.instructions.items.len - 1] = @as(u64, @intFromPtr(&VirtualMachine.@"return")); return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; } @@ -113,7 +113,7 @@ pub const Parser = struct { // FIXME: might setting .block in ControlFrame mean we don't have to replace final end with return? // Patch last end so that it is return - self.module.instructions.items[self.module.instructions.items.len - 1] = VirtualMachine.@"return"; + self.module.instructions.items[self.module.instructions.items.len - 1] = @as(u64, @intFromPtr(&VirtualMachine.@"return")); return Parsed{ .start = code_start, .max_depth = self.validator.max_depth }; } @@ -158,7 +158,7 @@ pub const Parser = struct { } pub fn next(self: *Parser) !?Opcode { - defer self.code_ptr += 1; + defer self.code_ptr = self.module.instructions.items.len; if (self.scope > 0 and self.code.len == 0) return error.CouldntFindEnd; if (self.code.len == 0) return null; @@ -168,12 +168,12 @@ pub const Parser = struct { const instr = std.meta.intToEnum(Opcode, self.code[0]) catch return error.IllegalOpcode; self.code = self.code[1..]; - // Record the start of this instruction's immediates - const immediates_count = std.math.cast(u32, self.module.immediates.items.len) orelse return error.TooManyImmediates; // FIXME: error or assert - try self.module.immediates_offset.append(immediates_count); - // std.debug.print("instr[{}] = {}, immediate offset = {}\n", .{ self.code_ptr, instr, immediates_count }); + // std.debug.print("instr = {}\n", .{instr}); + // defer std.debug.print("{any}\n\n", .{self.module.instructions.items}); + try self.module.instructions.append(@as(u64, @intFromPtr(VirtualMachine.lookup[@intFromEnum(instr)]))); + // 2. Find the start of the next instruction switch (instr) { .@"unreachable" => {}, @@ -209,9 +209,9 @@ pub const Parser = struct { try self.pushContinuationStack(self.code_ptr, .block); self.scope += 1; - try self.module.immediates.append(block_params); - try self.module.immediates.append(block_returns); - try self.module.immediates.append(0); + try self.module.instructions.append(block_params); + try self.module.instructions.append(block_returns); + try self.module.instructions.append(0); // Rr{ // .block = .{ @@ -251,9 +251,9 @@ pub const Parser = struct { try self.pushContinuationStack(self.code_ptr, .loop); self.scope += 1; - try self.module.immediates.append(block_params); - try self.module.immediates.append(block_params); - try self.module.immediates.append(math.cast(u32, self.code_ptr) orelse return error.FailedCast); + try self.module.instructions.append(block_params); + try self.module.instructions.append(block_params); + try self.module.instructions.append(math.cast(u32, self.code_ptr) orelse return error.FailedCast); // rr = Rr{ // .loop = .{ @@ -298,12 +298,12 @@ pub const Parser = struct { try self.pushContinuationStack(self.code_ptr, .@"if"); self.scope += 1; - try self.module.immediates.append(block_params); - try self.module.immediates.append(block_returns); - try self.module.immediates.append(0); + try self.module.instructions.append(block_params); + try self.module.instructions.append(block_returns); + try self.module.instructions.append(0); // an if with no else only has 3 immediates, but we push a fourth here // so we can exchange the if with an if_with_else - try self.module.immediates.append(0); + try self.module.instructions.append(0); // FIXME: we have found an if, but we were actually pushing an if_no_else // i.e. we assume we don't have an else until we find one (and if we @@ -321,12 +321,11 @@ pub const Parser = struct { }, .@"else" => { const pushed_instruction = try self.peekContinuationStack(); - const immediates_offset = self.module.immediates_offset.items[pushed_instruction.offset]; switch (pushed_instruction.opcode) { .@"if" => { - self.module.immediates.items[immediates_offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; - self.module.instructions.items[pushed_instruction.offset] = VirtualMachine.if_with_else; + // std.debug.print("pushed_instruction.offset = {}\n", .{pushed_instruction.offset}); + self.module.instructions.items[pushed_instruction.offset] = @as(u64, @intFromPtr(&VirtualMachine.if_with_else)); }, else => return error.UnexpectedInstruction, } @@ -338,22 +337,21 @@ pub const Parser = struct { // If we're not looking at the `end` of a function if (self.scope != 0) { const pushed_instruction = try self.popContinuationStack(); - const immediate_offset = self.module.immediates_offset.items[pushed_instruction.offset]; // std.debug.print("instr[{}]: end immediate_offset = {}\n", .{ pushed_instruction.offset, immediate_offset }); switch (pushed_instruction.opcode) { - .block => self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, + .block => self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, .loop => {}, .if_with_else => { - self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, .@"if" => { - const param_arity = self.module.immediates.items[immediate_offset]; - const return_arity = self.module.immediates.items[immediate_offset + 1]; + const param_arity = self.module.instructions.items[pushed_instruction.offset + 1]; + const return_arity = self.module.instructions.items[pushed_instruction.offset + 2]; // We have an if with no else, check that this works arity-wise and replace with fast if if (param_arity -% return_arity != 0) return error.ValidatorElseBranchExpected; - self.module.immediates.items[immediate_offset + 2] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; }, else => return error.UnexpectedInstruction, } @@ -365,14 +363,14 @@ pub const Parser = struct { const label = try self.readULEB128Mem(u32); try self.validator.validateBr(label); - try self.module.immediates.append(label); + try self.module.instructions.append(label); // rr = Rr{ .br = label }; }, .br_if => { const label = try self.readULEB128Mem(u32); try self.validator.validateBrIf(label); - try self.module.immediates.append(label); + try self.module.instructions.append(label); // rr = Rr{ .br_if = label }; }, .br_table => { @@ -389,9 +387,9 @@ pub const Parser = struct { try self.validator.validateBrTable(l_star, ln); - try self.module.immediates.append(label_start); - try self.module.immediates.append(label_count); - try self.module.immediates.append(ln); + try self.module.instructions.append(label_start); + try self.module.instructions.append(label_count); + try self.module.instructions.append(ln); // rr = Rr{ // .br_table = .{ @@ -408,13 +406,12 @@ pub const Parser = struct { try self.validator.validateCall(functype); - try self.module.immediates.append(funcidx); + try self.module.instructions.append(funcidx); // To allow swapping out a .call with a .fast_call we need enough space for all .fast_call immediates: - try self.module.immediates.append(0); - try self.module.immediates.append(0); - try self.module.immediates.append(0); - try self.module.immediates.append(0); - try self.module.immediates.append(0); + try self.module.instructions.append(0); + try self.module.instructions.append(0); + try self.module.instructions.append(0); + try self.module.instructions.append(0); // rr = Rr{ .call = funcidx }; // TODO: do the replacement at instantiate-time for a fastcall if in same module? @@ -429,8 +426,8 @@ pub const Parser = struct { try self.validator.validateCallIndirect(functype); - try self.module.immediates.append(typeidx); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(typeidx); + try self.module.instructions.append(tableidx); // rr = Rr{ // .call_indirect = .{ @@ -455,7 +452,7 @@ pub const Parser = struct { try self.validator.validateGlobalGet(global); - try self.module.immediates.append(globalidx); + try self.module.instructions.append(globalidx); // rr = Rr{ .@"global.get" = globalidx }; }, @@ -465,7 +462,7 @@ pub const Parser = struct { try self.validator.validateGlobalSet(global); - try self.module.immediates.append(globalidx); + try self.module.instructions.append(globalidx); // rr = Rr{ .@"global.set" = globalidx }; }, .@"table.get" => { @@ -480,7 +477,7 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); _ = try self.validator.pushOperand(Type{ .Known = reftype }); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .@"table.get" = tableidx }; }, .@"table.set" => { @@ -495,7 +492,7 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .@"table.set" = tableidx }; }, .@"local.get" => { @@ -524,7 +521,7 @@ pub const Parser = struct { } } - try self.module.immediates.append(localidx); + try self.module.instructions.append(localidx); // rr = Rr{ .@"local.get" = localidx }; }, .@"local.set" => { @@ -554,7 +551,7 @@ pub const Parser = struct { } } - try self.module.immediates.append(localidx); + try self.module.instructions.append(localidx); // rr = Rr{ .@"local.set" = localidx }; }, @@ -585,7 +582,7 @@ pub const Parser = struct { } } - try self.module.immediates.append(localidx); + try self.module.instructions.append(localidx); // rr = Rr{ .@"local.tee" = localidx }; }, .@"memory.size" => { @@ -593,7 +590,7 @@ pub const Parser = struct { const memidx = try self.readByte(); if (memidx != 0) return error.MalformedMemoryReserved; - try self.module.immediates.append(memidx); + try self.module.instructions.append(memidx); // rr = Rr{ .@"memory.size" = memidx }; }, .@"memory.grow" => { @@ -601,35 +598,33 @@ pub const Parser = struct { const memidx = try self.readByte(); if (memidx != 0) return error.MalformedMemoryReserved; - try self.module.immediates.append(memidx); + try self.module.instructions.append(memidx); // rr = Rr{ .@"memory.grow" = memidx }; }, .@"i32.const" => { const i32_const = try self.readILEB128Mem(i32); - try self.module.immediates.append(@as(u32, @bitCast(i32_const))); + try self.module.instructions.append(@as(u32, @bitCast(i32_const))); // rr = Rr{ .@"i32.const" = i32_const }; }, .@"i64.const" => { const i64_const = try self.readILEB128Mem(i64); const u64_const = @as(u64, @bitCast(i64_const)); - try self.module.immediates.append(@as(u32, @truncate(u64_const & 0xFFFFFFFF))); - try self.module.immediates.append(@as(u32, @truncate(u64_const >> 32))); + try self.module.instructions.append(u64_const); // rr = Rr{ .@"i64.const" = i64_const }; }, .@"f32.const" => { const float_const: f32 = @bitCast(try self.readU32()); - try self.module.immediates.append(@as(u32, @bitCast(float_const))); + try self.module.instructions.append(@as(u32, @bitCast(float_const))); // rr = Rr{ .@"f32.const" = float_const }; }, .@"f64.const" => { const float_const: f64 = @bitCast(try self.readU64()); const u64_float = @as(u64, @bitCast(float_const)); - try self.module.immediates.append(@as(u32, @truncate(u64_float & 0xFFFF))); - try self.module.immediates.append(@as(u32, @truncate(u64_float >> 32))); + try self.module.instructions.append(u64_float); // rr = Rr{ .@"f64.const" = float_const }; }, @@ -641,8 +636,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.load" = .{ // .alignment = alignment, @@ -657,8 +652,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load" = .{ // .alignment = alignment, @@ -673,8 +668,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"f32.load" = .{ // .alignment = alignment, @@ -689,8 +684,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"f64.load" = .{ // .alignment = alignment, @@ -705,8 +700,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.load8_s" = .{ // .alignment = alignment, @@ -721,8 +716,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.load8_u" = .{ // .alignment = alignment, @@ -737,8 +732,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.load16_s" = .{ // .alignment = alignment, @@ -753,8 +748,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.load16_u" = .{ // .alignment = alignment, @@ -769,8 +764,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load8_s" = .{ // .alignment = alignment, @@ -785,8 +780,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load8_u" = .{ // .alignment = alignment, @@ -801,8 +796,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load16_s" = .{ // .alignment = alignment, @@ -817,8 +812,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load16_u" = .{ // .alignment = alignment, @@ -833,8 +828,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load32_s" = .{ // .alignment = alignment, @@ -849,8 +844,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.load32_u" = .{ // .alignment = alignment, @@ -865,8 +860,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.store" = .{ // .alignment = alignment, @@ -881,8 +876,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.store" = .{ // .alignment = alignment, @@ -897,8 +892,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"f32.store" = .{ // .alignment = alignment, @@ -913,8 +908,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 64) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"f64.store" = .{ // .alignment = alignment, @@ -929,8 +924,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.store8" = .{ // .alignment = alignment, @@ -945,8 +940,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i32.store16" = .{ // .alignment = alignment, @@ -961,8 +956,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 8) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.store8" = .{ // .alignment = alignment, @@ -977,8 +972,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 16) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.store16" = .{ // .alignment = alignment, @@ -992,8 +987,8 @@ pub const Parser = struct { if (try math.mul(u32, 8, try math.powi(u32, 2, alignment)) > 32) return error.InvalidAlignment; - try self.module.immediates.append(alignment); - try self.module.immediates.append(offset); + try self.module.instructions.append(alignment); + try self.module.instructions.append(offset); // rr = Rr{ // .@"i64.store32" = .{ // .alignment = alignment, @@ -1135,7 +1130,7 @@ pub const Parser = struct { try self.validator.validateRefNull(reftype); - try self.module.immediates.append(@as(u32, @intFromEnum(reftype))); + try self.module.instructions.append(@as(u32, @intFromEnum(reftype))); // rr = Rr{ .@"ref.null" = reftype }; }, .@"ref.is_null" => {}, @@ -1158,7 +1153,7 @@ pub const Parser = struct { if (!in_references) return error.ValidatorUnreferencedFunction; } - try self.module.immediates.append(funcidx); + try self.module.instructions.append(funcidx); // rr = Rr{ .@"ref.func" = funcidx }; }, .misc => { @@ -1185,8 +1180,8 @@ pub const Parser = struct { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - try self.module.immediates.append(dataidx); - try self.module.immediates.append(memidx); + try self.module.instructions.append(dataidx); + try self.module.instructions.append(memidx); // rr = Rr{ // .misc = MiscRr{ // .@"memory.init" = .{ @@ -1202,7 +1197,7 @@ pub const Parser = struct { const data_count = self.module.data_count orelse return error.InstructionRequiresDataCountSection; if (!(dataidx < data_count)) return error.InvalidDataIndex; - try self.module.immediates.append(dataidx); + try self.module.instructions.append(dataidx); // rr = Rr{ .misc = MiscRr{ .@"data.drop" = dataidx } }; }, .@"memory.copy" => { @@ -1211,8 +1206,8 @@ pub const Parser = struct { const dst_memidx = try self.readByte(); if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - try self.module.immediates.append(src_memidx); - try self.module.immediates.append(dst_memidx); + try self.module.instructions.append(src_memidx); + try self.module.instructions.append(dst_memidx); // rr = Rr{ .misc = MiscRr{ .@"memory.copy" = .{ // .src_memidx = src_memidx, // .dest_memidx = dest_memidx, @@ -1222,7 +1217,7 @@ pub const Parser = struct { const memidx = try self.readByte(); if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; - try self.module.immediates.append(memidx); + try self.module.instructions.append(memidx); // rr = Rr{ .misc = MiscRr{ .@"memory.fill" = memidx } }; }, .@"table.init" => { @@ -1234,8 +1229,8 @@ pub const Parser = struct { if (elemtype.reftype != tabletype.reftype) return error.MismatchedTypes; - try self.module.immediates.append(elemidx); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(elemidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .misc = MiscRr{ .@"table.init" = .{ // .elemidx = elemidx, // .tableidx = tableidx, @@ -1246,7 +1241,7 @@ pub const Parser = struct { if (elemidx >= self.module.elements.list.items.len) return error.ValidatorInvalidElementIndex; - try self.module.immediates.append(elemidx); + try self.module.instructions.append(elemidx); // rr = Rr{ .misc = MiscRr{ .@"elem.drop" = .{ .elemidx = elemidx } } }; }, .@"table.copy" => { @@ -1258,8 +1253,8 @@ pub const Parser = struct { if (dst_tabletype.reftype != src_tabletype.reftype) return error.MismatchedTypes; - try self.module.immediates.append(dst_tableidx); - try self.module.immediates.append(src_tableidx); + try self.module.instructions.append(dst_tableidx); + try self.module.instructions.append(src_tableidx); // rr = Rr{ .misc = MiscRr{ .@"table.copy" = .{ // .dest_tableidx = dest_tableidx, // .src_tableidx = src_tableidx, @@ -1278,7 +1273,7 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); try self.validator.pushOperand(Type{ .Known = .I32 }); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .misc = MiscRr{ .@"table.grow" = .{ // .tableidx = tableidx, // } } }; @@ -1287,7 +1282,7 @@ pub const Parser = struct { const tableidx = try self.readULEB128Mem(u32); if (tableidx >= self.module.tables.list.items.len) return error.ValidatorInvalidTableIndex; - try self.module.immediates.append(tableidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .misc = MiscRr{ .@"table.size" = .{ // .tableidx = tableidx, // } } }; @@ -1305,7 +1300,7 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = reftype }); _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); - try self.module.immediates.append(tableidx); + try self.module.instructions.append(tableidx); // rr = Rr{ .misc = MiscRr{ .@"table.fill" = .{ // .tableidx = tableidx, // } } }; @@ -1317,8 +1312,6 @@ pub const Parser = struct { // std.debug.print("immediates = {any}\nimmeoffset = {any}\n\n", .{ self.module.immediates.items, self.module.immediates_offset.items }); try self.validator.validate(instr); - try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); - return instr; } From f39a9451795195a28bd9d55d6e9cbc4663ff7265 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Mon, 31 Jul 2023 18:27:42 +0100 Subject: [PATCH 13/16] Fix br --- src/instance/vm.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index e043ed8b..d11ff5b7 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -219,7 +219,7 @@ pub const VirtualMachine = struct { } pub fn br(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - const next_ip = self.branch(instructions[ip]); + const next_ip = self.branch(instructions[ip + 1]); return dispatch(self, next_ip, instructions); } @@ -227,7 +227,7 @@ pub const VirtualMachine = struct { pub fn br_if(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const condition = self.popOperand(u32); - const next_ip = if (condition == 0) ip + 1 else self.branch(instructions[ip]); + const next_ip = if (condition == 0) ip + 1 else self.branch(instructions[ip + 1]); return dispatch(self, next_ip, instructions); } From 00e9c32a660310f537ca1f7bbca24465bd4d0c3b Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Tue, 1 Aug 2023 00:50:14 +0100 Subject: [PATCH 14/16] WIP --- src/instance/vm.zig | 27 +++++++-------------------- src/module/parser.zig | 17 +++++++---------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index d11ff5b7..6bb44f42 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -840,7 +840,7 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(u32, @as(u32, @intCast(memory.size()))); - return dispatch(self, ip + 1, instructions); + return dispatch(self, ip + 2, instructions); } pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { @@ -853,39 +853,26 @@ pub const VirtualMachine = struct { self.pushOperandNoCheck(i32, @as(i32, -1)); } - return dispatch(self, ip + 1, instructions); + return dispatch(self, ip + 2, instructions); } pub fn @"i32.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - const literal = @as(i32, @intCast(instructions[ip + 1])); - // std.debug.print("{}: i32.const[{}]\n", .{ ip, literal }); - - self.pushOperandNoCheck(i32, literal); - + self.pushOperandNoCheck(u64, instructions[ip + 1]); return dispatch(self, ip + 2, instructions); } pub fn @"i64.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - const literal = @as(i64, @intCast(instructions[ip + 1])); - - self.pushOperandNoCheck(i64, literal); - + self.pushOperandNoCheck(u64, instructions[ip + 1]); return dispatch(self, ip + 2, instructions); } pub fn @"f32.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - const literal = @as(f32, @floatFromInt(instructions[ip + 1])); - - self.pushOperandNoCheck(f32, literal); - + self.pushOperandNoCheck(u64, instructions[ip + 1]); return dispatch(self, ip + 2, instructions); } pub fn @"f64.const"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - const literal = @as(f64, @floatFromInt(instructions[ip + 1])); - - self.pushOperandNoCheck(f64, literal); - + self.pushOperandNoCheck(u64, instructions[ip + 1]); return dispatch(self, ip + 2, instructions); } @@ -2153,7 +2140,7 @@ pub const VirtualMachine = struct { pub fn @"ref.null"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { self.pushOperandNoCheck(u64, REF_NULL); - return dispatch(self, ip + 1, instructions); + return dispatch(self, ip + 2, instructions); } pub fn @"ref.is_null"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { diff --git a/src/module/parser.zig b/src/module/parser.zig index 837308f1..db85141a 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -323,10 +323,7 @@ pub const Parser = struct { const pushed_instruction = try self.peekContinuationStack(); switch (pushed_instruction.opcode) { - .@"if" => { - // std.debug.print("pushed_instruction.offset = {}\n", .{pushed_instruction.offset}); - self.module.instructions.items[pushed_instruction.offset] = @as(u64, @intFromPtr(&VirtualMachine.if_with_else)); - }, + .@"if" => self.module.instructions.items[pushed_instruction.offset] = @as(u64, @intFromPtr(&VirtualMachine.if_with_else)), else => return error.UnexpectedInstruction, } @@ -337,21 +334,21 @@ pub const Parser = struct { // If we're not looking at the `end` of a function if (self.scope != 0) { const pushed_instruction = try self.popContinuationStack(); - // std.debug.print("instr[{}]: end immediate_offset = {}\n", .{ pushed_instruction.offset, immediate_offset }); + // Instruction after `end`: + const next_instr = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; switch (pushed_instruction.opcode) { - .block => self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast, + .block => self.module.instructions.items[pushed_instruction.offset + 3] = next_instr, .loop => {}, - .if_with_else => { - self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; - }, + .if_with_else => self.module.instructions.items[pushed_instruction.offset + 3] = next_instr, .@"if" => { const param_arity = self.module.instructions.items[pushed_instruction.offset + 1]; const return_arity = self.module.instructions.items[pushed_instruction.offset + 2]; + // We have an if with no else, check that this works arity-wise and replace with fast if if (param_arity -% return_arity != 0) return error.ValidatorElseBranchExpected; - self.module.instructions.items[pushed_instruction.offset + 3] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + self.module.instructions.items[pushed_instruction.offset + 3] = next_instr; }, else => return error.UnexpectedInstruction, } From 39c16f4c326d39405e6b283dd505c7ab17726f69 Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Tue, 1 Aug 2023 01:49:18 +0100 Subject: [PATCH 15/16] Working --- src/instance/vm.zig | 29 +++++++++++------------------ src/module.zig | 4 ++++ src/module/parser.zig | 21 +++++++++++++-------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 6bb44f42..233586b8 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -109,7 +109,7 @@ pub const VirtualMachine = struct { @"i32.extend8_s", @"i32.extend16_s", @"i64.extend8_s", @"i64.extend16_s", @"i64.extend32_s", impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, @"ref.null", @"ref.is_null", @"ref.func", impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, - impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, misc, impl_ni, impl_ni, impl_ni, + impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, impl_ni, }; inline fn dispatch(self: *VirtualMachine, next_ip: usize, instructions: []u64) WasmError!void { @@ -227,7 +227,7 @@ pub const VirtualMachine = struct { pub fn br_if(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const condition = self.popOperand(u32); - const next_ip = if (condition == 0) ip + 1 else self.branch(instructions[ip + 1]); + const next_ip = if (condition == 0) ip + 2 else self.branch(instructions[ip + 1]); return dispatch(self, next_ip, instructions); } @@ -291,7 +291,7 @@ pub const VirtualMachine = struct { if (self.inst == f.instance) { // Switch call with fast_call - self.inst.module.instructions.items[ip] = @as(u64, @intFromPtr(&VirtualMachine.fast_call)); + instructions[ip] = @as(u64, @intFromPtr(&VirtualMachine.fast_call)); instructions[ip + 1] = f.start; instructions[ip + 2] = f.locals_count; instructions[ip + 3] = function.params.len; @@ -836,6 +836,7 @@ pub const VirtualMachine = struct { } pub fn @"memory.size"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + _ = instructions[ip + 1]; const memory = try self.inst.getMemory(0); self.pushOperandNoCheck(u32, @as(u32, @intCast(memory.size()))); @@ -844,6 +845,7 @@ pub const VirtualMachine = struct { } pub fn @"memory.grow"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + _ = instructions[ip + 1]; const memory = try self.inst.getMemory(0); const num_pages = self.popOperand(u32); @@ -2138,6 +2140,7 @@ pub const VirtualMachine = struct { } pub fn @"ref.null"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { + _ = instructions[ip + 1]; self.pushOperandNoCheck(u64, REF_NULL); return dispatch(self, ip + 2, instructions); @@ -2165,21 +2168,11 @@ pub const VirtualMachine = struct { return dispatch(self, ip + 2, instructions); } - pub fn misc(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - return miscDispatch(self, ip, instructions); - } - - const misc_lookup = [18]InstructionFunction{ + pub const misc_lookup = [18]InstructionFunction{ @"i32.trunc_sat_f32_s", @"i32.trunc_sat_f32_u", @"i32.trunc_sat_f64_s", @"i32.trunc_sat_f64_u", @"i64.trunc_sat_f32_s", @"i64.trunc_sat_f32_u", @"i64.trunc_sat_f64_s", @"i64.trunc_sat_f64_u", @"memory.init", @"data.drop", @"memory.copy", @"memory.fill", @"table.init", @"elem.drop", @"table.copy", @"table.grow", @"table.size", @"table.fill", }; - inline fn miscDispatch(self: *VirtualMachine, next_ip: usize, instructions: []u64) WasmError!void { - const next_instr = instructions[next_ip + 1]; - - return try @call(.always_tail, misc_lookup[next_instr], .{ self, next_ip, instructions }); - } - pub fn @"i32.trunc_sat_f32_s"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const c1 = self.popOperand(f32); const trunc = @trunc(c1); @@ -2358,8 +2351,8 @@ pub const VirtualMachine = struct { pub fn @"memory.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"memory.init"; - const memidx = instructions[ip + 1]; - const dataidx = instructions[ip + 2]; + const dataidx = instructions[ip + 1]; + const memidx = instructions[ip + 2]; const n = self.popOperand(u32); const src = self.popOperand(u32); @@ -2448,8 +2441,8 @@ pub const VirtualMachine = struct { pub fn @"table.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { // const meta = code[ip].misc.@"table.init"; - const tableidx = instructions[ip + 1]; - const elemidx = instructions[ip + 2]; + const elemidx = instructions[ip + 1]; + const tableidx = instructions[ip + 2]; const table = try self.inst.getTable(tableidx); const elem = try self.inst.getElem(elemidx); diff --git a/src/module.zig b/src/module.zig index ec5bf8ea..a93f5ad0 100644 --- a/src/module.zig +++ b/src/module.zig @@ -481,6 +481,7 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); + try self.instructions.append(funcidx); // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); @@ -514,6 +515,7 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); + try self.instructions.append(funcidx); // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); @@ -549,6 +551,7 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); + try self.instructions.append(funcidx); // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); @@ -581,6 +584,7 @@ pub const Module = struct { const init_offset = self.instructions.items.len; // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); + try self.instructions.append(funcidx); // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); try self.element_init_offsets.append(init_offset); diff --git a/src/module/parser.zig b/src/module/parser.zig index db85141a..ef8ef9d8 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -62,7 +62,6 @@ pub const Parser = struct { while (try self.next()) |instr| { _ = instr; - // try self.module.instructions.append(VirtualMachine.lookup[@intFromEnum(instr)]); } const bytes_read = self.bytesRead(); @@ -168,10 +167,6 @@ pub const Parser = struct { const instr = std.meta.intToEnum(Opcode, self.code[0]) catch return error.IllegalOpcode; self.code = self.code[1..]; - // std.debug.print("instr[{}] = {}, immediate offset = {}\n", .{ self.code_ptr, instr, immediates_count }); - - // std.debug.print("instr = {}\n", .{instr}); - // defer std.debug.print("{any}\n\n", .{self.module.instructions.items}); try self.module.instructions.append(@as(u64, @intFromPtr(VirtualMachine.lookup[@intFromEnum(instr)]))); // 2. Find the start of the next instruction @@ -300,10 +295,10 @@ pub const Parser = struct { try self.module.instructions.append(block_params); try self.module.instructions.append(block_returns); - try self.module.instructions.append(0); + try self.module.instructions.append(0); // branch_target // an if with no else only has 3 immediates, but we push a fourth here // so we can exchange the if with an if_with_else - try self.module.instructions.append(0); + try self.module.instructions.append(0); // else_ip // FIXME: we have found an if, but we were actually pushing an if_no_else // i.e. we assume we don't have an else until we find one (and if we @@ -323,7 +318,14 @@ pub const Parser = struct { const pushed_instruction = try self.peekContinuationStack(); switch (pushed_instruction.opcode) { - .@"if" => self.module.instructions.items[pushed_instruction.offset] = @as(u64, @intFromPtr(&VirtualMachine.if_with_else)), + .@"if" => { + self.module.instructions.items[pushed_instruction.offset] = @as(u64, @intFromPtr(&VirtualMachine.if_with_else)); + self.module.instructions.items[pushed_instruction.offset + 4] = math.cast(u32, self.code_ptr + 1) orelse return error.FailedCast; + // Replace top of continuation stack with .if_with_else + _ = try self.popContinuationStack(); + try self.pushContinuationStack(pushed_instruction.offset, .if_with_else); + }, + else => return error.UnexpectedInstruction, } @@ -1158,6 +1160,9 @@ pub const Parser = struct { const misc_opcode = try std.meta.intToEnum(MiscOpcode, version); try self.validator.validateMisc(misc_opcode); + // Replace misc with particular function + self.module.instructions.items[self.module.instructions.items.len - 1] = @as(u64, @intFromPtr(VirtualMachine.misc_lookup[@intFromEnum(misc_opcode)])); + switch (misc_opcode) { // FIXME: do I need to handle misc separately .@"i32.trunc_sat_f32_s" => {}, From 04aee43e6b43c37dc776129fdfc22426c072bd1e Mon Sep 17 00:00:00 2001 From: Malcolm Still Date: Tue, 1 Aug 2023 02:00:23 +0100 Subject: [PATCH 16/16] Clean up --- src/instance/vm.zig | 19 +--- src/module.zig | 16 ++-- src/module/parser.zig | 210 ------------------------------------------ 3 files changed, 9 insertions(+), 236 deletions(-) diff --git a/src/instance/vm.zig b/src/instance/vm.zig index 233586b8..2475d6c5 100644 --- a/src/instance/vm.zig +++ b/src/instance/vm.zig @@ -89,8 +89,6 @@ pub const VirtualMachine = struct { try @call(.auto, @as(InstructionFunction, @ptrFromInt(instr)), .{ self, ip, self.inst.module.instructions.items }); } - // To avoid a recursive definition, define similar function pointer type we will cast to / from - // pub const Instruction = *const fn (*VirtualMachine, usize, []u64) WasmError!void; pub const InstructionFunction = *const fn (*VirtualMachine, usize, []u64) WasmError!void; pub const lookup = [256]InstructionFunction{ @@ -133,7 +131,6 @@ pub const VirtualMachine = struct { } pub fn block(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].block; const param_arity = instructions[ip + 1]; const return_arity = instructions[ip + 2]; const branch_target = instructions[ip + 3]; @@ -186,15 +183,12 @@ pub const VirtualMachine = struct { return dispatch(self, label.branch_target, instructions); } - // if_no_else pub fn @"if"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].if_no_else; const param_arity = instructions[ip + 1]; const return_arity = instructions[ip + 2]; const branch_target = instructions[ip + 3]; const else_ip = instructions[ip + 4]; _ = else_ip; - // std.debug.print("{}: if[{}, {}, {}, {}]\n", .{ ip, param_arity, return_arity, branch_target, else_ip }); const condition = self.popOperand(u32); @@ -247,7 +241,7 @@ pub const VirtualMachine = struct { pub fn @"return"(self: *VirtualMachine, ip: usize, _: []u64) WasmError!void { _ = ip; - // std.debug.print("{}: return[]\n", .{ip}); + const frame = self.peekFrame(); const n = frame.return_arity; @@ -275,7 +269,6 @@ pub const VirtualMachine = struct { } pub fn call(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const funcidx = code[ip].call; const funcidx = instructions[ip + 1]; const function = try self.inst.getFunc(funcidx); @@ -329,7 +322,6 @@ pub const VirtualMachine = struct { } pub fn call_indirect(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const call_indirect_instruction = code[ip].call_indirect; var module = self.inst.module; const typeidx = instructions[ip + 1]; @@ -385,7 +377,6 @@ pub const VirtualMachine = struct { } pub fn fast_call(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const f = code[ip].fast_call; const start = instructions[ip + 1]; const locals = instructions[ip + 2]; const params = instructions[ip + 3]; @@ -437,7 +428,6 @@ pub const VirtualMachine = struct { pub fn @"local.get"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { const localidx = instructions[ip + 1]; - // std.debug.print("{}: local.get[{}]\n", .{ ip, localidx }); const frame = self.peekFrame(); @@ -2350,7 +2340,6 @@ pub const VirtualMachine = struct { } pub fn @"memory.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].misc.@"memory.init"; const dataidx = instructions[ip + 1]; const memidx = instructions[ip + 2]; @@ -2379,7 +2368,6 @@ pub const VirtualMachine = struct { } pub fn @"data.drop"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const dataidx = code[ip].misc.@"data.drop"; const dataidx = instructions[ip + 1]; const data = try self.inst.getData(dataidx); data.dropped = true; @@ -2440,7 +2428,6 @@ pub const VirtualMachine = struct { } pub fn @"table.init"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].misc.@"table.init"; const elemidx = instructions[ip + 1]; const tableidx = instructions[ip + 2]; @@ -2469,7 +2456,6 @@ pub const VirtualMachine = struct { } pub fn @"elem.drop"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].misc.@"elem.drop"; const elemidx = instructions[ip + 1]; const elem = try self.inst.getElem(elemidx); elem.dropped = true; @@ -2478,9 +2464,6 @@ pub const VirtualMachine = struct { } pub fn @"table.copy"(self: *VirtualMachine, ip: usize, instructions: []u64) WasmError!void { - // const meta = code[ip].misc.@"table.copy"; - // const dest_tableidx = meta.dest_tableidx; - // const src_tableidx = meta.src_tableidx; const dst_tableidx = instructions[ip + 1]; const src_tableidx = instructions[ip + 2]; diff --git a/src/module.zig b/src/module.zig index a93f5ad0..9dd8b290 100644 --- a/src/module.zig +++ b/src/module.zig @@ -479,11 +479,11 @@ pub const Module = struct { try self.references.append(funcidx); const init_offset = self.instructions.items.len; - // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); try self.instructions.append(funcidx); - // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); + try self.element_init_offsets.append(init_offset); } @@ -513,11 +513,11 @@ pub const Module = struct { try self.references.append(funcidx); const init_offset = self.instructions.items.len; - // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); try self.instructions.append(funcidx); - // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); + try self.element_init_offsets.append(init_offset); } @@ -549,11 +549,11 @@ pub const Module = struct { try self.references.append(funcidx); const init_offset = self.instructions.items.len; - // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); try self.instructions.append(funcidx); - // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); + try self.element_init_offsets.append(init_offset); } @@ -582,11 +582,11 @@ pub const Module = struct { try self.references.append(funcidx); const init_offset = self.instructions.items.len; - // try self.parsed_code.append(Rr{ .@"ref.func" = funcidx }); + try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"ref.func"))); try self.instructions.append(funcidx); - // try self.parsed_code.append(Rr.@"return"); try self.instructions.append(@as(u64, @intFromPtr(&VirtualMachine.@"return"))); + try self.element_init_offsets.append(init_offset); } diff --git a/src/module/parser.zig b/src/module/parser.zig index ef8ef9d8..2aa34a65 100644 --- a/src/module/parser.zig +++ b/src/module/parser.zig @@ -207,14 +207,6 @@ pub const Parser = struct { try self.module.instructions.append(block_params); try self.module.instructions.append(block_returns); try self.module.instructions.append(0); - - // Rr{ - // .block = .{ - // .param_arity = block_params, - // .return_arity = block_returns, - // .branch_target = 0, - // }, - // }; }, .loop => { const block_type = try self.readILEB128Mem(i32); @@ -249,14 +241,6 @@ pub const Parser = struct { try self.module.instructions.append(block_params); try self.module.instructions.append(block_params); try self.module.instructions.append(math.cast(u32, self.code_ptr) orelse return error.FailedCast); - - // rr = Rr{ - // .loop = .{ - // .param_arity = block_params, - // .return_arity = block_params, - // .branch_target = math.cast(u32, self.code_ptr) orelse return error.FailedCast, - // }, - // }; }, .@"if" => { const block_type = try self.readILEB128Mem(i32); @@ -299,20 +283,6 @@ pub const Parser = struct { // an if with no else only has 3 immediates, but we push a fourth here // so we can exchange the if with an if_with_else try self.module.instructions.append(0); // else_ip - - // FIXME: we have found an if, but we were actually pushing an if_no_else - // i.e. we assume we don't have an else until we find one (and if we - // do we replace the if_no_else with a plain if). We could turn this - // around, so that e.g. if means if-no-else and then have a if-with-else - // instruction - // - // rr = Rr{ - // .if_no_else = .{ - // .param_arity = block_params, - // .return_arity = block_returns, - // .branch_target = 0, - // }, - // }; }, .@"else" => { const pushed_instruction = try self.peekContinuationStack(); @@ -328,8 +298,6 @@ pub const Parser = struct { else => return error.UnexpectedInstruction, } - - // rr = Rr.@"else"; }, .end => { self.scope -= 1; @@ -355,22 +323,18 @@ pub const Parser = struct { else => return error.UnexpectedInstruction, } } - - // rr = Rr.end; }, .br => { const label = try self.readULEB128Mem(u32); try self.validator.validateBr(label); try self.module.instructions.append(label); - // rr = Rr{ .br = label }; }, .br_if => { const label = try self.readULEB128Mem(u32); try self.validator.validateBrIf(label); try self.module.instructions.append(label); - // rr = Rr{ .br_if = label }; }, .br_table => { const label_start = math.cast(u32, self.module.br_table_indices.items.len) orelse return error.TooManyBrTableIndices; @@ -389,13 +353,6 @@ pub const Parser = struct { try self.module.instructions.append(label_start); try self.module.instructions.append(label_count); try self.module.instructions.append(ln); - - // rr = Rr{ - // .br_table = .{ - // .ls = Range{ .offset = label_start, .count = label_count }, - // .ln = ln, - // }, - // }; }, .@"return" => {}, .call => { @@ -411,10 +368,6 @@ pub const Parser = struct { try self.module.instructions.append(0); try self.module.instructions.append(0); try self.module.instructions.append(0); - - // rr = Rr{ .call = funcidx }; - // TODO: do the replacement at instantiate-time for a fastcall if in same module? - // rr = Rr{ .fast_call = .{ .ip_start = 0, .params = 1, .locals = 0, .results = 1 } }; }, .call_indirect => { const typeidx = try self.readULEB128Mem(u32); @@ -427,13 +380,6 @@ pub const Parser = struct { try self.module.instructions.append(typeidx); try self.module.instructions.append(tableidx); - - // rr = Rr{ - // .call_indirect = .{ - // .typeidx = typeidx, - // .tableidx = tableidx, - // }, - // }; }, .drop => {}, .select => {}, @@ -452,8 +398,6 @@ pub const Parser = struct { try self.validator.validateGlobalGet(global); try self.module.instructions.append(globalidx); - - // rr = Rr{ .@"global.get" = globalidx }; }, .@"global.set" => { const globalidx = try self.readULEB128Mem(u32); @@ -462,7 +406,6 @@ pub const Parser = struct { try self.validator.validateGlobalSet(global); try self.module.instructions.append(globalidx); - // rr = Rr{ .@"global.set" = globalidx }; }, .@"table.get" => { const tableidx = try self.readULEB128Mem(u32); @@ -477,7 +420,6 @@ pub const Parser = struct { _ = try self.validator.pushOperand(Type{ .Known = reftype }); try self.module.instructions.append(tableidx); - // rr = Rr{ .@"table.get" = tableidx }; }, .@"table.set" => { const tableidx = try self.readULEB128Mem(u32); @@ -492,7 +434,6 @@ pub const Parser = struct { _ = try self.validator.popOperandExpecting(Type{ .Known = .I32 }); try self.module.instructions.append(tableidx); - // rr = Rr{ .@"table.set" = tableidx }; }, .@"local.get" => { const localidx = try self.readULEB128Mem(u32); @@ -521,7 +462,6 @@ pub const Parser = struct { } try self.module.instructions.append(localidx); - // rr = Rr{ .@"local.get" = localidx }; }, .@"local.set" => { const localidx = try self.readULEB128Mem(u32); @@ -551,8 +491,6 @@ pub const Parser = struct { } try self.module.instructions.append(localidx); - - // rr = Rr{ .@"local.set" = localidx }; }, .@"local.tee" => { const localidx = try self.readULEB128Mem(u32); @@ -582,7 +520,6 @@ pub const Parser = struct { } try self.module.instructions.append(localidx); - // rr = Rr{ .@"local.tee" = localidx }; }, .@"memory.size" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -590,7 +527,6 @@ pub const Parser = struct { if (memidx != 0) return error.MalformedMemoryReserved; try self.module.instructions.append(memidx); - // rr = Rr{ .@"memory.size" = memidx }; }, .@"memory.grow" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -598,34 +534,28 @@ pub const Parser = struct { if (memidx != 0) return error.MalformedMemoryReserved; try self.module.instructions.append(memidx); - // rr = Rr{ .@"memory.grow" = memidx }; }, .@"i32.const" => { const i32_const = try self.readILEB128Mem(i32); try self.module.instructions.append(@as(u32, @bitCast(i32_const))); - // rr = Rr{ .@"i32.const" = i32_const }; }, .@"i64.const" => { const i64_const = try self.readILEB128Mem(i64); const u64_const = @as(u64, @bitCast(i64_const)); try self.module.instructions.append(u64_const); - // rr = Rr{ .@"i64.const" = i64_const }; }, .@"f32.const" => { const float_const: f32 = @bitCast(try self.readU32()); try self.module.instructions.append(@as(u32, @bitCast(float_const))); - // rr = Rr{ .@"f32.const" = float_const }; }, .@"f64.const" => { const float_const: f64 = @bitCast(try self.readU64()); const u64_float = @as(u64, @bitCast(float_const)); try self.module.instructions.append(u64_float); - - // rr = Rr{ .@"f64.const" = float_const }; }, .@"i32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -637,12 +567,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.load" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -653,12 +577,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"f32.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -669,12 +587,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"f32.load" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"f64.load" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -685,12 +597,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"f64.load" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -701,12 +607,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.load8_s" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -717,12 +617,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.load8_u" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -733,12 +627,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.load16_s" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -749,12 +637,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.load16_u" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load8_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -765,12 +647,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load8_s" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load8_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -781,12 +657,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load8_u" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load16_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -797,12 +667,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load16_s" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load16_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -813,12 +677,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load16_u" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load32_s" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -829,12 +687,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load32_s" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.load32_u" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -845,12 +697,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.load32_u" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -861,12 +707,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.store" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -877,12 +717,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.store" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"f32.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -893,12 +727,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"f32.store" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"f64.store" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -909,12 +737,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"f64.store" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -925,12 +747,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.store8" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -941,12 +757,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i32.store16" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.store8" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -957,12 +767,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.store8" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.store16" => { if (self.module.memories.list.items.len != 1) return error.ValidatorUnknownMemory; @@ -973,12 +777,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.store16" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i64.store32" => { const alignment = try self.readULEB128Mem(u32); @@ -988,12 +786,6 @@ pub const Parser = struct { try self.module.instructions.append(alignment); try self.module.instructions.append(offset); - // rr = Rr{ - // .@"i64.store32" = .{ - // .alignment = alignment, - // .offset = offset, - // }, - // }; }, .@"i32.eqz" => {}, .@"i32.eq" => {}, @@ -1130,7 +922,6 @@ pub const Parser = struct { try self.validator.validateRefNull(reftype); try self.module.instructions.append(@as(u32, @intFromEnum(reftype))); - // rr = Rr{ .@"ref.null" = reftype }; }, .@"ref.is_null" => {}, .@"ref.func" => { @@ -1153,7 +944,6 @@ pub const Parser = struct { } try self.module.instructions.append(funcidx); - // rr = Rr{ .@"ref.func" = funcidx }; }, .misc => { const version = try self.readULEB128Mem(u32);