blob: b057e0c166208c23232687cfe6b95a6d2c4632f0 [file] [log] [blame] [edit]
(module
(type $struct (struct (mut i32)))
(type $extendedstruct (struct_subtype (mut i32) f64 $struct))
(type $bytes (array (mut i8)))
(type $void_func (func))
(type $int_func (func (result i32)))
(import "fuzzing-support" "log-i32" (func $log (param i32)))
(func "structs"
(local $x (ref null $struct))
(local $y (ref null $struct))
(local.set $x
(struct.new_default $struct)
)
;; The value is initialized to 0
;; Note: We cannot optimize these to constants without either immutability or
;; some kind of escape analysis (to verify that the GC data referred to is not
;; written to elsewhere).
(call $log
(struct.get $struct 0 (local.get $x))
)
;; Assigning a value works
(struct.set $struct 0
(local.get $x)
(i32.const 42)
)
(call $log
(struct.get $struct 0 (local.get $x))
)
;; References are references, so writing to one's value affects the other's
(local.set $y (local.get $x))
(struct.set $struct 0
(local.get $y)
(i32.const 100)
)
(call $log
(struct.get $struct 0 (local.get $x))
)
(call $log
(struct.get $struct 0 (local.get $y))
)
)
(func "arrays"
(local $x (ref null $bytes))
(local.set $x
(array.new $bytes
(i32.const 42) ;; value to splat into the array
(i32.const 50) ;; size
)
)
;; The length should be 50
(call $log
(array.len $bytes (local.get $x))
)
;; The value should be 42
(call $log
(array.get_u $bytes (local.get $x) (i32.const 10))
)
;; Write a value that will be truncated into an i8
(array.set $bytes (local.get $x) (i32.const 10) (i32.const 0xff80))
;; The value should be 0x80 (-128 or 128 depending on signed/unsigned)
(call $log
(array.get_u $bytes (local.get $x) (i32.const 10))
)
(call $log
(array.get_s $bytes (local.get $x) (i32.const 10))
)
;; Other items than the one at index 10 are unaffected.
(call $log
(array.get_s $bytes (local.get $x) (i32.const 20))
)
)
(func "br_on_cast"
(local $any anyref)
;; create a simple $struct, store it in an anyref
(local.set $any
(struct.new_default $struct)
)
(drop
(block $block (result ($ref $struct))
(drop
(block $extendedblock (result (ref $extendedstruct))
(drop
;; second, try to cast our simple $struct to what it is, which will work
(br_on_cast $block anyref (ref $struct)
;; first, try to cast our simple $struct to an extended, which will fail
(br_on_cast $extendedblock anyref (ref $extendedstruct)
(local.get $any)
)
)
)
(call $log (i32.const -1)) ;; we should never get here
(return)
)
)
(call $log (i32.const -2)) ;; we should never get here either
(return)
)
)
(call $log (i32.const 3)) ;; we should get here
)
(func "br_on_failed_cast-1"
(local $any anyref)
;; create a simple $struct, store it in an anyref
(local.set $any
(struct.new_default $struct)
)
(drop
(block $any (result (ref null any))
(call $log (i32.const 1))
(drop
;; try to cast our simple $struct to an extended, which will fail, and
;; so we will branch, skipping the next logging.
(br_on_cast_fail $any anyref (ref $extendedstruct)
(local.get $any)
)
)
(call $log (i32.const 999)) ;; we should skip this
(ref.null any)
)
)
)
(func "br_on_failed_cast-2"
(local $any anyref)
;; create an $extendedstruct, store it in an anyref
(local.set $any
(struct.new_default $extendedstruct)
)
(drop
(block $any (result (ref null any))
(call $log (i32.const 1))
(drop
;; try to cast our simple $struct to an extended, which will succeed, and
;; so we will continue to the next logging.
(br_on_cast_fail $any anyref (ref $extendedstruct)
(local.get $any)
)
)
(call $log (i32.const 999))
(ref.null any)
)
)
)
(func "cast-null-anyref-to-gc"
;; a null anyref is a literal which is not even of GC data, as it's not an
;; array or a struct, so our casting code should not assume it is. it is ok
;; to try to cast it, and the result should be 0.
(call $log
(ref.test $struct
(ref.null any)
)
)
)
(func $get_struct (result structref)
(struct.new_default $struct)
)
(func "br-on_non_null"
(drop
(block $non-null (result (ref any))
(br_on_non_null $non-null (i31.new (i32.const 0)))
;; $x refers to an i31, which is not null, so we will branch, and not
;; log
(call $log (i32.const 1))
(unreachable)
)
)
)
(func "br-on_non_null-2"
(drop
(block $non-null (result (ref any))
(br_on_non_null $non-null (ref.null any))
;; $x is null, and so we will not branch, and log and then trap
(call $log (i32.const 1))
(unreachable)
)
)
)
(func "ref-as-func-of-func"
(drop
(ref.cast func
(ref.func $0)
)
)
)
(func $a-void-func
(call $log (i32.const 1337))
)
(func "cast-on-func"
(call $log (i32.const 0))
;; a valid cast
(call_ref $void_func
(ref.cast $void_func (ref.func $a-void-func))
)
(call $log (i32.const 1))
;; an invalid cast
(drop (call_ref $int_func
(ref.cast $int_func (ref.func $a-void-func))
))
;; will never be reached
(call $log (i32.const 2))
)
(func "array-alloc-failure"
(drop
(array.new_default $bytes
(i32.const -1) ;; un-allocatable size (4GB * sizeof(Literal))
)
)
)
(func "init-array-packed" (result i32)
(local $x (ref null $bytes))
(local.set $x
(array.new $bytes
(i32.const -43) ;; initialize the i8 values with a negative i32
(i32.const 50)
)
)
;; read the value, which should be -43 & 255 ==> 213
(array.get_u $bytes
(local.get $x)
(i32.const 10)
)
)
(func $call-target (param $0 eqref)
(nop)
)
(func "array-copy"
(local $x (ref null $bytes))
(local $y (ref null $bytes))
;; Create an array of 10's, of size 100.
(local.set $x
(array.new $bytes
(i32.const 10)
(i32.const 100)
)
)
;; Create an array of zeros of size 200, and also set one index there.
(local.set $y
(array.new_default $bytes
(i32.const 200)
)
)
(array.set $bytes
(local.get $y)
(i32.const 42)
(i32.const 99)
)
;; Log out a value from $x before.
(call $log
(array.get_u $bytes (local.get $x) (i32.const 10))
)
(array.copy $bytes $bytes
(local.get $x)
(i32.const 10)
(local.get $y)
(i32.const 42)
(i32.const 2)
)
;; Log out some value from $x after. Indexes 10 and 11 should be modified.
(call $log
(array.get_u $bytes (local.get $x) (i32.const 9))
)
(call $log
(array.get_u $bytes (local.get $x) (i32.const 10))
)
(call $log
(array.get_u $bytes (local.get $x) (i32.const 11))
)
(call $log
(array.get_u $bytes (local.get $x) (i32.const 12))
)
)
(func "array.new_fixed"
(local $x (ref null $bytes))
(local.set $x
(array.new_fixed $bytes
(i32.const 42) ;; first value
(i32.const 50) ;; second value
)
)
;; The length should be 2
(call $log
(array.len $bytes (local.get $x))
)
;; The first value should be 42
(call $log
(array.get_u $bytes (local.get $x) (i32.const 0))
)
;; The second value should be 50
(call $log
(array.get_u $bytes (local.get $x) (i32.const 1))
)
)
(func "array.new_fixed-packed"
(local $x (ref null $bytes))
(local.set $x
(array.new_fixed $bytes
(i32.const -11512)
)
)
;; The value should be be -11512 & 255 => 8
(call $log
(array.get_u $bytes (local.get $x) (i32.const 0))
)
)
(func "static-casts"
;; Casting null returns null.
(call $log (ref.is_null
(ref.cast null $struct (ref.null $struct))
))
;; Testing null returns 0.
(call $log
(ref.test $struct (ref.null $struct))
)
;; Testing something completely wrong (struct vs array) returns 0.
(call $log
(ref.test $struct
(array.new $bytes
(i32.const 20)
(i32.const 10)
)
)
)
;; Testing a thing with the same type returns 1.
(call $log
(ref.test $struct
(struct.new_default $struct)
)
)
;; A bad downcast returns 0: we create a struct, which is not a extendedstruct.
(call $log
(ref.test $extendedstruct
(struct.new_default $struct)
)
)
;; Casting to a supertype works.
(call $log
(ref.test $struct
(struct.new_default $extendedstruct)
)
)
)
(func "static-br_on_cast"
(local $any anyref)
;; create a simple $struct, store it in an anyref
(local.set $any
(struct.new_default $struct)
)
(drop
(block $block (result ($ref $struct))
(drop
(block $extendedblock (result (ref $extendedstruct))
(drop
;; second, try to cast our simple $struct to what it is, which will work
(br_on_cast $block anyref (ref $struct)
;; first, try to cast our simple $struct to an extended, which will fail
(br_on_cast $extendedblock anyref (ref $extendedstruct)
(local.get $any)
)
)
)
(call $log (i32.const -1)) ;; we should never get here
(return)
)
)
(call $log (i32.const -2)) ;; we should never get here either
(return)
)
)
(call $log (i32.const 3)) ;; we should get here
)
(func "static-br_on_cast_fail"
(local $any anyref)
;; create a simple $struct, store it in an anyref
(local.set $any
(struct.new_default $struct)
)
(drop
(block $failblock (result anyref)
(drop
;; try to cast our simple $struct to an extended, which will fail
(br_on_cast_fail $failblock anyref (ref $extendedstruct)
(local.get $any)
)
)
(call $log (i32.const -1)) ;; we should never get here
(return)
)
)
(call $log (i32.const -2)) ;; we should get here.
(return)
)
)
(module
(type $[mut:i8] (array (mut i8)))
(func "foo" (result i32)
;; before opts this will trap on failing to allocate -1 >>> 0 bytes. after
;; opts the unused value is removed so there is no trap, and a value is
;; returned, which should not confuse the fuzzer.
(drop
(array.new_default $[mut:i8]
(i32.const -1)
)
)
(i32.const 0)
)
)