def from_reader(cls, r: typing.BinaryIO): code_byte = r.read(1) if not code_byte: return None code = ord(code_byte) code_size = convention.opcodes[code][1] if code_size == '': immediate_arguments = None elif code_size == 'u8': immediate_arguments = common.read_count(r, 8) elif code_size == 'u32': immediate_arguments = common.read_count(r, 32) elif code_size == 'i32': immediate_arguments = num.int2i32(common.read_count(r, 32, signed=True)) elif code_size == 'i64': immediate_arguments = num.int2i64(common.read_count(r, 64, signed=True)) elif code_size == 'f32': immediate_arguments = num.LittleEndian.f32(r.read(4)) elif code_size == 'f64': immediate_arguments = num.LittleEndian.f64(r.read(8)) elif code_size == 'u32,u8': immediate_arguments = [common.read_count(r, 32), common.read_count(r, 8)] elif code_size == 'u32,u32': immediate_arguments = [common.read_count(r, 32) for _ in range(2)] elif code == convention.br_table: n = common.read_count(r, 32) a = [common.read_count(r, 32) for _ in range(n)] b = common.read_count(r, 32) immediate_arguments = [a, b] else: raise Exception('pywasm: invalid code size') return Instruction(code, immediate_arguments)
def parse_val(s: str): t, v = s.split(':') if t == 'i32' and v.startswith('0x'): return num.int2i32(int(v, 16)) if t == 'i32': return num.int2i32(int(v)) if t == 'i64' and v.startswith('0x'): return num.int2i64(int(v, 16)) if t == 'i64': return num.int2i64(int(v)) if t == 'f32' and v.startswith('0x'): return float.fromhex(v) if t == 'f32': return float(v) if t == 'f64' and v.startswith('0x'): return float.fromhex(v) if t == 'f64': return float(v) raise NotImplementedError
def exec_expr( store: Store, frame: Frame, stack: Stack, expr: structure.Expression, ): module = frame.module if not expr.data: raise Exception('pywasm: empty init expr') pc = -1 while True: pc += 1 if pc >= len(expr.data): break i = expr.data[pc] log.debugln(f'{str(i):<18} {stack}') opcode = i.code if opcode >= convention.unreachable and opcode <= convention.call_indirect: if opcode == convention.unreachable: raise Exception('pywasm: reached unreachable') if opcode == convention.nop: continue if opcode == convention.block: arity = 0 if i.immediate_arguments == convention.empty else 1 stack.add(Label(arity, expr.composition[pc][-1] + 1)) continue if opcode == convention.loop: stack.add(Label(0, expr.composition[pc][0])) continue if opcode == convention.if_: c = stack.pop().n arity = 0 if i.immediate_arguments == convention.empty else 1 stack.add(Label(arity, expr.composition[pc][-1] + 1)) if c != 0: continue if len(expr.composition[pc]) > 2: pc = expr.composition[pc][1] continue pc = expr.composition[pc][-1] - 1 continue if opcode == convention.else_: for i in range(len(stack.data)): i = -1 - i e = stack.data[i] if isinstance(e, Label): pc = e.continuation - 1 del stack.data[i] break continue if opcode == convention.end: # label{instr∗} val* end -> val* if stack.status() == Label: for i in range(len(stack.data)): i = -1 - i if isinstance(stack.data[i], Label): del stack.data[i] break continue # frame{F} val* end -> val* v = [stack.pop() for _ in range(frame.arity)][::-1] assert isinstance(stack.pop(), Frame) stack.ext(v) continue if opcode == convention.br: pc = spec_br(i.immediate_arguments, stack) continue if opcode == convention.br_if: if stack.pop().n == 0: continue pc = spec_br(i.immediate_arguments, stack) continue if opcode == convention.br_table: a = i.immediate_arguments[0] l = i.immediate_arguments[1] c = stack.pop().n if c >= 0 and c < len(a): l = a[c] pc = spec_br(l, stack) continue if opcode == convention.return_: v = [stack.pop() for _ in range(frame.arity)][::-1] while True: e = stack.pop() if isinstance(e, Frame): stack.add(e) break stack.ext(v) break if opcode == convention.call: call(module, module.funcaddrs[i.immediate_arguments], store, stack) continue if opcode == convention.call_indirect: if i.immediate_arguments[1] != 0x00: raise Exception("pywasm: zero byte malformed in call_indirect") idx = stack.pop().n tab = store.tables[module.tableaddrs[0]] if not 0 <= idx < len(tab.elem): raise Exception('pywasm: undefined element index') call(module, tab.elem[idx], store, stack) continue continue if opcode == convention.drop: stack.pop() continue if opcode == convention.select: cond = stack.pop().n a = stack.pop() b = stack.pop() if cond: stack.add(b) else: stack.add(a) continue if opcode == convention.get_local: stack.add(frame.locals[i.immediate_arguments]) continue if opcode == convention.set_local: if i.immediate_arguments >= len(frame.locals): frame.locals.extend( [Value.from_i32(0) for _ in range(i.immediate_arguments - len(frame.locals) + 1)] ) frame.locals[i.immediate_arguments] = stack.pop() continue if opcode == convention.tee_local: frame.locals[i.immediate_arguments] = stack.top() continue if opcode == convention.get_global: stack.add(store.globals[module.globaladdrs[i.immediate_arguments]].value) continue if opcode == convention.set_global: store.globals[module.globaladdrs[i.immediate_arguments]] = GlobalInstance(stack.pop(), True) continue if opcode >= convention.i32_load and opcode <= convention.grow_memory: m = store.mems[module.memaddrs[0]] if opcode >= convention.i32_load and opcode <= convention.i64_load32_u: a = stack.pop().n + i.immediate_arguments[1] if a + convention.opcodes[opcode][2] > len(m.data): raise Exception('pywasm: out of bounds memory access') if opcode == convention.i32_load: stack.add(Value.from_i32(num.LittleEndian.i32(m.data[a:a + 4]))) continue if opcode == convention.i64_load: stack.add(Value.from_i64(num.LittleEndian.i64(m.data[a:a + 8]))) continue if opcode == convention.f32_load: stack.add(Value.from_f32(num.LittleEndian.f32(m.data[a:a + 4]))) continue if opcode == convention.f64_load: stack.add(Value.from_f64(num.LittleEndian.f64(m.data[a:a + 8]))) continue if opcode == convention.i32_load8_s: stack.add(Value.from_i32(num.LittleEndian.i8(m.data[a:a + 1]))) continue if opcode == convention.i32_load8_u: stack.add(Value.from_i32(num.LittleEndian.u8(m.data[a:a + 1]))) continue if opcode == convention.i32_load16_s: stack.add(Value.from_i32(num.LittleEndian.i16(m.data[a:a + 2]))) continue if opcode == convention.i32_load16_u: stack.add(Value.from_i32(num.LittleEndian.u16(m.data[a:a + 2]))) continue if opcode == convention.i64_load8_s: stack.add(Value.from_i64(num.LittleEndian.i8(m.data[a:a + 1]))) continue if opcode == convention.i64_load8_u: stack.add(Value.from_i64(num.LittleEndian.u8(m.data[a:a + 1]))) continue if opcode == convention.i64_load16_s: stack.add(Value.from_i64(num.LittleEndian.i16(m.data[a:a + 2]))) continue if opcode == convention.i64_load16_u: stack.add(Value.from_i64(num.LittleEndian.u16(m.data[a:a + 2]))) continue if opcode == convention.i64_load32_s: stack.add(Value.from_i64(num.LittleEndian.i32(m.data[a:a + 4]))) continue if opcode == convention.i64_load32_u: stack.add(Value.from_i64(num.LittleEndian.u32(m.data[a:a + 4]))) continue continue if opcode >= convention.i32_store and opcode <= convention.i64_store32: v = stack.pop().n a = stack.pop().n + i.immediate_arguments[1] if a + convention.opcodes[opcode][2] > len(m.data): raise Exception('pywasm: out of bounds memory access') if opcode == convention.i32_store: m.data[a:a + 4] = num.LittleEndian.pack_i32(v) continue if opcode == convention.i64_store: m.data[a:a + 8] = num.LittleEndian.pack_i64(v) continue if opcode == convention.f32_store: m.data[a:a + 4] = num.LittleEndian.pack_f32(v) continue if opcode == convention.f64_store: m.data[a:a + 8] = num.LittleEndian.pack_f64(v) continue if opcode == convention.i32_store8: m.data[a:a + 1] = num.LittleEndian.pack_i8(num.int2i8(v)) continue if opcode == convention.i32_store16: m.data[a:a + 2] = num.LittleEndian.pack_i16(num.int2i16(v)) continue if opcode == convention.i64_store8: m.data[a:a + 1] = num.LittleEndian.pack_i8(num.int2i8(v)) continue if opcode == convention.i64_store16: m.data[a:a + 2] = num.LittleEndian.pack_i16(num.int2i16(v)) continue if opcode == convention.i64_store32: m.data[a:a + 4] = num.LittleEndian.pack_i32(num.int2i32(v)) continue continue if opcode == convention.current_memory: stack.add(Value.from_i32(m.size)) continue if opcode == convention.grow_memory: cursize = m.size m.grow(stack.pop().n) stack.add(Value.from_i32(cursize)) continue continue if opcode >= convention.i32_const and opcode <= convention.f64_const: if opcode == convention.i32_const: stack.add(Value.from_i32(i.immediate_arguments)) continue if opcode == convention.i64_const: stack.add(Value.from_i64(i.immediate_arguments)) continue if opcode == convention.f32_const: stack.add(Value.from_f32(i.immediate_arguments)) continue if opcode == convention.f64_const: stack.add(Value.from_f64(i.immediate_arguments)) continue continue if opcode == convention.i32_eqz: stack.add(Value.from_i32(int(stack.pop().n == 0))) continue if opcode >= convention.i32_eq and opcode <= convention.i32_geu: b = stack.pop().n a = stack.pop().n if opcode == convention.i32_eq: stack.add(Value.from_i32(int(a == b))) continue if opcode == convention.i32_ne: stack.add(Value.from_i32(int(a != b))) continue if opcode == convention.i32_lts: stack.add(Value.from_i32(int(a < b))) continue if opcode == convention.i32_ltu: stack.add(Value.from_i32(int(num.int2u32(a) < num.int2u32(b)))) continue if opcode == convention.i32_gts: stack.add(Value.from_i32(int(a > b))) continue if opcode == convention.i32_gtu: stack.add(Value.from_i32(int(num.int2u32(a) > num.int2u32(b)))) continue if opcode == convention.i32_les: stack.add(Value.from_i32(int(a <= b))) continue if opcode == convention.i32_leu: stack.add(Value.from_i32(int(num.int2u32(a) <= num.int2u32(b)))) continue if opcode == convention.i32_ges: stack.add(Value.from_i32(int(a >= b))) continue if opcode == convention.i32_geu: stack.add(Value.from_i32(int(num.int2u32(a) >= num.int2u32(b)))) continue continue if opcode == convention.i64_eqz: stack.add(Value.from_i32(int(stack.pop().n == 0))) continue if opcode >= convention.i64_eq and opcode <= convention.i64_geu: b = stack.pop().n a = stack.pop().n if opcode == convention.i64_eq: stack.add(Value.from_i32(int(a == b))) continue if opcode == convention.i64_ne: stack.add(Value.from_i32(int(a != b))) continue if opcode == convention.i64_lts: stack.add(Value.from_i32(int(a < b))) continue if opcode == convention.i64_ltu: stack.add(Value.from_i32(int(num.int2u64(a) < num.int2u64(b)))) continue if opcode == convention.i64_gts: stack.add(Value.from_i32(int(a > b))) continue if opcode == convention.i64_gtu: stack.add(Value.from_i32(int(num.int2u64(a) > num.int2u64(b)))) continue if opcode == convention.i64_les: stack.add(Value.from_i32(int(a <= b))) continue if opcode == convention.i64_leu: stack.add(Value.from_i32(int(num.int2u64(a) <= num.int2u64(b)))) continue if opcode == convention.i64_ges: stack.add(Value.from_i32(int(a >= b))) continue if opcode == convention.i64_geu: stack.add(Value.from_i32(int(num.int2u64(a) >= num.int2u64(b)))) continue continue if opcode >= convention.f32_eq and opcode <= convention.f64_ge: b = stack.pop().n a = stack.pop().n if opcode == convention.f32_eq: stack.add(Value.from_i32(int(a == b))) continue if opcode == convention.f32_ne: stack.add(Value.from_i32(int(a != b))) continue if opcode == convention.f32_lt: stack.add(Value.from_i32(int(a < b))) continue if opcode == convention.f32_gt: stack.add(Value.from_i32(int(a > b))) continue if opcode == convention.f32_le: stack.add(Value.from_i32(int(a <= b))) continue if opcode == convention.f32_ge: stack.add(Value.from_i32(int(a >= b))) continue if opcode == convention.f64_eq: stack.add(Value.from_i32(int(a == b))) continue if opcode == convention.f64_ne: stack.add(Value.from_i32(int(a != b))) continue if opcode == convention.f64_lt: stack.add(Value.from_i32(int(a < b))) continue if opcode == convention.f64_gt: stack.add(Value.from_i32(int(a > b))) continue if opcode == convention.f64_le: stack.add(Value.from_i32(int(a <= b))) continue if opcode == convention.f64_ge: stack.add(Value.from_i32(int(a >= b))) continue continue if opcode >= convention.i32_clz and opcode <= convention.i32_popcnt: a = stack.pop().n if opcode == convention.i32_clz: c = 0 while c < 32 and (a & 0x80000000) == 0: c += 1 a *= 2 stack.add(Value.from_i32(c)) continue if opcode == convention.i32_ctz: c = 0 while c < 32 and (a % 2) == 0: c += 1 a /= 2 stack.add(Value.from_i32(c)) continue if opcode == convention.i32_popcnt: c = 0 for i in range(32): if 0x1 & a: c += 1 a /= 2 stack.add(Value.from_i32(c)) continue continue if opcode >= convention.i32_add and opcode <= convention.i32_rotr: b = stack.pop().n a = stack.pop().n if opcode in [ convention.i32_divs, convention.i32_divu, convention.i32_rems, convention.i32_remu, ]: if b == 0: raise Exception('pywasm: integer divide by zero') if opcode == convention.i32_add: stack.add(Value.from_i32(num.int2i32(a + b))) continue if opcode == convention.i32_sub: stack.add(Value.from_i32(num.int2i32(a - b))) continue if opcode == convention.i32_mul: stack.add(Value.from_i32(num.int2i32(a * b))) continue if opcode == convention.i32_divs: if a == 0x80000000 and b == -1: raise Exception('pywasm: integer overflow') stack.add(Value.from_i32(num.idiv_s(a, b))) continue if opcode == convention.i32_divu: stack.add(Value.from_i32(num.int2i32(num.int2u32(a) // num.int2u32(b)))) continue if opcode == convention.i32_rems: stack.add(Value.from_i32(num.irem_s(a, b))) continue if opcode == convention.i32_remu: stack.add(Value.from_i32(num.int2i32(num.int2u32(a) % num.int2u32(b)))) continue if opcode == convention.i32_and: stack.add(Value.from_i32(a & b)) continue if opcode == convention.i32_or: stack.add(Value.from_i32(a | b)) continue if opcode == convention.i32_xor: stack.add(Value.from_i32(a ^ b)) continue if opcode == convention.i32_shl: stack.add(Value.from_i32(num.int2i32(a << (b % 0x20)))) continue if opcode == convention.i32_shrs: stack.add(Value.from_i32(a >> (b % 0x20))) continue if opcode == convention.i32_shru: stack.add(Value.from_i32(num.int2u32(a) >> (b % 0x20))) continue if opcode == convention.i32_rotl: stack.add(Value.from_i32(num.int2i32(num.rotl_u32(a, b)))) continue if opcode == convention.i32_rotr: stack.add(Value.from_i32(num.int2i32(num.rotr_u32(a, b)))) continue continue if opcode >= convention.i64_clz and opcode <= convention.i64_popcnt: a = stack.pop().n if opcode == convention.i64_clz: if a < 0: stack.add(Value.from_i32(0)) continue c = 1 while c < 63 and (a & 0x4000000000000000) == 0: c += 1 a *= 2 stack.add(Value.from_i64(c)) continue if opcode == convention.i64_ctz: c = 0 while c < 64 and (a % 2) == 0: c += 1 a /= 2 stack.add(Value.from_i64(c)) continue if opcode == convention.i64_popcnt: c = 0 for i in range(64): if 0x1 & a: c += 1 a /= 2 stack.add(Value.from_i64(c)) continue continue if opcode >= convention.i64_add and opcode <= convention.i64_rotr: b = stack.pop().n a = stack.pop().n if opcode in [ convention.i64_divs, convention.i64_divu, convention.i64_rems, convention.i64_remu, ]: if b == 0: raise Exception('pywasm: integer divide by zero') if opcode == convention.i64_add: stack.add(Value.from_i64(num.int2i64(a + b))) continue if opcode == convention.i64_sub: stack.add(Value.from_i64(num.int2i64(a - b))) continue if opcode == convention.i64_mul: stack.add(Value.from_i64(num.int2i64(a * b))) continue if opcode == convention.i64_divs: stack.add(Value.from_i64(num.idiv_s(a, b))) continue if opcode == convention.i64_divu: stack.add(Value.from_i64(num.int2i64(num.int2u64(a) // num.int2u64(b)))) continue if opcode == convention.i64_rems: stack.add(Value.from_i64(num.irem_s(a, b))) if opcode == convention.i64_remu: stack.add(Value.from_i64(num.int2u64(a) % num.int2u64(b))) continue if opcode == convention.i64_and: stack.add(Value.from_i64(a & b)) continue if opcode == convention.i64_or: stack.add(Value.from_i64(a | b)) continue if opcode == convention.i64_xor: stack.add(Value.from_i64(a ^ b)) continue if opcode == convention.i64_shl: stack.add(Value.from_i64(num.int2i64(a << (b % 0x40)))) continue if opcode == convention.i64_shrs: stack.add(Value.from_i64(a >> (b % 0x40))) continue if opcode == convention.i64_shru: stack.add(Value.from_i64(num.int2u64(a) >> (b % 0x40))) continue if opcode == convention.i64_rotl: stack.add(Value.from_i64(num.int2i64(num.rotl_u64(a, b)))) continue if opcode == convention.i64_rotr: stack.add(Value.from_i64(num.int2i64(num.rotr_u64(a, b)))) continue continue if opcode >= convention.f32_abs and opcode <= convention.f32_sqrt: a = stack.pop().n if opcode == convention.f32_abs: stack.add(Value.from_f32(abs(a))) continue if opcode == convention.f32_neg: stack.add(Value.from_f32(-a)) continue if opcode == convention.f32_ceil: stack.add(Value.from_f32(math.ceil(a))) continue if opcode == convention.f32_floor: stack.add(Value.from_f32(math.floor(a))) continue if opcode == convention.f32_trunc: stack.add(Value.from_f32(math.trunc(a))) continue if opcode == convention.f32_nearest: ceil = math.ceil(a) if ceil - a >= 0.5: r = ceil else: r = ceil - 1 stack.add(Value.from_f32(r)) continue if opcode == convention.f32_sqrt: stack.add(Value.from_f32(math.sqrt(a))) continue continue if opcode >= convention.f32_add and opcode <= convention.f32_copysign: b = stack.pop().n a = stack.pop().n if opcode == convention.f32_add: stack.add(Value.from_f32(a + b)) continue if opcode == convention.f32_sub: stack.add(Value.from_f32(a - b)) continue if opcode == convention.f32_mul: stack.add(Value.from_f32(a * b)) continue if opcode == convention.f32_div: stack.add(Value.from_f32(a / b)) continue if opcode == convention.f32_min: stack.add(Value.from_f32(min(a, b))) continue if opcode == convention.f32_max: stack.add(Value.from_f32(max(a, b))) continue if opcode == convention.f32_copysign: stack.add(Value.from_f32(math.copysign(a, b))) continue continue if opcode >= convention.f64_abs and opcode <= convention.f64_sqrt: a = stack.pop().n if opcode == convention.f64_abs: stack.add(Value.from_f64(abs(a))) continue if opcode == convention.f64_neg: stack.add(Value.from_f64(-a)) continue if opcode == convention.f64_ceil: stack.add(Value.from_f64(math.ceil(a))) continue if opcode == convention.f64_floor: stack.add(Value.from_f64(math.floor(a))) continue if opcode == convention.f64_trunc: stack.add(Value.from_f64(math.trunc(a))) continue if opcode == convention.f64_nearest: ceil = math.ceil(a) if ceil - a >= 0.5: r = ceil else: r = ceil - 1 stack.add(Value.from_f64(r)) continue if opcode == convention.f64_sqrt: stack.add(Value.from_f64(math.sqrt(a))) continue continue if opcode >= convention.f64_add and opcode <= convention.f64_copysign: b = stack.pop().n a = stack.pop().n if opcode == convention.f64_add: stack.add(Value.from_f64(a + b)) continue if opcode == convention.f64_sub: stack.add(Value.from_f64(a - b)) continue if opcode == convention.f64_mul: stack.add(Value.from_f64(a * b)) continue if opcode == convention.f64_div: stack.add(Value.from_f64(a / b)) continue if opcode == convention.f64_min: stack.add(Value.from_f64(min(a, b))) continue if opcode == convention.f64_max: stack.add(Value.from_f64(max(a, b))) continue if opcode == convention.f64_copysign: stack.add(Value.from_f64(math.copysign(a, b))) continue continue if opcode >= convention.i32_wrap_i64 and opcode <= convention.f64_promote_f32: a = stack.pop().n if opcode in [ convention.i32_trunc_sf32, convention.i32_trunc_uf32, convention.i32_trunc_sf64, convention.i32_trunc_uf64, convention.i64_trunc_sf32, convention.i64_trunc_uf32, convention.i64_trunc_sf64, convention.i64_trunc_uf64, ]: if math.isnan(a): raise Exception('pywasm: invalid conversion to integer') if opcode == convention.i32_wrap_i64: stack.add(Value.from_i32(num.int2i32(a))) continue if opcode == convention.i32_trunc_sf32: if a > 2**31 - 1 or a < -2**32: raise Exception('pywasm: integer overflow') stack.add(Value.from_i32(int(a))) continue if opcode == convention.i32_trunc_uf32: if a > 2**32 - 1 or a < -1: raise Exception('pywasm: integer overflow') stack.add(Value.from_i32(int(a))) continue if opcode == convention.i32_trunc_sf64: if a > 2**31 - 1 or a < -2**32: raise Exception('pywasm: integer overflow') stack.add(Value.from_i32(int(a))) continue if opcode == convention.i32_trunc_uf64: if a > 2**32 - 1 or a < -1: raise Exception('pywasm: integer overflow') stack.add(Value.from_i32(int(a))) continue if opcode == convention.i64_extend_si32: stack.add(Value.from_i64(a)) continue if opcode == convention.i64_extend_ui32: stack.add(Value.from_i64(num.int2u32(a))) continue if opcode == convention.i64_trunc_sf32: if a > 2**63 - 1 or a < -2**63: raise Exception('pywasm: integer overflow') stack.add(Value.from_i64(int(a))) continue if opcode == convention.i64_trunc_uf32: if a > 2**63 - 1 or a < -1: raise Exception('pywasm: integer overflow') stack.add(Value.from_i64(int(a))) continue if opcode == convention.i64_trunc_sf64: stack.add(Value.from_i64(int(a))) continue if opcode == convention.i64_trunc_uf64: if a < -1: raise Exception('pywasm: integer overflow') stack.add(Value.from_i64(int(a))) continue if opcode == convention.f32_convert_si32: stack.add(Value.from_f32(a)) continue if opcode == convention.f32_convert_ui32: stack.add(Value.from_f32(num.int2u32(a))) continue if opcode == convention.f32_convert_si64: stack.add(Value.from_f32(a)) continue if opcode == convention.f32_convert_ui64: stack.add(Value.from_f32(num.int2u64(a))) continue if opcode == convention.f32_demote_f64: stack.add(Value.from_f32(a)) continue if opcode == convention.f64_convert_si32: stack.add(Value.from_f64(a)) continue if opcode == convention.f64_convert_ui32: stack.add(Value.from_f64(num.int2u32(a))) continue if opcode == convention.f64_convert_si64: stack.add(Value.from_f64(a)) continue if opcode == convention.f64_convert_ui64: stack.add(Value.from_f64(num.int2u64(a))) continue if opcode == convention.f64_promote_f32: stack.add(Value.from_f64(a)) continue continue if opcode >= convention.i32_reinterpret_f32 and opcode <= convention.f64_reinterpret_i64: a = stack.pop().n if opcode == convention.i32_reinterpret_f32: stack.add(Value.from_i32(num.f322i32(a))) continue if opcode == convention.i64_reinterpret_f64: stack.add(Value.from_i64(num.f642i64(a))) continue if opcode == convention.f32_reinterpret_i32: stack.add(Value.from_f32(num.i322f32(a))) continue if opcode == convention.f64_reinterpret_i64: stack.add(Value.from_f64(num.i642f64(a))) continue continue return stack.data[-frame.arity:]