This commit is contained in:
Chris Fallin 2022-11-28 22:08:08 -08:00
parent 539af66b88
commit 3bde79a15d
6 changed files with 43 additions and 7 deletions

2
.gitignore vendored
View file

@ -2,3 +2,5 @@
*~ *~
.*.swp .*.swp
Cargo.lock Cargo.lock
/*.wasm
wasm_tests/*.wasm

View file

@ -25,7 +25,7 @@ impl<'a> WasmBackend<'a> {
log::trace!("RPO:\n{:?}\n", rpo); log::trace!("RPO:\n{:?}\n", rpo);
let trees = Trees::compute(body); let trees = Trees::compute(body);
log::trace!("Trees:\n{:?}\n", trees); 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); log::trace!("Ctrl:\n{:?}\n", ctrl);
Ok(WasmBackend { Ok(WasmBackend {
body, body,

View file

@ -96,17 +96,17 @@ impl CtrlEntry {
} }
impl<'a, 'b> Context<'a, 'b> { 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<Self> {
let (merge_nodes, loop_headers) = let (merge_nodes, loop_headers) =
Self::compute_merge_nodes_and_loop_headers(body, cfg, rpo); Self::compute_merge_nodes_and_loop_headers(body, cfg, rpo)?;
Self { Ok(Self {
body, body,
cfg, cfg,
rpo, rpo,
merge_nodes, merge_nodes,
loop_headers, loop_headers,
ctrl_stack: vec![], ctrl_stack: vec![],
} })
} }
pub fn compute(mut self) -> Vec<WasmBlock<'a>> { pub fn compute(mut self) -> Vec<WasmBlock<'a>> {
@ -119,7 +119,7 @@ impl<'a, 'b> Context<'a, 'b> {
body: &FunctionBody, body: &FunctionBody,
cfg: &CFGInfo, cfg: &CFGInfo,
rpo: &RPO, rpo: &RPO,
) -> (HashSet<Block>, HashSet<Block>) { ) -> anyhow::Result<(HashSet<Block>, HashSet<Block>)> {
let mut loop_headers = HashSet::new(); let mut loop_headers = HashSet::new();
let mut branched_once = HashSet::new(); let mut branched_once = HashSet::new();
let mut merge_nodes = HashSet::new(); let mut merge_nodes = HashSet::new();
@ -128,6 +128,9 @@ impl<'a, 'b> Context<'a, 'b> {
for &succ in cfg.succs(block) { for &succ in cfg.succs(block) {
let succ_rpo = rpo.rev[succ].unwrap(); let succ_rpo = rpo.rev[succ].unwrap();
if succ_rpo <= block_rpo { if succ_rpo <= block_rpo {
if !cfg.dominates(succ, block) {
anyhow::bail!("Irreducible control flow: edge from {} to {}", block, succ);
}
// Backward branch. // Backward branch.
loop_headers.insert(succ); loop_headers.insert(succ);
} else { } 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<WasmBlock<'a>>) { fn handle_dom_subtree(&mut self, block: Block, into: &mut Vec<WasmBlock<'a>>) {

6
wasm_tests/test.wat Normal file
View file

@ -0,0 +1,6 @@
(module
(func (result i32)
i32.const 2
i32.const 2
i32.add
))

12
wasm_tests/test2.wat Normal file
View file

@ -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))

13
wasm_tests/test3.wat Normal file
View file

@ -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))))))