opt in progress

This commit is contained in:
NikVolf
2017-04-25 18:29:51 +03:00
parent f0ef00292e
commit 4213d2a7bc

View File

@ -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<Symbol>) {
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<Symbol>) {
use Symbol::*;
@ -58,23 +77,55 @@ fn expand_symbols(module: &elements::Module, set: &mut HashSet<Symbol>) {
let mut fringe = set.iter().cloned().collect::<Vec<Symbol>>();
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)