Added memory_grow spectest

This commit is contained in:
Syrus Akbary 2018-11-18 11:13:20 -08:00
parent f915f0ea43
commit d01a10d810
2 changed files with 318 additions and 5 deletions

View File

@ -79,7 +79,7 @@ This spectests are currently covered:
- linking.wast
- loop.wast ✅
- memory.wast ✅
- memory_grow.wast
- memory_grow.wast
- memory_redundancy.wast ✅
- memory_trap.wast
- names.wast ✅
@ -112,16 +112,18 @@ There are some cases that we decided to skip for now to fasten the time to relea
- `SKIP_MUTABLE_GLOBALS`: Right now the WASM parser can't validate a module with imported/exported mut globals. We decided to skip the tests until Cranelift and wasmparser can handle this (original spec proposal: https://github.com/WebAssembly/mutable-global). Spectests affected:
- `globals.wast`
- `SKIP_CALL_INDIRECT_TYPE_MISMATCH`: we implemented traps in a fast way. We haven't covered yet the type mismatch on `call_indirect`. Specs affected:
- `call_indirect.wast`
- `SKIP_CALL_UNDEFINED_ELEMENT`
Tables are imported into every spec module, even for modules that don't expect it. We need to figure out a way to prevent import of objects that are not explicitly imported into the module.
Tables are imported into every spec module, even for modules that don't expect it. We need to figure out a way to prevent import of objects that are not explicitly imported into the module.
Currently cranelift_wasm::ModuleEnvironment does not provide `declare_table_import`, etc. so there is no meaningful way of fixing this yet.
- `call_indirect.wast`
- `call_indirect.wast`
- `SKIP_SHARED_TABLE` [elem.wast]
Currently sharing tables between instances/modules does not work. Below are some of the reasons it is hard to achieve.
Currently sharing tables between instances/modules does not work. Below are some of the reasons it is hard to achieve.
- Rust naturally prevents such because of the possibility of race conditions
- ImportObject is just a wrapper, what we really care about is references to its content.
@ -129,6 +131,7 @@ Currently sharing tables between instances/modules does not work. Below are some
table[table_element_index] = func_addr
- Instance has its own created memories and tables and references to them must outlive Instance::new()
- Possible strategy
```rust
// ImportObject should be passed by ref
Instance::new<'a>(..., &ImportObject);
@ -141,8 +144,9 @@ Currently sharing tables between instances/modules does not work. Below are some
unsafe { transmute::<&ImportObject, &mut ImportObject>(import) }
}
```
- `elem.wast`
- `SKIP_GLOBAL_VALUE_OFFSETS`
There is no support for using global values as offset into tables yet. I believe this is an issue from cranelift side as well, so we will have to wait for it to be supported.
There is no support for using global values as offset into tables yet. I believe this is an issue from cranelift side as well, so we will have to wait for it to be supported.
- `elem.wast`

309
spectests/memory_grow.wast Normal file
View File

@ -0,0 +1,309 @@
(module
(memory 0)
(func (export "load_at_zero") (result i32) (i32.load (i32.const 0)))
(func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2)))
(func (export "load_at_page_size") (result i32) (i32.load (i32.const 0x10000)))
(func (export "store_at_page_size") (i32.store (i32.const 0x10000) (i32.const 3)))
(func (export "grow") (param $sz i32) (result i32) (memory.grow (get_local $sz)))
(func (export "size") (result i32) (memory.size))
)
(assert_return (invoke "size") (i32.const 0))
(assert_trap (invoke "store_at_zero") "out of bounds memory access")
(assert_trap (invoke "load_at_zero") "out of bounds memory access")
(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
(assert_return (invoke "size") (i32.const 1))
(assert_return (invoke "load_at_zero") (i32.const 0))
(assert_return (invoke "store_at_zero"))
(assert_return (invoke "load_at_zero") (i32.const 2))
(assert_trap (invoke "store_at_page_size") "out of bounds memory access")
(assert_trap (invoke "load_at_page_size") "out of bounds memory access")
(assert_return (invoke "grow" (i32.const 4)) (i32.const 1))
(assert_return (invoke "size") (i32.const 5))
(assert_return (invoke "load_at_zero") (i32.const 2))
(assert_return (invoke "store_at_zero"))
(assert_return (invoke "load_at_zero") (i32.const 2))
(assert_return (invoke "load_at_page_size") (i32.const 0))
(assert_return (invoke "store_at_page_size"))
(assert_return (invoke "load_at_page_size") (i32.const 3))
(module
(memory 0)
(func (export "grow") (param i32) (result i32) (memory.grow (get_local 0)))
)
(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 0)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 2)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 800)) (i32.const 3))
(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
(assert_return (invoke "grow" (i32.const 64736)) (i32.const -1))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 803))
(module
(memory 0 10)
(func (export "grow") (param i32) (result i32) (memory.grow (get_local 0)))
)
(assert_return (invoke "grow" (i32.const 0)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 1))
(assert_return (invoke "grow" (i32.const 2)) (i32.const 2))
(assert_return (invoke "grow" (i32.const 6)) (i32.const 4))
(assert_return (invoke "grow" (i32.const 0)) (i32.const 10))
(assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
;; Test that newly allocated memory (program start and memory.grow) is zeroed
(module
(memory 1)
(func (export "grow") (param i32) (result i32)
(memory.grow (get_local 0))
)
(func (export "check-memory-zero") (param i32 i32) (result i32)
(local i32)
(set_local 2 (i32.const 1))
(block
(loop
(set_local 2 (i32.load8_u (get_local 0)))
(br_if 1 (i32.ne (get_local 2) (i32.const 0)))
(br_if 1 (i32.ge_u (get_local 0) (get_local 1)))
(set_local 0 (i32.add (get_local 0) (i32.const 1)))
(br_if 0 (i32.le_u (get_local 0) (get_local 1)))
)
)
(get_local 2)
)
)
(assert_return (invoke "check-memory-zero" (i32.const 0) (i32.const 0xffff)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 1))
(assert_return (invoke "check-memory-zero" (i32.const 0x10000) (i32.const 0x1_ffff)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 2))
(assert_return (invoke "check-memory-zero" (i32.const 0x20000) (i32.const 0x2_ffff)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 3))
(assert_return (invoke "check-memory-zero" (i32.const 0x30000) (i32.const 0x3_ffff)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 4))
(assert_return (invoke "check-memory-zero" (i32.const 0x40000) (i32.const 0x4_ffff)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 1)) (i32.const 5))
(assert_return (invoke "check-memory-zero" (i32.const 0x50000) (i32.const 0x5_ffff)) (i32.const 0))
;; As the argument of control constructs and instructions
(module
(memory 1)
(func (export "as-br-value") (result i32)
(block (result i32) (br 0 (memory.grow (i32.const 0))))
)
(func (export "as-br_if-cond")
(block (br_if 0 (memory.grow (i32.const 0))))
)
(func (export "as-br_if-value") (result i32)
(block (result i32)
(drop (br_if 0 (memory.grow (i32.const 0)) (i32.const 1))) (i32.const 7)
)
)
(func (export "as-br_if-value-cond") (result i32)
(block (result i32)
(drop (br_if 0 (i32.const 6) (memory.grow (i32.const 0)))) (i32.const 7)
)
)
(func (export "as-br_table-index")
(block (br_table 0 0 0 (memory.grow (i32.const 0))))
)
(func (export "as-br_table-value") (result i32)
(block (result i32)
(br_table 0 0 0 (memory.grow (i32.const 0)) (i32.const 1)) (i32.const 7)
)
)
(func (export "as-br_table-value-index") (result i32)
(block (result i32)
(br_table 0 0 (i32.const 6) (memory.grow (i32.const 0))) (i32.const 7)
)
)
(func (export "as-return-value") (result i32)
(return (memory.grow (i32.const 0)))
)
(func (export "as-if-cond") (result i32)
(if (result i32) (memory.grow (i32.const 0))
(then (i32.const 0)) (else (i32.const 1))
)
)
(func (export "as-if-then") (result i32)
(if (result i32) (i32.const 1)
(then (memory.grow (i32.const 0))) (else (i32.const 0))
)
)
(func (export "as-if-else") (result i32)
(if (result i32) (i32.const 0)
(then (i32.const 0)) (else (memory.grow (i32.const 0)))
)
)
(func (export "as-select-first") (param i32 i32) (result i32)
(select (memory.grow (i32.const 0)) (get_local 0) (get_local 1))
)
(func (export "as-select-second") (param i32 i32) (result i32)
(select (get_local 0) (memory.grow (i32.const 0)) (get_local 1))
)
(func (export "as-select-cond") (result i32)
(select (i32.const 0) (i32.const 1) (memory.grow (i32.const 0)))
)
(func $f (param i32 i32 i32) (result i32) (i32.const -1))
(func (export "as-call-first") (result i32)
(call $f (memory.grow (i32.const 0)) (i32.const 2) (i32.const 3))
)
(func (export "as-call-mid") (result i32)
(call $f (i32.const 1) (memory.grow (i32.const 0)) (i32.const 3))
)
(func (export "as-call-last") (result i32)
(call $f (i32.const 1) (i32.const 2) (memory.grow (i32.const 0)))
)
(type $sig (func (param i32 i32 i32) (result i32)))
(table anyfunc (elem $f))
(func (export "as-call_indirect-first") (result i32)
(call_indirect (type $sig)
(memory.grow (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0)
)
)
(func (export "as-call_indirect-mid") (result i32)
(call_indirect (type $sig)
(i32.const 1) (memory.grow (i32.const 0)) (i32.const 3) (i32.const 0)
)
)
(func (export "as-call_indirect-last") (result i32)
(call_indirect (type $sig)
(i32.const 1) (i32.const 2) (memory.grow (i32.const 0)) (i32.const 0)
)
)
(func (export "as-call_indirect-index") (result i32)
(call_indirect (type $sig)
(i32.const 1) (i32.const 2) (i32.const 3) (memory.grow (i32.const 0))
)
)
(func (export "as-set_local-value") (local i32)
(set_local 0 (memory.grow (i32.const 0)))
)
(func (export "as-tee_local-value") (result i32) (local i32)
(tee_local 0 (memory.grow (i32.const 0)))
)
(global $g (mut i32) (i32.const 0))
(func (export "as-set_global-value") (local i32)
(set_global $g (memory.grow (i32.const 0)))
)
(func (export "as-load-address") (result i32)
(i32.load (memory.grow (i32.const 0)))
)
(func (export "as-loadN-address") (result i32)
(i32.load8_s (memory.grow (i32.const 0)))
)
(func (export "as-store-address")
(i32.store (memory.grow (i32.const 0)) (i32.const 7))
)
(func (export "as-store-value")
(i32.store (i32.const 2) (memory.grow (i32.const 0)))
)
(func (export "as-storeN-address")
(i32.store8 (memory.grow (i32.const 0)) (i32.const 7))
)
(func (export "as-storeN-value")
(i32.store16 (i32.const 2) (memory.grow (i32.const 0)))
)
(func (export "as-unary-operand") (result i32)
(i32.clz (memory.grow (i32.const 0)))
)
(func (export "as-binary-left") (result i32)
(i32.add (memory.grow (i32.const 0)) (i32.const 10))
)
(func (export "as-binary-right") (result i32)
(i32.sub (i32.const 10) (memory.grow (i32.const 0)))
)
(func (export "as-test-operand") (result i32)
(i32.eqz (memory.grow (i32.const 0)))
)
(func (export "as-compare-left") (result i32)
(i32.le_s (memory.grow (i32.const 0)) (i32.const 10))
)
(func (export "as-compare-right") (result i32)
(i32.ne (i32.const 10) (memory.grow (i32.const 0)))
)
(func (export "as-memory.grow-size") (result i32)
(memory.grow (memory.grow (i32.const 0)))
)
)
(assert_return (invoke "as-br-value") (i32.const 1))
(assert_return (invoke "as-br_if-cond"))
(assert_return (invoke "as-br_if-value") (i32.const 1))
(assert_return (invoke "as-br_if-value-cond") (i32.const 6))
(assert_return (invoke "as-br_table-index"))
(assert_return (invoke "as-br_table-value") (i32.const 1))
(assert_return (invoke "as-br_table-value-index") (i32.const 6))
(assert_return (invoke "as-return-value") (i32.const 1))
(assert_return (invoke "as-if-cond") (i32.const 0))
(assert_return (invoke "as-if-then") (i32.const 1))
(assert_return (invoke "as-if-else") (i32.const 1))
(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 1))
(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 1))
(assert_return (invoke "as-select-cond") (i32.const 0))
(assert_return (invoke "as-call-first") (i32.const -1))
(assert_return (invoke "as-call-mid") (i32.const -1))
(assert_return (invoke "as-call-last") (i32.const -1))
(assert_return (invoke "as-call_indirect-first") (i32.const -1))
(assert_return (invoke "as-call_indirect-mid") (i32.const -1))
(assert_return (invoke "as-call_indirect-last") (i32.const -1))
(assert_trap (invoke "as-call_indirect-index") "undefined element")
(assert_return (invoke "as-set_local-value"))
(assert_return (invoke "as-tee_local-value") (i32.const 1))
(assert_return (invoke "as-set_global-value"))
(assert_return (invoke "as-load-address") (i32.const 0))
(assert_return (invoke "as-loadN-address") (i32.const 0))
(assert_return (invoke "as-store-address"))
(assert_return (invoke "as-store-value"))
(assert_return (invoke "as-storeN-address"))
(assert_return (invoke "as-storeN-value"))
(assert_return (invoke "as-unary-operand") (i32.const 31))
(assert_return (invoke "as-binary-left") (i32.const 11))
(assert_return (invoke "as-binary-right") (i32.const 9))
(assert_return (invoke "as-test-operand") (i32.const 0))
(assert_return (invoke "as-compare-left") (i32.const 1))
(assert_return (invoke "as-compare-right") (i32.const 1))
(assert_return (invoke "as-memory.grow-size") (i32.const 1))