diff --git a/opt/src/main.rs b/opt/src/main.rs index c66cd9b..bef331f 100644 --- a/opt/src/main.rs +++ b/opt/src/main.rs @@ -4,7 +4,7 @@ use std::env; use std::collections::HashSet; use parity_wasm::elements; -#[derive(PartialEq, Eq, Hash, Copy, Clone)] +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] enum Symbol { Import(usize), Global(usize), @@ -50,6 +50,25 @@ fn resolve_global(module: &elements::Module, index: u32) -> Symbol { } } +fn push_code_symbols(module: &elements::Module, opcodes: &[elements::Opcode], dest: &mut Vec) { + use parity_wasm::elements::Opcode::*; + + for opcode in opcodes { + match opcode { + &Call(idx) | &CallIndirect(idx, _) => { + dest.push(resolve_function(module, idx)); + }, + &GetGlobal(idx) | &SetGlobal(idx) => { + dest.push(resolve_global(module, idx)) + }, + &If(_, ref block) | &Loop(_, ref block) | &Block(_, ref block) => { + push_code_symbols(module, block.elements(), dest); + }, + _ => { }, + } + } +} + fn expand_symbols(module: &elements::Module, set: &mut HashSet) { use Symbol::*; @@ -58,23 +77,55 @@ fn expand_symbols(module: &elements::Module, set: &mut HashSet) { let mut fringe = set.iter().cloned().collect::>(); loop { let next = match fringe.pop() { + Some(s) if stop.contains(&s) => { continue; } Some(s) => s, _ => { break; } }; - - if stop.contains(&next) { - continue; - } + println!("Processing symbol {:?}", next); match next { Export(idx) => { let entry = &module.export_section().expect("Export section to exist").entries()[idx]; match entry.internal() { - &elements::Internal::Function(func_idx) => { fringe.push(resolve_function(module, func_idx)); }, - &elements::Internal::Global(global_idx) => { fringe.push(resolve_global(module, global_idx)); }, + &elements::Internal::Function(func_idx) => { + let symbol = resolve_function(module, func_idx); + if !stop.contains(&symbol) { + fringe.push(symbol); + } + set.insert(symbol); + }, + &elements::Internal::Global(global_idx) => { + let symbol = resolve_global(module, global_idx); + if !stop.contains(&symbol) { + fringe.push(symbol); + } + set.insert(symbol); + }, _ => {} } }, + Function(idx) => { + let body = &module.code_section().expect("Code section to exist").bodies()[idx]; + let mut code_symbols = Vec::new(); + push_code_symbols(module, body.code().elements(), &mut code_symbols); + for symbol in code_symbols.drain(..) { + if !stop.contains(&symbol) { + fringe.push(symbol); + } + set.insert(symbol); + } + }, + Global(idx) => { + let entry = &module.global_section().expect("Global section to exist").entries()[idx]; + let mut code_symbols = Vec::new(); + push_code_symbols(module, entry.init_expr().code(), &mut code_symbols); + for symbol in code_symbols.drain(..) { + if !stop.contains(&symbol) { + fringe.push(symbol); + } + set.insert(symbol); + } + } _ => {} } @@ -112,6 +163,10 @@ fn main() { // that are already used by those which already there expand_symbols(&mut module, &mut stay); + for symbol in stay.iter() { + println!("symbol to stay: {:?}", symbol); + } + // Finally, delete all items one by one, updating reference indices in the process // (todo: initial naive impementation can be optimized to avoid multiple passes)