def trunc_sat(vm, args): if args == 0: # i32.trunc_sat_f32_s v = __trunc_sat_s(vm.pop_f32(), 32) vm.push_s32(int32(v)) elif args == 1: # i32.trunc_sat_f32_u v = __trunc_sat_u(vm.pop_f32(), 32) vm.push_u32(uint32(v)) elif args == 2: # i32.trunc_sat_f64_s v = __trunc_sat_s(vm.pop_f64(), 32) vm.push_s32(int32(v)) elif args == 3: # i32.trunc_sat_f64_u v = __trunc_sat_u(vm.pop_f64(), 32) vm.push_u32(uint32(v)) elif args == 4: # i64.trunc_sat_f32_s v = __trunc_sat_s(vm.pop_f32(), 64) vm.push_s64(v) elif args == 5: # i64.trunc_sat_f32_u v = __trunc_sat_u(vm.pop_f32(), 64) vm.push_u64(v) elif args == 6: # i64.trunc_sat_f64_s v = __trunc_sat_s(vm.pop_f64(), 64) vm.push_s64(v) elif args == 7: # i64.trunc_sat_f64_u v = __trunc_sat_u(vm.pop_f64(), 64) vm.push_u64(v) else: raise Exception("unreachable")
def test_nan(self): self.assertEqual(uint32(0x7fc00000), float32(str(math.nan))) self.assertEqual(uint32(0xffc00000), float32('-nan')) self.assertEqual(uint32(0x7f800000), float32(str(math.inf))) self.assertEqual(uint32(0xff800000), float32('-inf')) self.assertEqual(uint64(0x7ff8000000000001), float64(str(math.nan))) self.assertEqual(uint64(0xfff8000000000001), float64('-nan')) self.assertEqual(uint64(0x7ff0000000000000), float64(str(math.inf))) self.assertEqual(uint64(0xfff0000000000000), float64('-inf'))
def parse_u32(s: str): base = 10 s = s.replace("_", "") if s.find("0x") >= 0: base = 16 s = s.replace("0x", "", 1) i = int(s, base) return uint32(i)
def i32_trunc_f64u(vm, _): val = vm.pop_f64() if math.isinf(val): raise ErrIntOverflow if math.isnan(val): raise ErrConvertToInt f = math.trunc(val) if f > __MaxUint32 or f < 0: raise ErrIntOverflow vm.push_u32(uint32(f))
def parse_nan32(s: str): s = s.replace("_", "") f = float32(math.nan) if s[0] == '-': f = -f s = s[1:] elif s[0] == '+': s = s[1:] if s.startswith("nan:0x"): payload = int(s[6:], 16) bits = struct.unpack('>l', struct.pack('>f', f))[0] & 0xFFBFFFFF try: f = float32( struct.unpack('>f', struct.pack('>l', int64(bits | uint32(payload))))[0]) except struct.error: f = float32(math.nan) return f
def test_operand_stack(self): stack = OperandStack() stack.push_bool(True) stack.push_bool(False) stack.push_u32(1) stack.push_s32(-2) stack.push_u64(3) stack.push_s64(-4) stack.push_f32(5.5) stack.push_f64(6.5) self.assertEqual(6.5, stack.pop_f64()) self.assertEqual(float32(5.5), stack.pop_f32()) self.assertEqual(int64(-4), stack.pop_s64()) self.assertEqual(uint64(3), stack.pop_u64()) self.assertEqual(int32(-2), stack.pop_s32()) self.assertEqual(uint32(1), stack.pop_u32()) self.assertEqual(False, stack.pop_bool()) self.assertEqual(True, stack.pop_bool()) self.assertEqual(0, len(stack.slots))
def i32_load_16u(vm, mem_arg): val = read_u16(vm, mem_arg) vm.push_u32(uint32(val))
def i32_load_8u(vm, mem_arg): val = read_u8(vm, mem_arg) vm.push_u32(uint32(val))
def i64_store_32(vm, mem_arg): val = vm.pop_u64() write_u32(vm, mem_arg, uint32(val))
def read_u32(vm, mem_arg): buf = [0x00] * 4 offset = get_offset(vm, mem_arg) buf = vm.memory.read(offset, buf) return uint32(int.from_bytes(bytearray(buf), byteorder='little'))
def local_set(vm, args): """设置局部变量的值""" idx = uint32(args) val = vm.pop_u64() vm.set_operand(vm.local_0_idx + idx, val)
def local_tee(vm, args): """用重定向操作符>把某个命令的输出重定向到文件里""" idx = uint32(args) val = vm.pop_u64() vm.push_u64(val) vm.set_operand(vm.local_0_idx + idx, val)
def i32_wrap_i64(vm, _): vm.push_u32(uint32(vm.pop_u64()))
def i32_pop_cnt(vm, _): """统计1比特数""" vm.push_u32(uint32(__ones_count32(vm.pop_u32())))
def i32_ctz(vm, _): """统计后置0比特数""" vm.push_u32(uint32(__trailing_zeros32(vm.pop_u32())))
def local_get(vm, args): """获取局部变量""" idx = uint32(args) val = vm.get_operand(vm.local_0_idx + idx) vm.push_u64(val)
def global_get(vm, args): idx = uint32(args) val = vm.globals[idx].get_as_u64() vm.push_u64(val)
def control_return(vm, _): # 找到函数最外层块的标签索引(也就是当前控制块的深度) _, label_idx = vm.top_call_frame() br(vm, uint32(label_idx))
def push_s32(self, val): self.push_numeric(uint32(val))
def pop_u32(self) -> uint32: return uint32(self.pop_numeric())
def global_set(vm, args): idx = uint32(args) val = vm.pop_u64() vm.globals[idx].set_as_u64(val)
def i32_clz(vm, _): """统计前置0比特数""" vm.push_u32(uint32(__leading_zeros32(vm.pop_u32())))
def add_func(self, ft_idx, locals_vec, expr): self.module.func_sec.append(uint32(ft_idx)) self.module.code_sec.append(Code(locals_vec=locals_vec, expr=expr)) return self.fun_names.imported + len(self.module.func_sec) - 1