924 lines
20 KiB
Python
924 lines
20 KiB
Python
"""
|
|
stdlib: Standard types that are not wasm primitives
|
|
"""
|
|
from phasm.stdlib import alloc
|
|
from phasm.wasmgenerator import Generator, func_wrapper
|
|
from phasm.wasmgenerator import VarType_i32 as i32
|
|
from phasm.wasmgenerator import VarType_i64 as i64
|
|
|
|
|
|
@func_wrapper()
|
|
def __alloc_bytes__(g: Generator, length: i32) -> i32:
|
|
"""
|
|
Allocates room for a bytes instance, but does not write
|
|
anything to the allocated memory
|
|
"""
|
|
result = i32('result')
|
|
|
|
# Allocate the length of the byte string, as well
|
|
# as 4 bytes for a length header
|
|
g.local.get(length)
|
|
g.i32.const(4)
|
|
g.i32.add()
|
|
g.call(alloc.__alloc__)
|
|
|
|
# Store the address in a variable so we can use it up
|
|
# for writing the length header
|
|
g.local.tee(result)
|
|
g.local.get(length)
|
|
g.i32.store()
|
|
|
|
# Get the address back from the variable as return
|
|
g.local.get(result)
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __subscript_bytes__(g: Generator, adr: i32, ofs: i32) -> i32:
|
|
"""
|
|
Returns an index from a bytes value
|
|
|
|
If ofs is more than the length of the bytes, this
|
|
function returns 0, following the 'no undefined behaviour'
|
|
philosophy.
|
|
|
|
adr i32 The pointer for the allocated bytes
|
|
ofs i32 The offset within the allocated bytes
|
|
"""
|
|
g.local.get(ofs)
|
|
g.local.get(adr)
|
|
g.i32.load()
|
|
g.i32.ge_u()
|
|
|
|
with g.if_():
|
|
# The offset is outside the allocated bytes
|
|
g.unreachable(comment='Out of bounds')
|
|
|
|
# The offset is less than the length
|
|
|
|
g.local.get(adr)
|
|
g.i32.const(4) # Bytes header
|
|
g.i32.add()
|
|
g.local.get(ofs)
|
|
g.i32.add()
|
|
g.i32.load8_u()
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u32_ord_min__(g: Generator, x: i32, y: i32) -> i32:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i32.lt_u()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u64_ord_min__(g: Generator, x: i64, y: i64) -> i64:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i64.lt_u()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i64('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i32_ord_min__(g: Generator, x: i32, y: i32) -> i32:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i32.lt_s()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i64_ord_min__(g: Generator, x: i64, y: i64) -> i64:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i64.lt_s()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i64('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u32_ord_max__(g: Generator, x: i32, y: i32) -> i32:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i32.gt_u()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u64_ord_max__(g: Generator, x: i64, y: i64) -> i64:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i64.gt_u()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i64('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i32_ord_max__(g: Generator, x: i32, y: i32) -> i32:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i32.gt_s()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i64_ord_max__(g: Generator, x: i64, y: i64) -> i64:
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i64.gt_s()
|
|
|
|
with g.if_():
|
|
g.local.get(x)
|
|
g.return_()
|
|
|
|
g.local.get(y)
|
|
g.return_()
|
|
|
|
return i64('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i32_intnum_abs__(g: Generator, x: i32) -> i32:
|
|
# https://stackoverflow.com/a/14194764
|
|
y = i32('y')
|
|
# z = i32('z')
|
|
|
|
# y = x >> 31
|
|
g.local.get(x)
|
|
g.i32.const(31)
|
|
g.i32.shr_s() # Must be arithmetic shift
|
|
g.local.set(y)
|
|
|
|
# abs(x) = (x XOR y) - y
|
|
|
|
# (x XOR y)
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i32.xor()
|
|
|
|
# - y
|
|
g.local.get(y)
|
|
g.i32.sub()
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __i64_intnum_abs__(g: Generator, x: i64) -> i64:
|
|
# https://stackoverflow.com/a/14194764
|
|
y = i64('y')
|
|
# z = i64('z')
|
|
|
|
# y = x >> 31
|
|
g.local.get(x)
|
|
g.i64.const(31)
|
|
g.i64.shr_s() # Must be arithmetic shift
|
|
g.local.set(y)
|
|
|
|
# abs(x) = (x XOR y) - y
|
|
|
|
# (x XOR y)
|
|
g.local.get(x)
|
|
g.local.get(y)
|
|
g.i64.xor()
|
|
|
|
# - y
|
|
g.local.get(y)
|
|
g.i64.sub()
|
|
g.return_()
|
|
|
|
return i64('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u32_pow2__(g: Generator, x: i32) -> i32:
|
|
# 2^0 == 1
|
|
g.local.get(x)
|
|
g.i32.eqz()
|
|
with g.if_():
|
|
g.i32.const(1)
|
|
g.return_()
|
|
|
|
# 2 ^ x == 2 << (x - 1)
|
|
# (when x > 1)
|
|
g.i32.const(2)
|
|
g.local.get(x)
|
|
g.i32.const(1)
|
|
g.i32.sub()
|
|
g.i32.shl()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u8_rotl__(g: Generator, x: i32, r: i32) -> i32:
|
|
s = i32('s') # The shifted part we need to overlay
|
|
|
|
# Handle cases where we need to shift more than 8 bits
|
|
g.local.get(r)
|
|
g.i32.const(8)
|
|
g.i32.rem_u()
|
|
g.local.set(r)
|
|
|
|
# Now do the rotation
|
|
|
|
g.local.get(x)
|
|
|
|
# 0000 0000 1100 0011
|
|
|
|
g.local.get(r)
|
|
|
|
# 0000 0000 1100 0011, 3
|
|
|
|
g.i32.shl()
|
|
|
|
# 0000 0110 0001 1000
|
|
|
|
g.local.tee(s)
|
|
|
|
# 0000 0110 0001 1000
|
|
|
|
g.i32.const(255)
|
|
|
|
# 0000 0110 0001 1000, 0000 0000 1111 1111
|
|
|
|
g.i32.and_()
|
|
|
|
# 0000 0000 0001 1000
|
|
|
|
g.local.get(s)
|
|
|
|
# 0000 0000 0001 1000, 0000 0110 0001 1000
|
|
|
|
g.i32.const(65280)
|
|
|
|
# 0000 0000 0001 1000, 0000 0110 0001 1000, 1111 1111 0000 0000
|
|
|
|
g.i32.and_()
|
|
|
|
# 0000 0000 0001 1000, 0000 0110 0000 0000
|
|
|
|
g.i32.const(8)
|
|
|
|
# 0000 0000 0001 1000, 0000 0110 0000 0000, 8
|
|
|
|
g.i32.shr_u()
|
|
|
|
# 0000 0000 0001 1000, 0000 0000 0000 0110
|
|
|
|
g.i32.or_()
|
|
|
|
# 0000 0000 0001 110
|
|
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
@func_wrapper()
|
|
def __u8_rotr__(g: Generator, x: i32, r: i32) -> i32:
|
|
s = i32('s') # The shifted part we need to overlay
|
|
|
|
# Handle cases where we need to shift more than 8 bits
|
|
g.local.get(r)
|
|
g.i32.const(8)
|
|
g.i32.rem_u()
|
|
g.local.set(r)
|
|
|
|
# Now do the rotation
|
|
|
|
g.local.get(x)
|
|
|
|
# 0000 0000 1100 0011
|
|
|
|
g.local.get(r)
|
|
|
|
# 0000 0000 1100 0011, 3
|
|
|
|
g.i32.rotr()
|
|
|
|
# 0110 0000 0000 0000 0000 0000 0001 1000
|
|
|
|
g.local.tee(s)
|
|
|
|
# 0110 0000 0000 0000 0000 0000 0001 1000
|
|
|
|
g.i32.const(255)
|
|
|
|
# 0110 0000 0000 0000 0000 0000 0001 1000, 0000 0000 1111 1111
|
|
|
|
g.i32.and_()
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000
|
|
|
|
g.local.get(s)
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000, 0110 0000 0000 0000 0000 0000 0001 1000
|
|
|
|
g.i32.const(4278190080)
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000, 0110 0000 0000 0000 0000 0000 0001 1000, 1111 1111 0000 0000 0000 0000 0000 0000
|
|
|
|
g.i32.and_()
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000, 0110 0000 0000 0000 0000 0000 0000 0000
|
|
|
|
g.i32.const(24)
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000, 0110 0000 0000 0000 0000 0000 0000 0000, 24
|
|
|
|
g.i32.shr_u()
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0001 1000, 0000 0000 0000 0000 0000 0000 0110 0000
|
|
|
|
g.i32.or_()
|
|
|
|
# 0000 0000 0000 0000 0000 0000 0111 1000
|
|
|
|
g.return_()
|
|
|
|
return i32('return') # To satisfy mypy
|
|
|
|
## ###
|
|
## class Eq
|
|
|
|
def u8_eq_equals(g: Generator) -> None:
|
|
g.i32.eq()
|
|
|
|
def u32_eq_equals(g: Generator) -> None:
|
|
g.i32.eq()
|
|
|
|
def u64_eq_equals(g: Generator) -> None:
|
|
g.i64.eq()
|
|
|
|
def i8_eq_equals(g: Generator) -> None:
|
|
g.i32.eq()
|
|
|
|
def i32_eq_equals(g: Generator) -> None:
|
|
g.i32.eq()
|
|
|
|
def i64_eq_equals(g: Generator) -> None:
|
|
g.i64.eq()
|
|
|
|
def f32_eq_equals(g: Generator) -> None:
|
|
g.f32.eq()
|
|
|
|
def f64_eq_equals(g: Generator) -> None:
|
|
g.f64.eq()
|
|
|
|
def u8_eq_not_equals(g: Generator) -> None:
|
|
g.i32.ne()
|
|
|
|
def u32_eq_not_equals(g: Generator) -> None:
|
|
g.i32.ne()
|
|
|
|
def u64_eq_not_equals(g: Generator) -> None:
|
|
g.i64.ne()
|
|
|
|
def i8_eq_not_equals(g: Generator) -> None:
|
|
g.i32.ne()
|
|
|
|
def i32_eq_not_equals(g: Generator) -> None:
|
|
g.i32.ne()
|
|
|
|
def i64_eq_not_equals(g: Generator) -> None:
|
|
g.i64.ne()
|
|
|
|
def f32_eq_not_equals(g: Generator) -> None:
|
|
g.f32.ne()
|
|
|
|
def f64_eq_not_equals(g: Generator) -> None:
|
|
g.f64.ne()
|
|
|
|
## ###
|
|
## class Ord
|
|
|
|
def u8_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_ord_min__')
|
|
|
|
def u32_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_ord_min__')
|
|
|
|
def u64_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u64_ord_min__')
|
|
|
|
def i8_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i32_ord_min__')
|
|
|
|
def i32_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i32_ord_min__')
|
|
|
|
def i64_ord_min(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i64_ord_min__')
|
|
|
|
def f32_ord_min(g: Generator) -> None:
|
|
g.f32.min()
|
|
|
|
def f64_ord_min(g: Generator) -> None:
|
|
g.f64.min()
|
|
|
|
def u8_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_ord_max__')
|
|
|
|
def u32_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_ord_max__')
|
|
|
|
def u64_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u64_ord_max__')
|
|
|
|
def i8_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i32_ord_max__')
|
|
|
|
def i32_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i32_ord_max__')
|
|
|
|
def i64_ord_max(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i64_ord_max__')
|
|
|
|
def f32_ord_max(g: Generator) -> None:
|
|
g.f32.max()
|
|
|
|
def f64_ord_max(g: Generator) -> None:
|
|
g.f64.max()
|
|
|
|
|
|
def u8_ord_less_than(g: Generator) -> None:
|
|
g.i32.lt_u()
|
|
|
|
def u32_ord_less_than(g: Generator) -> None:
|
|
g.i32.lt_u()
|
|
|
|
def u64_ord_less_than(g: Generator) -> None:
|
|
g.i64.lt_u()
|
|
|
|
def i8_ord_less_than(g: Generator) -> None:
|
|
g.i32.lt_s()
|
|
|
|
def i32_ord_less_than(g: Generator) -> None:
|
|
g.i32.lt_s()
|
|
|
|
def i64_ord_less_than(g: Generator) -> None:
|
|
g.i64.lt_s()
|
|
|
|
def f32_ord_less_than(g: Generator) -> None:
|
|
g.f32.lt()
|
|
|
|
def f64_ord_less_than(g: Generator) -> None:
|
|
g.f64.lt()
|
|
|
|
def u8_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i32.le_u()
|
|
|
|
def u32_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i32.le_u()
|
|
|
|
def u64_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i64.le_u()
|
|
|
|
def i8_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i32.le_s()
|
|
|
|
def i32_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i32.le_s()
|
|
|
|
def i64_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.i64.le_s()
|
|
|
|
def f32_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.f32.le()
|
|
|
|
def f64_ord_less_than_or_equal(g: Generator) -> None:
|
|
g.f64.le()
|
|
|
|
def u8_ord_greater_than(g: Generator) -> None:
|
|
g.i32.gt_u()
|
|
|
|
def u32_ord_greater_than(g: Generator) -> None:
|
|
g.i32.gt_u()
|
|
|
|
def u64_ord_greater_than(g: Generator) -> None:
|
|
g.i64.gt_u()
|
|
|
|
def i8_ord_greater_than(g: Generator) -> None:
|
|
g.i32.gt_s()
|
|
|
|
def i32_ord_greater_than(g: Generator) -> None:
|
|
g.i32.gt_s()
|
|
|
|
def i64_ord_greater_than(g: Generator) -> None:
|
|
g.i64.gt_s()
|
|
|
|
def f32_ord_greater_than(g: Generator) -> None:
|
|
g.f32.gt()
|
|
|
|
def f64_ord_greater_than(g: Generator) -> None:
|
|
g.f64.gt()
|
|
|
|
def u8_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i32.ge_u()
|
|
|
|
def u32_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i32.ge_u()
|
|
|
|
def u64_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i64.ge_u()
|
|
|
|
def i8_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i32.ge_s()
|
|
|
|
def i32_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i32.ge_s()
|
|
|
|
def i64_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.i64.ge_s()
|
|
|
|
def f32_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.f32.ge()
|
|
|
|
def f64_ord_greater_than_or_equal(g: Generator) -> None:
|
|
g.f64.ge()
|
|
|
|
## ###
|
|
## class Bits
|
|
|
|
def u8_bits_logical_shift_left(g: Generator) -> None:
|
|
g.i32.shl()
|
|
g.i32.const(255)
|
|
g.i32.and_()
|
|
|
|
def u32_bits_logical_shift_left(g: Generator) -> None:
|
|
g.i32.shl()
|
|
|
|
def u64_bits_logical_shift_left(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shl()
|
|
|
|
def u8_bits_logical_shift_right(g: Generator) -> None:
|
|
g.i32.shr_u()
|
|
|
|
def u32_bits_logical_shift_right(g: Generator) -> None:
|
|
g.i32.shr_u()
|
|
|
|
def u64_bits_logical_shift_right(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shr_u()
|
|
|
|
def u8_bits_rotate_left(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u8_rotl__')
|
|
|
|
def u32_bits_rotate_left(g: Generator) -> None:
|
|
g.i32.rotl()
|
|
|
|
def u64_bits_rotate_left(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.rotl()
|
|
|
|
def u8_bits_rotate_right(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u8_rotr__')
|
|
|
|
def u32_bits_rotate_right(g: Generator) -> None:
|
|
g.i32.rotr()
|
|
|
|
def u64_bits_rotate_right(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.rotr()
|
|
|
|
def u8_bits_bitwise_and(g: Generator) -> None:
|
|
g.i32.and_()
|
|
|
|
def u32_bits_bitwise_and(g: Generator) -> None:
|
|
g.i32.and_()
|
|
|
|
def u64_bits_bitwise_and(g: Generator) -> None:
|
|
g.i64.and_()
|
|
|
|
def u8_bits_bitwise_or(g: Generator) -> None:
|
|
g.i32.or_()
|
|
|
|
def u32_bits_bitwise_or(g: Generator) -> None:
|
|
g.i32.or_()
|
|
|
|
def u64_bits_bitwise_or(g: Generator) -> None:
|
|
g.i64.or_()
|
|
|
|
def u8_bits_bitwise_xor(g: Generator) -> None:
|
|
g.i32.xor()
|
|
|
|
def u32_bits_bitwise_xor(g: Generator) -> None:
|
|
g.i32.xor()
|
|
|
|
def u64_bits_bitwise_xor(g: Generator) -> None:
|
|
g.i64.xor()
|
|
|
|
## ###
|
|
## class Fractional
|
|
|
|
def f32_fractional_ceil(g: Generator) -> None:
|
|
g.f32.ceil()
|
|
|
|
def f64_fractional_ceil(g: Generator) -> None:
|
|
g.f64.ceil()
|
|
|
|
def f32_fractional_floor(g: Generator) -> None:
|
|
g.f32.floor()
|
|
|
|
def f64_fractional_floor(g: Generator) -> None:
|
|
g.f64.floor()
|
|
|
|
def f32_fractional_trunc(g: Generator) -> None:
|
|
g.f32.trunc()
|
|
|
|
def f64_fractional_trunc(g: Generator) -> None:
|
|
g.f64.trunc()
|
|
|
|
def f32_fractional_nearest(g: Generator) -> None:
|
|
g.f32.nearest()
|
|
|
|
def f64_fractional_nearest(g: Generator) -> None:
|
|
g.f64.nearest()
|
|
|
|
def f32_fractional_div(g: Generator) -> None:
|
|
g.f32.div()
|
|
|
|
def f64_fractional_div(g: Generator) -> None:
|
|
g.f64.div()
|
|
|
|
## ###
|
|
## class Floating
|
|
|
|
def f32_floating_sqrt(g: Generator) -> None:
|
|
g.add_statement('f32.sqrt')
|
|
|
|
def f64_floating_sqrt(g: Generator) -> None:
|
|
g.add_statement('f64.sqrt')
|
|
|
|
## ###
|
|
## class Integral
|
|
|
|
def u32_integral_div(g: Generator) -> None:
|
|
g.add_statement('i32.div_u')
|
|
|
|
def u64_integral_div(g: Generator) -> None:
|
|
g.add_statement('i64.div_u')
|
|
|
|
def i32_integral_div(g: Generator) -> None:
|
|
g.add_statement('i32.div_s')
|
|
|
|
def i64_integral_div(g: Generator) -> None:
|
|
g.add_statement('i64.div_s')
|
|
|
|
def u32_integral_rem(g: Generator) -> None:
|
|
g.add_statement('i32.rem_u')
|
|
|
|
def u64_integral_rem(g: Generator) -> None:
|
|
g.add_statement('i64.rem_u')
|
|
|
|
def i32_integral_rem(g: Generator) -> None:
|
|
g.add_statement('i32.rem_s')
|
|
|
|
def i64_integral_rem(g: Generator) -> None:
|
|
g.add_statement('i64.rem_s')
|
|
|
|
## ###
|
|
## class NatNum
|
|
|
|
def u32_natnum_add(g: Generator) -> None:
|
|
g.add_statement('i32.add')
|
|
|
|
def u64_natnum_add(g: Generator) -> None:
|
|
g.add_statement('i64.add')
|
|
|
|
def i32_natnum_add(g: Generator) -> None:
|
|
g.add_statement('i32.add')
|
|
|
|
def i64_natnum_add(g: Generator) -> None:
|
|
g.add_statement('i64.add')
|
|
|
|
def f32_natnum_add(g: Generator) -> None:
|
|
g.add_statement('f32.add')
|
|
|
|
def f64_natnum_add(g: Generator) -> None:
|
|
g.add_statement('f64.add')
|
|
|
|
def u32_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('i32.sub')
|
|
|
|
def u64_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('i64.sub')
|
|
|
|
def i32_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('i32.sub')
|
|
|
|
def i64_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('i64.sub')
|
|
|
|
def f32_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('f32.sub')
|
|
|
|
def f64_natnum_sub(g: Generator) -> None:
|
|
g.add_statement('f64.sub')
|
|
|
|
def u32_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('i32.mul')
|
|
|
|
def u64_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('i64.mul')
|
|
|
|
def i32_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('i32.mul')
|
|
|
|
def i64_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('i64.mul')
|
|
|
|
def f32_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('f32.mul')
|
|
|
|
def f64_natnum_mul(g: Generator) -> None:
|
|
g.add_statement('f64.mul')
|
|
|
|
def u32_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.i32.shl()
|
|
|
|
def u64_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shl()
|
|
|
|
def i32_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.i32.shl()
|
|
|
|
def i64_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shl()
|
|
|
|
def f32_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_pow2__')
|
|
g.f32.convert_i32_u()
|
|
g.f32.mul()
|
|
|
|
def f64_natnum_arithmic_shift_left(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_pow2__')
|
|
g.f64.convert_i32_u()
|
|
g.f64.mul()
|
|
|
|
def u32_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.i32.shr_u()
|
|
|
|
def u64_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shr_u()
|
|
|
|
def i32_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.i32.shr_s()
|
|
|
|
def i64_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
g.i64.shr_s()
|
|
|
|
def f32_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_pow2__')
|
|
g.f32.convert_i32_u()
|
|
g.f32.div()
|
|
|
|
def f64_natnum_arithmic_shift_right(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__u32_pow2__')
|
|
g.f64.convert_i32_u()
|
|
g.f64.div()
|
|
|
|
## ###
|
|
## class IntNum
|
|
|
|
def i32_intnum_abs(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i32_intnum_abs__')
|
|
|
|
def i64_intnum_abs(g: Generator) -> None:
|
|
g.add_statement('call $stdlib.types.__i64_intnum_abs__')
|
|
|
|
def f32_intnum_abs(g: Generator) -> None:
|
|
g.f32.abs()
|
|
|
|
def f64_intnum_abs(g: Generator) -> None:
|
|
g.f64.abs()
|
|
|
|
def i32_intnum_neg(g: Generator) -> None:
|
|
g.i32.const(-1)
|
|
g.i32.mul()
|
|
|
|
def i64_intnum_neg(g: Generator) -> None:
|
|
g.i64.const(-1)
|
|
g.i64.mul()
|
|
|
|
def f32_intnum_neg(g: Generator) -> None:
|
|
g.f32.neg()
|
|
|
|
def f64_intnum_neg(g: Generator) -> None:
|
|
g.f64.neg()
|
|
|
|
## ###
|
|
## Class Sized
|
|
|
|
def bytes_sized_len(g: Generator) -> None:
|
|
# The length is stored in the first 4 bytes
|
|
g.i32.load()
|
|
|
|
## ###
|
|
## Extendable
|
|
|
|
def u8_u32_extend(g: Generator) -> None:
|
|
# No-op
|
|
# u8 is already stored as u32
|
|
pass
|
|
|
|
def u8_u64_extend(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
|
|
def u32_u64_extend(g: Generator) -> None:
|
|
g.i64.extend_i32_u()
|
|
|
|
def i8_i32_extend(g: Generator) -> None:
|
|
# No-op
|
|
# i8 is already stored as i32
|
|
pass
|
|
|
|
def i8_i64_extend(g: Generator) -> None:
|
|
g.i64.extend_i32_s()
|
|
|
|
def i32_i64_extend(g: Generator) -> None:
|
|
g.i64.extend_i32_s()
|
|
|
|
def u8_u32_wrap(g: Generator) -> None:
|
|
g.i32.const(0xFF)
|
|
g.i32.and_()
|
|
|
|
def u8_u64_wrap(g: Generator) -> None:
|
|
g.i32.wrap_i64()
|
|
g.i32.const(0xFF)
|
|
g.i32.and_()
|
|
|
|
def u32_u64_wrap(g: Generator) -> None:
|
|
g.i32.wrap_i64()
|
|
|
|
def i8_i32_wrap(g: Generator) -> None:
|
|
g.i32.const(0xFF)
|
|
g.i32.and_()
|
|
|
|
def i8_i64_wrap(g: Generator) -> None:
|
|
g.i32.wrap_i64()
|
|
|
|
def i32_i64_wrap(g: Generator) -> None:
|
|
g.i32.wrap_i64()
|
|
|
|
## ###
|
|
## Promotable
|
|
|
|
def f32_f64_promote(g: Generator) -> None:
|
|
g.f64.promote_f32()
|
|
|
|
def f32_f64_demote(g: Generator) -> None:
|
|
g.f32.demote_f64()
|