result return for optimizer, test correctness

This commit is contained in:
NikVolf
2017-05-09 12:54:16 +03:00
parent e839064802
commit 3255d4be75
3 changed files with 19 additions and 6 deletions

View File

@ -18,7 +18,7 @@ fn main() {
// Invoke optimizer // Invoke optimizer
// Contract is supposed to have only these functions as public api // Contract is supposed to have only these functions as public api
// All other symbols not usable by this list is optimized away // All other symbols not usable by this list is optimized away
wasm_utils::optimize(&mut module, vec!["_call"]); wasm_utils::optimize(&mut module, vec!["_call"]).expect("Optimizer to finish without errors");
parity_wasm::serialize_to_file(&args[2], module).unwrap(); parity_wasm::serialize_to_file(&args[2], module).unwrap();
} }

View File

@ -9,7 +9,7 @@ mod symbols;
mod logger; mod logger;
mod ext; mod ext;
pub use optimizer::optimize; pub use optimizer::{optimize, Error as OptimizerError};
pub use gas::inject_gas_counter; pub use gas::inject_gas_counter;
pub use logger::init_log; pub use logger::init_log;
pub use ext::externalize; pub use ext::externalize;

View File

@ -3,17 +3,24 @@ use parity_wasm::elements;
use symbols::{Symbol, expand_symbols, push_code_symbols, resolve_function}; use symbols::{Symbol, expand_symbols, push_code_symbols, resolve_function};
#[derive(Debug)]
pub enum Error {
/// Since optimizer starts with export entries, export
/// section is supposed to exist.
NoExportSection,
}
pub fn optimize( pub fn optimize(
module: &mut elements::Module, // Module to optimize module: &mut elements::Module, // Module to optimize
used_exports: Vec<&str>, // List of only exports that will be usable after optimization used_exports: Vec<&str>, // List of only exports that will be usable after optimization
) { ) -> Result<(), Error> {
// WebAssembly exports optimizer // WebAssembly exports optimizer
// Motivation: emscripten compiler backend compiles in many unused exports // Motivation: emscripten compiler backend compiles in many unused exports
// which in turn compile in unused imports and leaves unused functions // which in turn compile in unused imports and leaves unused functions
// Algo starts from the top, listing all items that should stay // Algo starts from the top, listing all items that should stay
let mut stay = HashSet::new(); let mut stay = HashSet::new();
for (index, entry) in module.export_section().expect("Export section to exist").entries().iter().enumerate() { for (index, entry) in module.export_section().ok_or(Error::NoExportSection)?.entries().iter().enumerate() {
if used_exports.iter().find(|e| **e == entry.field()).is_some() { if used_exports.iter().find(|e| **e == entry.field()).is_some() {
stay.insert(Symbol::Export(index)); stay.insert(Symbol::Export(index));
} }
@ -239,6 +246,7 @@ pub fn optimize(
} }
} }
Ok(())
} }
@ -355,11 +363,16 @@ mod tests {
use parity_wasm::builder; use parity_wasm::builder;
use super::*; use super::*;
/// @spec
/// Optimizer presumes that export section exists and contains
/// all symbols passed as a second parameter. Since empty module
/// obviously contains no export section, optimizer should return
/// error on it.
#[test] #[test]
fn empty() { fn empty() {
let mut module = builder::module().build(); let mut module = builder::module().build();
optimize(&mut module, vec!["_call"]); let result = optimize(&mut module, vec!["_call"]);
assert!(module.type_section().is_none()); assert!(result.is_err());
} }
} }