optimizer decompose

This commit is contained in:
NikVolf
2017-05-04 15:59:22 +03:00
parent d0d23ddd98
commit 518669e44c
6 changed files with 179 additions and 148 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
Cargo.lock
target

21
Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "wasm-utils"
version = "0.1.0"
authors = ["NikVolf <nikvolf@gmail.com>"]
[dependencies]
parity-wasm = { git="https://github.com/nikvolf/parity-wasm" }
[lib]
[[bin]]
name = "wasm-opt"
path = "opt/src/main.rs"
[[bin]]
name = "wasm-ext"
path = "ext/src/main.rs"
[[bin]]
name = "wasm-gas"
path = "gas/src/main.rs"

View File

@ -4,4 +4,5 @@ version = "0.1.0"
authors = ["NikVolf <nikvolf@gmail.com>"]
[dependencies]
parity-wasm = { git="https://github.com/nikvolf/parity-wasm" }
parity-wasm = { git="https://github.com/nikvolf/parity-wasm" }
wasm-utils = { path = "../" }

View File

@ -1,154 +1,10 @@
extern crate parity_wasm;
extern crate wasm_utils;
use std::env;
use std::collections::HashSet;
use parity_wasm::elements;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
enum Symbol {
Type(usize),
Import(usize),
Global(usize),
Function(usize),
Export(usize),
}
fn resolve_function(module: &elements::Module, index: u32) -> Symbol {
let mut functions = 0;
for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
match item.external() {
&elements::External::Function(_) => {
if functions == index {
return Symbol::Import(item_index as usize);
}
functions += 1;
},
_ => {}
}
}
Symbol::Function(index as usize - functions as usize)
}
fn resolve_global(module: &elements::Module, index: u32) -> Symbol {
let mut globals = 0;
for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
match item.external() {
&elements::External::Global(_) => {
if globals == index {
return Symbol::Import(item_index as usize);
}
globals += 1;
},
_ => {}
}
}
Symbol::Global(index as usize - globals as usize)
}
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) => {
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::*;
// symbols that were already processed
let mut stop: HashSet<Symbol> = HashSet::new();
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; }
};
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) => {
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);
},
_ => {}
}
},
Import(idx) => {
let entry = &module.import_section().expect("Import section to exist").entries()[idx];
match entry.external() {
&elements::External::Function(type_idx) => {
let type_symbol = Symbol::Type(type_idx as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_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);
}
let signature = &module.functions_section().expect("Functions section to exist").entries()[idx];
let type_symbol = Symbol::Type(signature.type_ref() as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_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);
}
}
_ => {}
}
stop.insert(next);
}
}
use wasm_utils::symbols::{Symbol, expand_symbols, push_code_symbols, resolve_function};
pub fn update_call_index(opcodes: &mut elements::Opcodes, eliminated_indices: &[usize]) {
use parity_wasm::elements::Opcode::*;
@ -260,7 +116,7 @@ pub fn type_section<'a>(module: &'a mut elements::Module) -> Option<&'a mut elem
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 3 {
if args.len() < 3 {
println!("Usage: {} input_file.wasm output_file.wasm", args[0]);
return;
}

3
src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
extern crate parity_wasm;
pub mod symbols;

148
src/symbols.rs Normal file
View File

@ -0,0 +1,148 @@
use parity_wasm::elements;
use std::collections::HashSet;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum Symbol {
Type(usize),
Import(usize),
Global(usize),
Function(usize),
Export(usize),
}
pub fn resolve_function(module: &elements::Module, index: u32) -> Symbol {
let mut functions = 0;
for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
match item.external() {
&elements::External::Function(_) => {
if functions == index {
return Symbol::Import(item_index as usize);
}
functions += 1;
},
_ => {}
}
}
Symbol::Function(index as usize - functions as usize)
}
pub fn resolve_global(module: &elements::Module, index: u32) -> Symbol {
let mut globals = 0;
for (item_index, item) in module.import_section().expect("Functions section to exist").entries().iter().enumerate() {
match item.external() {
&elements::External::Global(_) => {
if globals == index {
return Symbol::Import(item_index as usize);
}
globals += 1;
},
_ => {}
}
}
Symbol::Global(index as usize - globals as usize)
}
pub 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) => {
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);
},
_ => { },
}
}
}
pub fn expand_symbols(module: &elements::Module, set: &mut HashSet<Symbol>) {
use self::Symbol::*;
// symbols that were already processed
let mut stop: HashSet<Symbol> = HashSet::new();
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; }
};
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) => {
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);
},
_ => {}
}
},
Import(idx) => {
let entry = &module.import_section().expect("Import section to exist").entries()[idx];
match entry.external() {
&elements::External::Function(type_idx) => {
let type_symbol = Symbol::Type(type_idx as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_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);
}
let signature = &module.functions_section().expect("Functions section to exist").entries()[idx];
let type_symbol = Symbol::Type(signature.type_ref() as usize);
if !stop.contains(&type_symbol) {
fringe.push(type_symbol);
}
set.insert(type_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);
}
}
_ => {}
}
stop.insert(next);
}
}