diff --git a/src/engine/v3/V3Interpreter.v3 b/src/engine/v3/V3Interpreter.v3 index 09abc5e90..75da127ec 100644 --- a/src/engine/v3/V3Interpreter.v3 +++ b/src/engine/v3/V3Interpreter.v3 @@ -468,29 +468,29 @@ class V3Interpreter extends WasmStack { Runtime.TABLE_SET(this, frame.func.instance, table_index); } - I32_LOAD => doLoad(ACCESS_U32, pushu); - I64_LOAD => doLoad(ACCESS_U64, pushw); - F32_LOAD => doLoad(ACCESS_F32, pushf); - F64_LOAD => doLoad(ACCESS_F64, pushd); - I32_LOAD8_S => doLoad(ACCESS_I8, pushi8); - I32_LOAD8_U => doLoad(ACCESS_U8, pushu8); - I32_LOAD16_S => doLoad(ACCESS_I16, pushi16); - I32_LOAD16_U => doLoad(ACCESS_U16, pushu16); - I64_LOAD8_S => doLoad(ACCESS_I8, pushl8); - I64_LOAD8_U => doLoad(ACCESS_U8, pushw8); - I64_LOAD16_S => doLoad(ACCESS_I16, pushl16); - I64_LOAD16_U => doLoad(ACCESS_U16, pushw16); - I64_LOAD32_S => doLoad(ACCESS_I32, pushl32); - I64_LOAD32_U => doLoad(ACCESS_U32, pushw32); - I32_STORE => doStore(ACCESS_U32, popu()); - I64_STORE => doStore(ACCESS_U64, popw()); - F32_STORE => doStore(ACCESS_F32, popf()); - F64_STORE => doStore(ACCESS_F64, popd()); - I32_STORE8 => doStore(ACCESS_U8, popu8()); - I32_STORE16 => doStore(ACCESS_U16, popu16()); - I64_STORE8 => doStore(ACCESS_U8, popw8()); - I64_STORE16 => doStore(ACCESS_U16, popw16()); - I64_STORE32 => doStore(ACCESS_U32, popw32()); + I32_LOAD => doLoad(MemoryAccessors.U32, pushu); + I64_LOAD => doLoad(MemoryAccessors.U64, pushw); + F32_LOAD => doLoad(MemoryAccessors.F32, pushf); + F64_LOAD => doLoad(MemoryAccessors.F64, pushd); + I32_LOAD8_S => doLoad(MemoryAccessors.I8, pushi8); + I32_LOAD8_U => doLoad(MemoryAccessors.U8, pushu8); + I32_LOAD16_S => doLoad(MemoryAccessors.I16, pushi16); + I32_LOAD16_U => doLoad(MemoryAccessors.U16, pushu16); + I64_LOAD8_S => doLoad(MemoryAccessors.I8, pushl8); + I64_LOAD8_U => doLoad(MemoryAccessors.U8, pushw8); + I64_LOAD16_S => doLoad(MemoryAccessors.I16, pushl16); + I64_LOAD16_U => doLoad(MemoryAccessors.U16, pushw16); + I64_LOAD32_S => doLoad(MemoryAccessors.I32, pushl32); + I64_LOAD32_U => doLoad(MemoryAccessors.U32, pushw32); + I32_STORE => doStore(MemoryAccessors.U32, popu()); + I64_STORE => doStore(MemoryAccessors.U64, popw()); + F32_STORE => doStore(MemoryAccessors.F32, popf()); + F64_STORE => doStore(MemoryAccessors.F64, popd()); + I32_STORE8 => doStore(MemoryAccessors.U8, popu8()); + I32_STORE16 => doStore(MemoryAccessors.U16, popu16()); + I64_STORE8 => doStore(MemoryAccessors.U8, popw8()); + I64_STORE16 => doStore(MemoryAccessors.U16, popw16()); + I64_STORE32 => doStore(MemoryAccessors.U32, popw32()); // Atomic operations MEMORY_ATOMIC_NOTIFY => { @@ -510,70 +510,70 @@ class V3Interpreter extends WasmStack { Runtime.ATOMIC_FENCE(); } - I32_ATOMIC_LOAD => doAtomicLoad(ACCESS_U32, pushu); - I64_ATOMIC_LOAD => doAtomicLoad(ACCESS_U64, pushw); - I32_ATOMIC_LOAD8_U => doAtomicLoad(ACCESS_U8, pushu8); - I32_ATOMIC_LOAD16_U => doAtomicLoad(ACCESS_U16, pushu16); - I64_ATOMIC_LOAD8_U => doAtomicLoad(ACCESS_U8, pushw8); - I64_ATOMIC_LOAD16_U => doAtomicLoad(ACCESS_U16, pushw16); - I64_ATOMIC_LOAD32_U => doAtomicLoad(ACCESS_U32, pushw32); - I32_ATOMIC_STORE => doAtomicStore(ACCESS_U32, popu); - I64_ATOMIC_STORE => doAtomicStore(ACCESS_U64, popw); - I32_ATOMIC_STORE8 => doAtomicStore(ACCESS_U8, popu8); - I32_ATOMIC_STORE16 => doAtomicStore(ACCESS_U16, popu16); - I64_ATOMIC_STORE8 => doAtomicStore(ACCESS_U8, popw8); - I64_ATOMIC_STORE16 => doAtomicStore(ACCESS_U16, popw16); - I64_ATOMIC_STORE32 => doAtomicStore(ACCESS_U32, popw32); - - I32_ATOMIC_RMW_ADD => doAtomicRmw(ACCESS_U32, popu(), V3Eval.I32_ADD, pushu); - I64_ATOMIC_RMW_ADD => doAtomicRmw(ACCESS_U64, popw(), V3Eval.I64_ADD, pushw); - I32_ATOMIC_RMW8_ADD_U => doAtomicRmw(ACCESS_U8, popu8(), u8.+, pushu8); - I32_ATOMIC_RMW16_ADD_U => doAtomicRmw(ACCESS_U16, popu16(), u16.+, pushu16); - I64_ATOMIC_RMW8_ADD_U => doAtomicRmw(ACCESS_U8, popw8(), u8.+, pushw8); - I64_ATOMIC_RMW16_ADD_U => doAtomicRmw(ACCESS_U16, popw16(), u16.+, pushw16); - I64_ATOMIC_RMW32_ADD_U => doAtomicRmw(ACCESS_U32, popw32(), u32.+, pushw32); - I32_ATOMIC_RMW_SUB => doAtomicRmw(ACCESS_U32, popu(), V3Eval.I32_SUB, pushu); - I64_ATOMIC_RMW_SUB => doAtomicRmw(ACCESS_U64, popw(), V3Eval.I64_SUB, pushw); - I32_ATOMIC_RMW8_SUB_U => doAtomicRmw(ACCESS_U8, popu8(), u8.-, pushu8); - I32_ATOMIC_RMW16_SUB_U => doAtomicRmw(ACCESS_U16, popu16(), u16.-, pushu16); - I64_ATOMIC_RMW8_SUB_U => doAtomicRmw(ACCESS_U8, popw8(), u8.-, pushw8); - I64_ATOMIC_RMW16_SUB_U => doAtomicRmw(ACCESS_U16, popw16(), u16.-, pushw16); - I64_ATOMIC_RMW32_SUB_U => doAtomicRmw(ACCESS_U32, popw32(), u32.-, pushw32); - I32_ATOMIC_RMW_AND => doAtomicRmw(ACCESS_U32, popu(), V3Eval.I32_AND, pushu); - I64_ATOMIC_RMW_AND => doAtomicRmw(ACCESS_U64, popw(), V3Eval.I64_AND, pushw); - I32_ATOMIC_RMW8_AND_U => doAtomicRmw(ACCESS_U8, popu8(), u8.&, pushu8); - I32_ATOMIC_RMW16_AND_U => doAtomicRmw(ACCESS_U16, popu16(), u16.&, pushu16); - I64_ATOMIC_RMW8_AND_U => doAtomicRmw(ACCESS_U8, popw8(), u8.&, pushw8); - I64_ATOMIC_RMW16_AND_U => doAtomicRmw(ACCESS_U16, popw16(), u16.&, pushw16); - I64_ATOMIC_RMW32_AND_U => doAtomicRmw(ACCESS_U32, popw32(), u32.&, pushw32); - I32_ATOMIC_RMW_OR => doAtomicRmw(ACCESS_U32, popu(), V3Eval.I32_OR, pushu); - I64_ATOMIC_RMW_OR => doAtomicRmw(ACCESS_U64, popw(), V3Eval.I64_AND, pushw); - I32_ATOMIC_RMW8_OR_U => doAtomicRmw(ACCESS_U8, popu8(), u8.|, pushu8); - I32_ATOMIC_RMW16_OR_U => doAtomicRmw(ACCESS_U16, popu16(), u16.|, pushu16); - I64_ATOMIC_RMW8_OR_U => doAtomicRmw(ACCESS_U8, popw8(), u8.|, pushw8); - I64_ATOMIC_RMW16_OR_U => doAtomicRmw(ACCESS_U16, popw16(), u16.|, pushw16); - I64_ATOMIC_RMW32_OR_U => doAtomicRmw(ACCESS_U32, popw32(), u32.|, pushw32); - I32_ATOMIC_RMW_XOR => doAtomicRmw(ACCESS_U32, popu(), V3Eval.I32_XOR, pushu); - I64_ATOMIC_RMW_XOR => doAtomicRmw(ACCESS_U64, popw(), V3Eval.I64_XOR, pushw); - I32_ATOMIC_RMW8_XOR_U => doAtomicRmw(ACCESS_U8, popu8(), u8.^, pushu8); - I32_ATOMIC_RMW16_XOR_U => doAtomicRmw(ACCESS_U16, popu16(), u16.^, pushu16); - I64_ATOMIC_RMW8_XOR_U => doAtomicRmw(ACCESS_U8, popw8(), u8.^, pushw8); - I64_ATOMIC_RMW16_XOR_U => doAtomicRmw(ACCESS_U16, popw16(), u16.^, pushw16); - I64_ATOMIC_RMW32_XOR_U => doAtomicRmw(ACCESS_U32, popw32(), u32.^, pushw32); - I32_ATOMIC_RMW_XCHG => doAtomicXchg(ACCESS_U32, popu(), pushu); - I64_ATOMIC_RMW_XCHG => doAtomicXchg(ACCESS_U64, popw(), pushw); - I32_ATOMIC_RMW8_XCHG_U => doAtomicXchg(ACCESS_U8, popu8(), pushu8); - I32_ATOMIC_RMW16_XCHG_U => doAtomicXchg(ACCESS_U16, popu16(), pushu16); - I64_ATOMIC_RMW8_XCHG_U => doAtomicXchg(ACCESS_U8, popw8(), pushw8); - I64_ATOMIC_RMW16_XCHG_U => doAtomicXchg(ACCESS_U16, popw16(), pushw16); - I64_ATOMIC_RMW32_XCHG_U => doAtomicXchg(ACCESS_U32, popw32(), pushw32); - I32_ATOMIC_RMW_CMPXCHG => doAtomicCmpXchg(ACCESS_U32, popu(), popu(), pushu); - I64_ATOMIC_RMW_CMPXCHG => doAtomicCmpXchg(ACCESS_U64, popw(), popw(), pushw); - I32_ATOMIC_RMW8_CMPXCHG_U => doAtomicCmpXchg(ACCESS_U8, popu8(), popu8(), pushu8); - I32_ATOMIC_RMW16_CMPXCHG_U => doAtomicCmpXchg(ACCESS_U16, popu16(), popu16(), pushu16); - I64_ATOMIC_RMW8_CMPXCHG_U => doAtomicCmpXchg(ACCESS_U8, popw8(), popw8(), pushw8); - I64_ATOMIC_RMW16_CMPXCHG_U => doAtomicCmpXchg(ACCESS_U16, popw16(), popw16(), pushw16); - I64_ATOMIC_RMW32_CMPXCHG_U => doAtomicCmpXchg(ACCESS_U32, popw32(), popw32(), pushw32); + I32_ATOMIC_LOAD => doAtomicLoad(MemoryAccessors.U32, pushu); + I64_ATOMIC_LOAD => doAtomicLoad(MemoryAccessors.U64, pushw); + I32_ATOMIC_LOAD8_U => doAtomicLoad(MemoryAccessors.U8, pushu8); + I32_ATOMIC_LOAD16_U => doAtomicLoad(MemoryAccessors.U16, pushu16); + I64_ATOMIC_LOAD8_U => doAtomicLoad(MemoryAccessors.U8, pushw8); + I64_ATOMIC_LOAD16_U => doAtomicLoad(MemoryAccessors.U16, pushw16); + I64_ATOMIC_LOAD32_U => doAtomicLoad(MemoryAccessors.U32, pushw32); + I32_ATOMIC_STORE => doAtomicStore(MemoryAccessors.U32, popu); + I64_ATOMIC_STORE => doAtomicStore(MemoryAccessors.U64, popw); + I32_ATOMIC_STORE8 => doAtomicStore(MemoryAccessors.U8, popu8); + I32_ATOMIC_STORE16 => doAtomicStore(MemoryAccessors.U16, popu16); + I64_ATOMIC_STORE8 => doAtomicStore(MemoryAccessors.U8, popw8); + I64_ATOMIC_STORE16 => doAtomicStore(MemoryAccessors.U16, popw16); + I64_ATOMIC_STORE32 => doAtomicStore(MemoryAccessors.U32, popw32); + + I32_ATOMIC_RMW_ADD => doAtomicRmw(MemoryAccessors.U32, popu(), V3Eval.I32_ADD, pushu); + I64_ATOMIC_RMW_ADD => doAtomicRmw(MemoryAccessors.U64, popw(), V3Eval.I64_ADD, pushw); + I32_ATOMIC_RMW8_ADD_U => doAtomicRmw(MemoryAccessors.U8, popu8(), u8.+, pushu8); + I32_ATOMIC_RMW16_ADD_U => doAtomicRmw(MemoryAccessors.U16, popu16(), u16.+, pushu16); + I64_ATOMIC_RMW8_ADD_U => doAtomicRmw(MemoryAccessors.U8, popw8(), u8.+, pushw8); + I64_ATOMIC_RMW16_ADD_U => doAtomicRmw(MemoryAccessors.U16, popw16(), u16.+, pushw16); + I64_ATOMIC_RMW32_ADD_U => doAtomicRmw(MemoryAccessors.U32, popw32(), u32.+, pushw32); + I32_ATOMIC_RMW_SUB => doAtomicRmw(MemoryAccessors.U32, popu(), V3Eval.I32_SUB, pushu); + I64_ATOMIC_RMW_SUB => doAtomicRmw(MemoryAccessors.U64, popw(), V3Eval.I64_SUB, pushw); + I32_ATOMIC_RMW8_SUB_U => doAtomicRmw(MemoryAccessors.U8, popu8(), u8.-, pushu8); + I32_ATOMIC_RMW16_SUB_U => doAtomicRmw(MemoryAccessors.U16, popu16(), u16.-, pushu16); + I64_ATOMIC_RMW8_SUB_U => doAtomicRmw(MemoryAccessors.U8, popw8(), u8.-, pushw8); + I64_ATOMIC_RMW16_SUB_U => doAtomicRmw(MemoryAccessors.U16, popw16(), u16.-, pushw16); + I64_ATOMIC_RMW32_SUB_U => doAtomicRmw(MemoryAccessors.U32, popw32(), u32.-, pushw32); + I32_ATOMIC_RMW_AND => doAtomicRmw(MemoryAccessors.U32, popu(), V3Eval.I32_AND, pushu); + I64_ATOMIC_RMW_AND => doAtomicRmw(MemoryAccessors.U64, popw(), V3Eval.I64_AND, pushw); + I32_ATOMIC_RMW8_AND_U => doAtomicRmw(MemoryAccessors.U8, popu8(), u8.&, pushu8); + I32_ATOMIC_RMW16_AND_U => doAtomicRmw(MemoryAccessors.U16, popu16(), u16.&, pushu16); + I64_ATOMIC_RMW8_AND_U => doAtomicRmw(MemoryAccessors.U8, popw8(), u8.&, pushw8); + I64_ATOMIC_RMW16_AND_U => doAtomicRmw(MemoryAccessors.U16, popw16(), u16.&, pushw16); + I64_ATOMIC_RMW32_AND_U => doAtomicRmw(MemoryAccessors.U32, popw32(), u32.&, pushw32); + I32_ATOMIC_RMW_OR => doAtomicRmw(MemoryAccessors.U32, popu(), V3Eval.I32_OR, pushu); + I64_ATOMIC_RMW_OR => doAtomicRmw(MemoryAccessors.U64, popw(), V3Eval.I64_AND, pushw); + I32_ATOMIC_RMW8_OR_U => doAtomicRmw(MemoryAccessors.U8, popu8(), u8.|, pushu8); + I32_ATOMIC_RMW16_OR_U => doAtomicRmw(MemoryAccessors.U16, popu16(), u16.|, pushu16); + I64_ATOMIC_RMW8_OR_U => doAtomicRmw(MemoryAccessors.U8, popw8(), u8.|, pushw8); + I64_ATOMIC_RMW16_OR_U => doAtomicRmw(MemoryAccessors.U16, popw16(), u16.|, pushw16); + I64_ATOMIC_RMW32_OR_U => doAtomicRmw(MemoryAccessors.U32, popw32(), u32.|, pushw32); + I32_ATOMIC_RMW_XOR => doAtomicRmw(MemoryAccessors.U32, popu(), V3Eval.I32_XOR, pushu); + I64_ATOMIC_RMW_XOR => doAtomicRmw(MemoryAccessors.U64, popw(), V3Eval.I64_XOR, pushw); + I32_ATOMIC_RMW8_XOR_U => doAtomicRmw(MemoryAccessors.U8, popu8(), u8.^, pushu8); + I32_ATOMIC_RMW16_XOR_U => doAtomicRmw(MemoryAccessors.U16, popu16(), u16.^, pushu16); + I64_ATOMIC_RMW8_XOR_U => doAtomicRmw(MemoryAccessors.U8, popw8(), u8.^, pushw8); + I64_ATOMIC_RMW16_XOR_U => doAtomicRmw(MemoryAccessors.U16, popw16(), u16.^, pushw16); + I64_ATOMIC_RMW32_XOR_U => doAtomicRmw(MemoryAccessors.U32, popw32(), u32.^, pushw32); + I32_ATOMIC_RMW_XCHG => doAtomicXchg(MemoryAccessors.U32, popu(), pushu); + I64_ATOMIC_RMW_XCHG => doAtomicXchg(MemoryAccessors.U64, popw(), pushw); + I32_ATOMIC_RMW8_XCHG_U => doAtomicXchg(MemoryAccessors.U8, popu8(), pushu8); + I32_ATOMIC_RMW16_XCHG_U => doAtomicXchg(MemoryAccessors.U16, popu16(), pushu16); + I64_ATOMIC_RMW8_XCHG_U => doAtomicXchg(MemoryAccessors.U8, popw8(), pushw8); + I64_ATOMIC_RMW16_XCHG_U => doAtomicXchg(MemoryAccessors.U16, popw16(), pushw16); + I64_ATOMIC_RMW32_XCHG_U => doAtomicXchg(MemoryAccessors.U32, popw32(), pushw32); + I32_ATOMIC_RMW_CMPXCHG => doAtomicCmpXchg(MemoryAccessors.U32, popu(), popu(), pushu); + I64_ATOMIC_RMW_CMPXCHG => doAtomicCmpXchg(MemoryAccessors.U64, popw(), popw(), pushw); + I32_ATOMIC_RMW8_CMPXCHG_U => doAtomicCmpXchg(MemoryAccessors.U8, popu8(), popu8(), pushu8); + I32_ATOMIC_RMW16_CMPXCHG_U => doAtomicCmpXchg(MemoryAccessors.U16, popu16(), popu16(), pushu16); + I64_ATOMIC_RMW8_CMPXCHG_U => doAtomicCmpXchg(MemoryAccessors.U8, popw8(), popw8(), pushw8); + I64_ATOMIC_RMW16_CMPXCHG_U => doAtomicCmpXchg(MemoryAccessors.U16, popw16(), popw16(), pushw16); + I64_ATOMIC_RMW32_CMPXCHG_U => doAtomicCmpXchg(MemoryAccessors.U32, popw32(), popw32(), pushw32); MEMORY_SIZE => { var index = codeptr.read_uleb32(); @@ -985,28 +985,28 @@ class V3Interpreter extends WasmStack { I64_SUB128 => do_wwww_ww(V3Eval.I64_SUB128); I64_MUL_WIDE_S => do_ll_ww(V3Eval.I64_MUL_WIDE_S); I64_MUL_WIDE_U => do_ww_ww(V3Eval.I64_MUL_WIDE_U); - V128_LOAD => doLoad(ACCESS_V128, pushs); - V128_LOAD_64_LANE => doLoadLane(ACCESS_U64); - V128_LOAD_32_LANE => doLoadLane(ACCESS_U32); - V128_LOAD_16_LANE => doLoadLane(ACCESS_U16); - V128_LOAD_8_LANE => doLoadLane(ACCESS_U8); - V128_LOAD_64_SPLAT => doLoadSplat(ACCESS_U64); - V128_LOAD_32_SPLAT => doLoadSplat(ACCESS_U32); - V128_LOAD_16_SPLAT => doLoadSplat(ACCESS_U16); - V128_LOAD_8_SPLAT => doLoadSplat(ACCESS_U8); - V128_LOAD_32_ZERO => doLoadZero(ACCESS_U32); - V128_LOAD_64_ZERO => doLoadZero(ACCESS_U64); + V128_LOAD => doLoad(MemoryAccessors.V128, pushs); + V128_LOAD_64_LANE => doLoadLane(MemoryAccessors.U64); + V128_LOAD_32_LANE => doLoadLane(MemoryAccessors.U32); + V128_LOAD_16_LANE => doLoadLane(MemoryAccessors.U16); + V128_LOAD_8_LANE => doLoadLane(MemoryAccessors.U8); + V128_LOAD_64_SPLAT => doLoadSplat(MemoryAccessors.U64); + V128_LOAD_32_SPLAT => doLoadSplat(MemoryAccessors.U32); + V128_LOAD_16_SPLAT => doLoadSplat(MemoryAccessors.U16); + V128_LOAD_8_SPLAT => doLoadSplat(MemoryAccessors.U8); + V128_LOAD_32_ZERO => doLoadZero(MemoryAccessors.U32); + V128_LOAD_64_ZERO => doLoadZero(MemoryAccessors.U64); V128_LOAD_8X8_S => doLoadExtend(1, i8.view, i16.view, u16.view); V128_LOAD_8X8_U => doLoadExtend(1, u8.view, u16.view, u16.view); V128_LOAD_16X4_S => doLoadExtend(2, i16.view, i32.view, u32.view); V128_LOAD_16X4_U => doLoadExtend(2, u16.view, u32.view, u32.view); V128_LOAD_32X2_S => doLoadExtend(4, i32.view, i64.view, u64.view); V128_LOAD_32X2_U => doLoadExtend(4, u32.view, u64.view, u64.view); - V128_STORE => doStore(ACCESS_V128, pops()); - V128_STORE_8_LANE => doStoreLane(ACCESS_U8, u8.view); - V128_STORE_16_LANE => doStoreLane(ACCESS_U16, u16.view); - V128_STORE_32_LANE => doStoreLane(ACCESS_U32, u32.view); - V128_STORE_64_LANE => doStoreLane(ACCESS_U64, u64.view); + V128_STORE => doStore(MemoryAccessors.V128, pops()); + V128_STORE_8_LANE => doStoreLane(MemoryAccessors.U8, u8.view); + V128_STORE_16_LANE => doStoreLane(MemoryAccessors.U16, u16.view); + V128_STORE_32_LANE => doStoreLane(MemoryAccessors.U32, u32.view); + V128_STORE_64_LANE => doStoreLane(MemoryAccessors.U64, u64.view); V128_CONST => { var low = codeptr.read_u64(); var high = codeptr.read_u64(); @@ -1405,23 +1405,23 @@ class V3Interpreter extends WasmStack { var index = popa(memory.decl.size); return memory.range_oil_64(memarg.offset, index, size); } - def doLoad(accessor: MemoryAccessor, push: T -> void) { + def doLoad(accessor: MemoryAccessorOf, push: T -> void) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); push(accessor.read(t.result)); } - def doAtomicLoad(accessor: MemoryAccessor, push: T -> void) { + def doAtomicLoad(accessor: MemoryAccessorOf, push: T -> void) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); push(accessor.read(t.result)); // XXX: assumes "read" function is atomic } - def doAtomicStore(accessor: MemoryAccessor, pop: void -> T) { + def doAtomicStore(accessor: MemoryAccessorOf, pop: void -> T) { var val = pop(); var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); accessor.write(t.result, val); // XXX: assumes "write" function is atomic } - def doAtomicRmw(accessor: MemoryAccessor, val: T, op: (T, T) -> T, push: T -> void) { + def doAtomicRmw(accessor: MemoryAccessorOf, val: T, op: (T, T) -> T, push: T -> void) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); var prev = accessor.read(t.result); // XXX: assumes no real threads @@ -1429,21 +1429,21 @@ class V3Interpreter extends WasmStack { accessor.write(t.result, updated); push(prev); } - def doAtomicXchg(accessor: MemoryAccessor, replacement: T, push: T -> void) { + def doAtomicXchg(accessor: MemoryAccessorOf, replacement: T, push: T -> void) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); var loaded = accessor.read(t.result); // XXX: assumes no real threads accessor.write(t.result, replacement); push(loaded); } - def doAtomicCmpXchg(accessor: MemoryAccessor, replacement: T, expected: T, push: T -> void) { + def doAtomicCmpXchg(accessor: MemoryAccessorOf, replacement: T, expected: T, push: T -> void) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); var loaded = accessor.read(t.result); // XXX: assumes no real threads if (loaded == expected) accessor.write(t.result, replacement); push(loaded); } - def doLoadLane(accessor: MemoryAccessor) { + def doLoadLane(accessor: MemoryAccessorOf) { var v = pops(); var t = decodeMemArgAndGetMemoryRange(accessor.size); var idx = codeptr.read1(); @@ -1461,7 +1461,7 @@ class V3Interpreter extends WasmStack { } pushs(low, high); } - def doLoadZero(accessor: MemoryAccessor) { + def doLoadZero(accessor: MemoryAccessorOf) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); var val = u64.!(accessor.read(t.result)); @@ -1567,7 +1567,7 @@ class V3Interpreter extends WasmStack { } return res; } - def doLoadSplat(accessor: MemoryAccessor) { + def doLoadSplat(accessor: MemoryAccessorOf) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) return void(trap(t.reason)); var val = u64.!(accessor.read(t.result)); @@ -1589,12 +1589,12 @@ class V3Interpreter extends WasmStack { } push(Value.V128(low, high)); } - def doStore(accessor: MemoryAccessor, val: T) { + def doStore(accessor: MemoryAccessorOf, val: T) { var t = decodeMemArgAndGetMemoryRange(accessor.size); if (t.reason != TrapReason.NONE) trap(t.reason); else accessor.write(t.result, val); } - def doStoreLane(accessor: MemoryAccessor, view: u64 -> T) { + def doStoreLane(accessor: MemoryAccessorOf, view: u64 -> T) { var v = pops(); var t = decodeMemArgAndGetMemoryRange(accessor.size); var idx = codeptr.read1(); // get lane immediate @@ -2219,19 +2219,6 @@ private class V3FrameWriter extends FrameWriter { } def fatal = System.error("V3InterpreterError", _); -// Connect a Virgil type to accessing memory (read, write, and push/pop from value stack). -private class MemoryAccessor(size: byte, log2_size: u3, read: Range -> T, write: (Range, T) -> void) { } - -def ACCESS_I8 = MemoryAccessor.new(1, 0, DataReaders.read_range_i8, DataWriters.write_range_i8); -def ACCESS_U8 = MemoryAccessor.new(1, 0, DataReaders.read_range_u8, DataWriters.write_range_u8); -def ACCESS_I16 = MemoryAccessor.new(2, 1, DataReaders.read_range_i16, DataWriters.write_range_i16); -def ACCESS_U16 = MemoryAccessor.new(2, 1, DataReaders.read_range_u16, DataWriters.write_range_u16); -def ACCESS_I32 = MemoryAccessor.new(4, 2, DataReaders.read_range_i32, DataWriters.write_range_i32); -def ACCESS_U32 = MemoryAccessor.new(4, 2, DataReaders.read_range_u32, DataWriters.write_range_u32); -def ACCESS_U64 = MemoryAccessor.new(8, 3, DataReaders.read_range_u64, DataWriters.write_range_u64); -def ACCESS_F32 = MemoryAccessor.new(4, 2, DataReaders.read_range_float, DataWriters.write_range_float); -def ACCESS_F64 = MemoryAccessor.new(8, 3, DataReaders.read_range_double, DataWriters.write_range_double); -def ACCESS_V128 = MemoryAccessor.new(16, 4, DataReaders.read_range_u128, DataWriters.write_range_u128); def make_new_v3_stack(func: Function) -> WasmStack { var stack = V3Interpreter.new(); diff --git a/src/util/MemoryAccessors.v3 b/src/util/MemoryAccessors.v3 new file mode 100644 index 000000000..dd0d77e3c --- /dev/null +++ b/src/util/MemoryAccessors.v3 @@ -0,0 +1,49 @@ +// Copyright 2026 WizardAuthors. All rights reserved. +// See LICENSE for details of Apache 2.0 license. + +// A utility to read/write primitive Wasm values into byte arrays. +class MemoryAccessor(size: byte, log2_size: u3) { + def readValue(r: Range) -> Value; + def writeValue(r: Range, v: Value); +} + +// A utility that connects a Virgil type to accessing memory (read, write) as well +// as boxing and unboxing to {Value}. +class MemoryAccessorOf extends MemoryAccessor { + def read: Range -> T; + def write: (Range, T) -> void; + def box: T -> Value; + def unbox: Value -> T; + + new(size: byte, log2_size: u3, read, write, box, unbox) super(size, log2_size) { } + + def readValue(r: Range) => box(read(r)); + def writeValue(r: Range, v: Value) => void(write(r, unbox(v))); +} + +// All of the primitive accessors for memory. +component MemoryAccessors { + def I8 = MemoryAccessorOf.new(1, 0, DataReaders.read_range_i8, DataWriters.write_range_i8, fun (d: i8) => Value.I32(u32.view(d)), fun (v: Value) => i8.view(Value.I32.!(v).val)); + def U8 = MemoryAccessorOf.new(1, 0, DataReaders.read_range_u8, DataWriters.write_range_u8, fun (d: u8) => Value.I32(d), fun (v: Value) => u8.view(Value.I32.!(v).val)); + def I16 = MemoryAccessorOf.new(2, 1, DataReaders.read_range_i16, DataWriters.write_range_i16, fun (d: i16) => Value.I32(u32.view(d)), fun (v: Value) => i16.view(Value.I32.!(v).val)); + def U16 = MemoryAccessorOf.new(2, 1, DataReaders.read_range_u16, DataWriters.write_range_u16, fun (d: u16) => Value.I32(d), fun (v: Value) => u16.view(Value.I32.!(v).val)); + def I32 = MemoryAccessorOf.new(4, 2, DataReaders.read_range_i32, DataWriters.write_range_i32, Values.box_i, Values.unbox_i); + def U32 = MemoryAccessorOf.new(4, 2, DataReaders.read_range_u32, DataWriters.write_range_u32, Value.I32, Values.unbox_u); + def U64 = MemoryAccessorOf.new(8, 3, DataReaders.read_range_u64, DataWriters.write_range_u64, Value.I64, Values.unbox_w); + def F32 = MemoryAccessorOf.new(4, 2, DataReaders.read_range_float, DataWriters.write_range_float, Values.box_f, Values.unbox_f); + def F64 = MemoryAccessorOf.new(8, 3, DataReaders.read_range_double, DataWriters.write_range_double, Values.box_d, Values.unbox_d); + def V128 = MemoryAccessorOf.new(16, 4, DataReaders.read_range_u128, DataWriters.write_range_u128, Values.box_s, Values.unbox_s); +} + +enum MemStorageKind(signed: bool, isFloat: bool, size: byte, log2_size: u3, accessor: MemoryAccessor) { + I8 (true, false, 1, 0, MemoryAccessors.I8), + U8 (false, false, 1, 0, MemoryAccessors.U8), + I16 (true, false, 2, 1, MemoryAccessors.I16), + U16 (false, false, 2, 1, MemoryAccessors.U16), + I32 (true, false, 4, 2, MemoryAccessors.I32), + U32 (false, false, 4, 2, MemoryAccessors.U32), + U64 (false, false, 8, 3, MemoryAccessors.U64), + F32 (false, true, 4, 2, MemoryAccessors.F32), + F64 (false, true, 8, 3, MemoryAccessors.F64), + V128 (false, false, 16, 4, MemoryAccessors.V128) +}