diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 8446bb3..f916814 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -13,6 +13,7 @@ cargo-fuzz = true libfuzzer-sys = "0.4" wasm-smith = "0.8" env_logger = "0.9" +log = "0.4" [dependencies.waffle] path = ".." diff --git a/fuzz/fuzz_targets/roundtrip.rs b/fuzz/fuzz_targets/roundtrip.rs index eec7311..f5e7ad9 100644 --- a/fuzz/fuzz_targets/roundtrip.rs +++ b/fuzz/fuzz_targets/roundtrip.rs @@ -5,6 +5,7 @@ use waffle::Module; fuzz_target!(|module: wasm_smith::Module| { let _ = env_logger::try_init(); + log::debug!("original module: {:?}", module); let orig_bytes = module.to_bytes(); let parsed_module = Module::from_wasm_bytes(&orig_bytes[..]).unwrap(); let _ = parsed_module.to_wasm_bytes(); diff --git a/src/backend.rs b/src/backend.rs index 97466df..677b909 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,6 +1,7 @@ //! IR-to-Wasm transform. use crate::{cfg::CFGInfo, ir::*}; +use log::debug; #[derive(Clone, Debug)] pub enum Shape { @@ -13,7 +14,7 @@ pub enum Shape { /// Index in RPO. type OrderedBlockId = usize; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Region { /// Forward-branch region. Extends from end (just prior to /// terminator) of first block to just before second block. Can be @@ -78,10 +79,14 @@ impl Region { } impl Shape { - pub fn compute(_f: &FunctionBody, cfg: &CFGInfo) -> Self { + pub fn compute(f: &FunctionBody, cfg: &CFGInfo) -> Self { // Process all non-contiguous edges in RPO block order. For // forward and backward edges, emit Regions. + debug!("f = {:?}", f); + debug!("cfg = {:?}", cfg); let order = cfg.rpo(); + debug!("rpo = {:?}", order); + assert_eq!(order[0], 0); // Entry block should come first. let mut regions = vec![]; for (block_pos, &block) in order.iter().enumerate() { @@ -102,6 +107,7 @@ impl Shape { // regions where necessary and duplicating where we find // irreducible control flow. regions.sort_by_key(|r| r.start()); + debug!("regions = {:?}", regions); // Examine each region in the sequence, determining whether it // is properly nested with respect to all overlapping regions. @@ -110,16 +116,23 @@ impl Shape { i += 1; let prev = regions[i - 1]; let this = regions[i]; + debug!("examining: {:?} -> {:?}", prev, this); if !prev.overlaps(&this) { + debug!(" -> no overlap"); continue; } match (prev, this) { + (a, b) if a == b => { + regions.remove(i); + i -= 1; + } (Region::Backward(a, b), Region::Backward(c, d)) if a == c => { // Merge by extending end. regions[i - 1] = Region::Backward(a, std::cmp::max(b, d)); regions.remove(i); + i -= 1; } (Region::Backward(a, b), Region::Backward(c, _d)) if a < c && c <= b => { panic!("Irreducible CFG"); @@ -137,6 +150,7 @@ impl Shape { // Merge. regions[i - 1] = Region::Forward(std::cmp::min(a, c), b); regions.remove(i); + i -= 1; } (Region::Forward(a, b), Region::Forward(c, d)) if a <= c && b < d => { regions[i - 1] = Region::Forward(a, d); @@ -146,6 +160,8 @@ impl Shape { } } + debug!("after stackifying: {:?}", regions); + // Ensure the regions properly nest. let mut stack: Vec = vec![]; for region in ®ions { @@ -167,6 +183,10 @@ impl Shape { } } + // TODO: make regions properly nest by doing replication right + // as we compute the RPO. Track the current nesting, and + // traverse more than once if needed. + Shape::None } }