functions and globals elimination

This commit is contained in:
NikVolf 2017-04-26 16:01:03 +03:00
parent 1051b60020
commit 7fd6ffabba
2 changed files with 89 additions and 20 deletions

2
opt/Cargo.lock generated
View File

@ -13,7 +13,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "parity-wasm" name = "parity-wasm"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/nikvolf/parity-wasm#825169d34ea6d9c3909fe762e36ccc3ba5ae98cf" source = "git+https://github.com/nikvolf/parity-wasm#c52ccb7cd3c54cb0dbf9495dec550b5848737dcb"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View File

@ -13,15 +13,11 @@ enum Symbol {
} }
fn resolve_function(module: &elements::Module, index: u32) -> Symbol { fn resolve_function(module: &elements::Module, index: u32) -> Symbol {
println!("Resolving function {}", index);
let mut functions = 0; let mut functions = 0;
let mut non_functions = 0;
for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() { for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
match item.external() { match item.external() {
&elements::External::Function(_) => { &elements::External::Function(_) => {
if functions == index { if functions == index {
println!("Import {}", item_index);
return Symbol::Import(item_index as usize); return Symbol::Import(item_index as usize);
} }
functions += 1; functions += 1;
@ -34,22 +30,20 @@ fn resolve_function(module: &elements::Module, index: u32) -> Symbol {
} }
fn resolve_global(module: &elements::Module, index: u32) -> Symbol { fn resolve_global(module: &elements::Module, index: u32) -> Symbol {
let imports_len = module let mut globals = 0;
.import_section() for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
.expect("Functions section to exist") match item.external() {
.entries() &elements::External::Global(_) => {
.iter() if globals == index {
.map(|e| match e.external() { return Symbol::Import(item_index as usize);
&elements::External::Global(_) => 1, }
_ => 0, globals += 1;
}) },
.sum(); _ => {}
}
if index < imports_len {
Symbol::Import(index as usize)
} else {
Symbol::Global(index as usize - imports_len as usize)
} }
Symbol::Global(index as usize - globals as usize)
} }
fn push_code_symbols(module: &elements::Module, opcodes: &[elements::Opcode], dest: &mut Vec<Symbol>) { fn push_code_symbols(module: &elements::Module, opcodes: &[elements::Opcode], dest: &mut Vec<Symbol>) {
@ -177,6 +171,42 @@ pub fn import_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut el
None None
} }
pub fn global_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::GlobalSection> {
for section in module.sections_mut() {
match section {
&mut elements::Section::Global(ref mut sect) => {
return Some(sect);
},
_ => { }
}
}
None
}
pub fn functions_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::FunctionsSection> {
for section in module.sections_mut() {
match section {
&mut elements::Section::Function(ref mut sect) => {
return Some(sect);
},
_ => { }
}
}
None
}
pub fn code_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elements::CodeSection> {
for section in module.sections_mut() {
match section {
&mut elements::Section::Code(ref mut sect) => {
return Some(sect);
},
_ => { }
}
}
None
}
fn main() { fn main() {
let args = env::args().collect::<Vec<_>>(); let args = env::args().collect::<Vec<_>>();
@ -242,6 +272,7 @@ fn main() {
} else { } else {
remove = true; remove = true;
eliminated_globals.push(top_globals); eliminated_globals.push(top_globals);
println!("Eliminated import({}) global({}, {})", old_index, top_globals, imports.entries()[index].field());
} }
top_globals += 1; top_globals += 1;
}, },
@ -259,6 +290,44 @@ fn main() {
} }
} }
// Senond, iterate through globals
{
let globals = global_section(&mut module).expect("Global section to exist");
index = 0;
old_index = 0;
loop {
if globals.entries_mut().len() == index { break; }
if stay.contains(&Symbol::Global(old_index)) {
index += 1;
} else {
globals.entries_mut().remove(index);
eliminated_globals.push(top_globals + old_index);
println!("Eliminated global({})", top_globals + old_index);
}
old_index += 1;
}
}
// Third, delete orphaned functions
index = 0;
old_index = 0;
loop {
if functions_section(&mut module).expect("Functons section to exist").entries_mut().len() == index { break; }
if stay.contains(&Symbol::Function(old_index)) {
index += 1;
} else {
functions_section(&mut module).expect("Functons section to exist").entries_mut().remove(index);
code_section(&mut module).expect("Functons section to exist").bodies_mut().remove(index);
eliminated_funcs.push(top_funcs + old_index);
println!("Eliminated function({})", top_funcs + old_index);
}
old_index += 1;
}
// Finally, delete all items one by one, updating reference indices in the process // Finally, delete all items one by one, updating reference indices in the process
// (todo: initial naive impementation can be optimized to avoid multiple passes) // (todo: initial naive impementation can be optimized to avoid multiple passes)