From 3bde79a15d3e0a9a59b348630f1da806470e4293 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Mon, 28 Nov 2022 22:08:08 -0800 Subject: [PATCH] WIP. --- .gitignore | 2 ++ src/backend/mod.rs | 2 +- src/backend/stackify.rs | 15 +++++++++------ wasm_tests/test.wat | 6 ++++++ wasm_tests/test2.wat | 12 ++++++++++++ wasm_tests/test3.wat | 13 +++++++++++++ 6 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 wasm_tests/test.wat create mode 100644 wasm_tests/test2.wat create mode 100644 wasm_tests/test3.wat diff --git a/.gitignore b/.gitignore index e15772d..38ada36 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *~ .*.swp Cargo.lock +/*.wasm +wasm_tests/*.wasm diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 059df29..0f61be6 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -25,7 +25,7 @@ impl<'a> WasmBackend<'a> { log::trace!("RPO:\n{:?}\n", rpo); let trees = Trees::compute(body); log::trace!("Trees:\n{:?}\n", trees); - let ctrl = StackifyContext::new(body, &cfg, &rpo).compute(); + let ctrl = StackifyContext::new(body, &cfg, &rpo)?.compute(); log::trace!("Ctrl:\n{:?}\n", ctrl); Ok(WasmBackend { body, diff --git a/src/backend/stackify.rs b/src/backend/stackify.rs index 067b0f6..2b5917d 100644 --- a/src/backend/stackify.rs +++ b/src/backend/stackify.rs @@ -96,17 +96,17 @@ impl CtrlEntry { } impl<'a, 'b> Context<'a, 'b> { - pub fn new(body: &'a FunctionBody, cfg: &'b CFGInfo, rpo: &'b RPO) -> Self { + pub fn new(body: &'a FunctionBody, cfg: &'b CFGInfo, rpo: &'b RPO) -> anyhow::Result { let (merge_nodes, loop_headers) = - Self::compute_merge_nodes_and_loop_headers(body, cfg, rpo); - Self { + Self::compute_merge_nodes_and_loop_headers(body, cfg, rpo)?; + Ok(Self { body, cfg, rpo, merge_nodes, loop_headers, ctrl_stack: vec![], - } + }) } pub fn compute(mut self) -> Vec> { @@ -119,7 +119,7 @@ impl<'a, 'b> Context<'a, 'b> { body: &FunctionBody, cfg: &CFGInfo, rpo: &RPO, - ) -> (HashSet, HashSet) { + ) -> anyhow::Result<(HashSet, HashSet)> { let mut loop_headers = HashSet::new(); let mut branched_once = HashSet::new(); let mut merge_nodes = HashSet::new(); @@ -128,6 +128,9 @@ impl<'a, 'b> Context<'a, 'b> { for &succ in cfg.succs(block) { let succ_rpo = rpo.rev[succ].unwrap(); if succ_rpo <= block_rpo { + if !cfg.dominates(succ, block) { + anyhow::bail!("Irreducible control flow: edge from {} to {}", block, succ); + } // Backward branch. loop_headers.insert(succ); } else { @@ -155,7 +158,7 @@ impl<'a, 'b> Context<'a, 'b> { } } - (merge_nodes, loop_headers) + Ok((merge_nodes, loop_headers)) } fn handle_dom_subtree(&mut self, block: Block, into: &mut Vec>) { diff --git a/wasm_tests/test.wat b/wasm_tests/test.wat new file mode 100644 index 0000000..445e7a9 --- /dev/null +++ b/wasm_tests/test.wat @@ -0,0 +1,6 @@ +(module + (func (result i32) + i32.const 2 + i32.const 2 + i32.add + )) diff --git a/wasm_tests/test2.wat b/wasm_tests/test2.wat new file mode 100644 index 0000000..68eecf6 --- /dev/null +++ b/wasm_tests/test2.wat @@ -0,0 +1,12 @@ +(module + (func (param i32) (result i32) + local.get 0 + if (result i32) + i32.const 1 + local.get 0 + i32.add + else + i32.const 2 + local.get 0 + i32.add + end)) diff --git a/wasm_tests/test3.wat b/wasm_tests/test3.wat new file mode 100644 index 0000000..bde69be --- /dev/null +++ b/wasm_tests/test3.wat @@ -0,0 +1,13 @@ +(module + (func (param i32) (result i32) + (local $i i32) + (local.set $i (local.get 0)) + + (local.get $i) + (block $loop-break (param i32) (result i32) + (loop $l (param i32) (result i32) + (if (i32.eq (local.get $i) (i32.const 100)) + (br $loop-break + (local.get $i))) + (local.set $i (i32.add (i32.const 10) (local.get $i))) + (br $l (local.get $i))))))