Fix use of locals

This commit is contained in:
Jef
2018-12-18 12:12:17 +01:00
parent 53841cdb07
commit 74ffb8560c
3 changed files with 490 additions and 113 deletions

View File

@@ -159,6 +159,7 @@ fn large_function() {
assert_eq!(
{
let translated = translate_wat(code);
translated.disassemble();
let out: u32 = unsafe { translated.execute_func(0, (5, 4, 3, 2, 1, 0)) };
out
},
@@ -192,6 +193,7 @@ fn function_read_args_spill_to_stack() {
assert_eq!(
{
let translated = translate_wat(code);
translated.disassemble();
let out: u32 = unsafe {
translated.execute_func(0, (7u32, 6u32, 5u32, 4u32, 3u32, 2u32, 1u32, 0u32))
};
@@ -258,6 +260,140 @@ fn function_write_args_spill_to_stack() {
11
);
}
#[test]
fn block() {
let code = r#"
(module
(func (param i32) (param i32) (result i32)
(block (result i32)
get_local 0
)
)
)
"#;
assert_eq!(execute_wat(code, 10, 20), 10);
}
#[test]
fn br_block() {
let code = r#"
(module
(func (param i32) (param i32) (result i32)
get_local 1
(block (result i32)
get_local 0
get_local 0
br 0
unreachable
)
i32.add
)
)
"#;
assert_eq!(execute_wat(code, 5, 7), 12);
}
// Tests discarding values on the value stack, while
// carrying over the result using a conditional branch.
#[test]
fn brif_block() {
let code = r#"
(module
(func (param i32) (param i32) (result i32)
get_local 1
(block (result i32)
get_local 0
get_local 0
br_if 0
unreachable
)
i32.add
)
)
"#;
assert_eq!(execute_wat(code, 5, 7), 12);
}
#[test]
fn spec_loop() {
let code = r#"
(module
(func
(call $assert-return (call $as-binary-operand) (i32.const 12))
(call $assert-return (call $break-bare) (i32.const 19))
(call $assert-return (call $break-value) (i32.const 18))
(call $assert-return (call $break-repeated) (i32.const 18))
(call $assert-return (call $break-inner) (i32.const 0x7))
)
(func $dummy)
(func $as-binary-operand (result i32)
(i32.mul
(loop (result i32) (call $dummy) (i32.const 3))
(loop (result i32) (call $dummy) (i32.const 4))
)
)
(func $break-bare (result i32)
(block (loop (br 1) (br 0) (unreachable)))
(block (loop (br_if 1 (i32.const 1)) (unreachable)))
(i32.const 19)
)
(func $break-value (result i32)
(block (result i32)
(loop (result i32) (br 1 (i32.const 18)) (br 0) (i32.const 19))
)
)
(func $break-repeated (result i32)
(block (result i32)
(loop (result i32)
(br 1 (i32.const 18))
(br 1 (i32.const 19))
(drop (br_if 1 (i32.const 20) (i32.const 0)))
(drop (br_if 1 (i32.const 20) (i32.const 1)))
(br 1 (i32.const 21))
(i32.const 21)
)
)
)
(func $break-inner (result i32)
(local i32)
(set_local 0 (i32.const 0))
(set_local 0 (i32.add (get_local 0) (block (result i32) (loop (result i32) (block (result i32) (br 2 (i32.const 0x1)))))))
(set_local 0 (i32.add (get_local 0) (block (result i32) (loop (result i32) (loop (result i32) (br 2 (i32.const 0x2)))))))
(set_local 0 (i32.add (get_local 0) (block (result i32) (loop (result i32) (block (result i32) (loop (result i32) (br 1 (i32.const 0x4))))))))
(get_local 0)
)
(func $assert-return (param i32) (param i32)
(if (i32.eq (get_local 0) (get_local 1)) (then) (else (unreachable)))
)
)
"#;
let translated = translate_wat(code);
translated.disassemble();
unsafe { translated.execute_func::<(), ()>(0, ()) }
}
// Tests that br_if keeps values in the case if the branch
// hasn't been taken.
#[test]
fn brif_block_passthru() {
let code = r#"
(module
(func (param i32) (param i32) (result i32)
(block (result i32)
get_local 1
get_local 0
br_if 0
get_local 1
i32.add
)
)
)
"#;
assert_eq!(execute_wat(code, 0, 3), 6);
}
#[test]
fn literals() {
let code = r#"