def wrap_u64(vt, val): if vt == ValTypeI32: return int32(val) elif vt == ValTypeI64: return int64(val) elif vt == ValTypeF32: try: cov_val = struct.unpack('>f', struct.pack('>l', int64(val)))[0] except struct.error: cov_val = struct.unpack('>f', struct.pack('>L', int64(val)))[0] if math.isnan(cov_val): return float32(val) else: return float32(cov_val) elif vt == ValTypeF64: try: cov_val = struct.unpack('>d', struct.pack('>q', int64(val)))[0] except struct.error: cov_val = struct.unpack('>d', struct.pack('>Q', int64(val)))[0] if math.isnan(cov_val): return float64(val) else: return float64(cov_val) else: raise Exception("unreachable")
def parse_nan64(s: str): s = s.replace("_", "") f = float64(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('>q', struct.pack('>d', f))[0] & 0xFFF7FFFFFFFFFFFE try: f = float64( struct.unpack('>d', struct.pack('>q', int64(bits | payload)))[0]) except struct.error: f = float64(math.nan) else: bits = struct.unpack('>q', struct.pack('>d', f))[0] & 0xFFFFFFFFFFFFFFFE try: f = float64(struct.unpack('>d', struct.pack('>q', int64(bits)))[0]) except struct.error: f = float64(math.nan) return f
def __trunc_sat_s(z, n): if math.isnan(z): return 0 min_value = -(int64(1) << (n - 1)) max_value = (int64(1) << (n - 1)) - 1 if z == -math.inf: return min_value if math.isinf(z): return max_value x = math.trunc(z) if x < float64(min_value): return min_value elif x >= float64(max_value): return max_value else: return int64(x)
def i64_trunc_f64s(vm, _): val = vm.pop_f64() if math.isinf(val): raise ErrIntOverflow if math.isnan(val): raise ErrConvertToInt f = math.trunc(val) if f >= __MaxInt64 or f < __MinInt64: raise ErrIntOverflow vm.push_s64(int64(f))
def parse_int(s, bit_size): base = 10 s = s.replace("_", "") if s.startswith("+"): s = s[1:] if s.find("0x") >= 0: s = s.replace("0x", "", 1) base = 16 if s.startswith("-"): i = int(s, base) else: u = int(s, base) i = int64(u) return i
def get_consts(expr): if len(expr) == 0: vals = [] else: vals = [None] * len(expr) for i, instr in enumerate(expr): opcode = instr.opcode if opcode == I32Const: vals[i] = int32(instr.args) elif opcode == I64Const: vals[i] = int64(instr.args) elif opcode == F32Const: vals[i] = float32(instr.args) elif opcode == F64Const: vals[i] = float64(instr.args) else: raise Exception("TODO") return vals
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 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 i64_extend_16s(vm, _): vm.push_s64(int64(int16(vm.pop_s64())))
def pop_f32(self): val = self.pop_numeric() val = struct.unpack('>f', struct.pack('>l', int64(val)))[0] return float32(val)
def i64_load_32s(vm, mem_arg): val = read_u32(vm, mem_arg) vm.push_s64(int64(int32(val)))
def i64_load_16s(vm, mem_arg): val = read_u16(vm, mem_arg) vm.push_s64(int64(int16(val)))
def i64_load_8s(vm, mem_arg): val = read_u8(vm, mem_arg) vm.push_s64(int64(int8(val)))
def i64_extend_32s(vm, _): vm.push_s64(int64(int32(vm.pop_s64())))
def pop_s64(self) -> int64: return int64(self.pop_numeric())
def i64_extend_8s(vm, _): vm.push_s64(int64(int8(vm.pop_s64())))
def i64_const(vm, args): vm.push_s64(int64(args))
def i64_extend_i32s(vm, _): vm.push_s64(int64(vm.pop_s32()))