From e16434fb44b2be8a3ff61dd635693779a359fc0e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 19 Sep 2019 22:52:16 +0100 Subject: [PATCH 01/17] Introduce ModuleConfig trait --- libchisel/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libchisel/src/lib.rs b/libchisel/src/lib.rs index 631b957..1d25e35 100644 --- a/libchisel/src/lib.rs +++ b/libchisel/src/lib.rs @@ -1,5 +1,6 @@ pub use parity_wasm::elements::Module; +use std::collections::HashMap; use std::{error, fmt}; pub mod imports; @@ -71,6 +72,17 @@ pub trait ModulePreset { Self: std::marker::Sized; } +// TODO: move this to be part of ChiselModule and retire ModulePreset +pub trait ModuleConfig { + fn with_defaults() -> Result + where + Self: std::marker::Sized; + + fn with_config(config: &HashMap) -> Result + where + Self: std::marker::Sized; +} + impl From for ModuleError { fn from(error: String) -> Self { ModuleError::Custom(error) From fd17712184b98e6d7478d00f02f0dec164b99b5d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 19 Sep 2019 22:57:44 +0100 Subject: [PATCH 02/17] Implement ModuleConfig in checkstartfunc --- libchisel/src/checkstartfunc.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libchisel/src/checkstartfunc.rs b/libchisel/src/checkstartfunc.rs index 6634180..844a5ff 100644 --- a/libchisel/src/checkstartfunc.rs +++ b/libchisel/src/checkstartfunc.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::Module; -use super::{ChiselModule, ModuleError, ModuleKind, ModuleValidator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleValidator}; /// Struct on which ModuleValidator is implemented. pub struct CheckStartFunc { @@ -31,6 +33,23 @@ impl<'a> ChiselModule<'a> for CheckStartFunc { } } +impl ModuleConfig for CheckStartFunc { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + let require_start = if let Some(value) = config.get("require_start") { + value == "true" + } else { + false + }; + Ok(CheckStartFunc { + start_required: require_start, + }) + } +} + impl ModuleValidator for CheckStartFunc { fn validate(&self, module: &Module) -> Result { Ok(module.start_section().is_some() == self.start_required) From 7bc6b464c2966e76f63caa99d8baa77cd147ec26 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 19 Sep 2019 23:08:02 +0100 Subject: [PATCH 03/17] Implement ModuleConfig in remapimports --- libchisel/src/remapimports.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libchisel/src/remapimports.rs b/libchisel/src/remapimports.rs index 40697ef..de4228c 100644 --- a/libchisel/src/remapimports.rs +++ b/libchisel/src/remapimports.rs @@ -1,7 +1,10 @@ +use std::collections::HashMap; + use parity_wasm::elements::{ImportEntry, ImportSection, Module}; use super::{ - imports::ImportList, ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator, + imports::ImportList, ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, + ModuleTranslator, }; pub struct RemapImports<'a> { @@ -29,6 +32,20 @@ impl<'a> ChiselModule<'a> for RemapImports<'a> { } } +impl<'a> ModuleConfig for RemapImports<'a> { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + RemapImports::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl<'a> ModulePreset for RemapImports<'a> { fn with_preset(preset: &str) -> Result { let mut interface_set: Vec = Vec::new(); From ac018ad61e6434222ff7812de0c9b9311ab3378d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 20 Sep 2019 23:31:30 +0100 Subject: [PATCH 04/17] Implement ModuleConfig in deployer --- libchisel/src/deployer.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/deployer.rs b/libchisel/src/deployer.rs index 002fccb..74b03f7 100644 --- a/libchisel/src/deployer.rs +++ b/libchisel/src/deployer.rs @@ -1,7 +1,9 @@ +use std::collections::HashMap; + use parity_wasm::builder; use parity_wasm::elements::{CustomSection, Module}; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; /// Enum on which ModuleTranslator is implemented. pub enum Deployer { @@ -25,6 +27,20 @@ impl<'a> ChiselModule<'a> for Deployer { } } +impl ModuleConfig for Deployer { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + Deployer::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl ModulePreset for Deployer { fn with_preset(preset: &str) -> Result { match preset { From 43b0184dbbb4b97e9d9d9111f6e06bf0a1fa5cd8 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Sep 2019 17:26:16 +0100 Subject: [PATCH 05/17] Implement ModuleConfig in snip --- libchisel/src/snip.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libchisel/src/snip.rs b/libchisel/src/snip.rs index 341d1bd..0a3e110 100644 --- a/libchisel/src/snip.rs +++ b/libchisel/src/snip.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::Module; -use super::{ChiselModule, ModuleError, ModuleKind, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleTranslator}; #[derive(Clone)] pub struct Snip(wasm_snip::Options); @@ -32,6 +34,17 @@ impl<'a> ChiselModule<'a> for Snip { } } +impl ModuleConfig for Snip { + fn with_defaults() -> Result { + Ok(Snip::new()) + } + + fn with_config(_config: &HashMap) -> Result { + // FIXME: expose the options + Err(ModuleError::NotSupported) + } +} + impl From for ModuleError { fn from(error: failure::Error) -> Self { ModuleError::Custom(error.to_string()) From c33b58c065480e05b6cf71b6e2c3400557df94bf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Sep 2019 17:26:51 +0100 Subject: [PATCH 06/17] Implement ModuleConfig in repack --- libchisel/src/repack.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libchisel/src/repack.rs b/libchisel/src/repack.rs index f735c2a..6c4a08b 100644 --- a/libchisel/src/repack.rs +++ b/libchisel/src/repack.rs @@ -1,7 +1,9 @@ +use std::collections::HashMap; + use parity_wasm::builder; use parity_wasm::elements::Module; -use super::{ChiselModule, ModuleError, ModuleKind, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleTranslator}; pub struct Repack; @@ -27,6 +29,16 @@ impl<'a> ChiselModule<'a> for Repack { } } +impl ModuleConfig for Repack { + fn with_defaults() -> Result { + Ok(Repack::new()) + } + + fn with_config(_config: &HashMap) -> Result { + Err(ModuleError::NotSupported) + } +} + impl ModuleTranslator for Repack { fn translate_inplace(&self, _module: &mut Module) -> Result { Err(ModuleError::NotSupported) From 723e85044db22053374f56bc1513d446822ac1ee Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Sep 2019 19:17:21 +0100 Subject: [PATCH 07/17] Implement ModuleConfig in binaryenopt --- libchisel/src/binaryenopt.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/binaryenopt.rs b/libchisel/src/binaryenopt.rs index 7a8cc06..2fca6c7 100644 --- a/libchisel/src/binaryenopt.rs +++ b/libchisel/src/binaryenopt.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::Module; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; // FIXME: change level names pub enum BinaryenOptimiser { @@ -29,6 +31,20 @@ impl<'a> ChiselModule<'a> for BinaryenOptimiser { } } +impl ModuleConfig for BinaryenOptimiser { + fn with_defaults() -> Result { + Ok(BinaryenOptimiser::O2) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + BinaryenOptimiser::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl ModulePreset for BinaryenOptimiser { fn with_preset(preset: &str) -> Result { match preset { From c2134202f98a52494853f3312fa17489e00064e9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Sep 2019 19:51:44 +0100 Subject: [PATCH 08/17] Implement ModuleConfig in dropsection --- libchisel/src/dropsection.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/libchisel/src/dropsection.rs b/libchisel/src/dropsection.rs index feb69e3..d6c26f8 100644 --- a/libchisel/src/dropsection.rs +++ b/libchisel/src/dropsection.rs @@ -1,6 +1,9 @@ +use std::collections::HashMap; +use std::error::Error; + use parity_wasm::elements::{Module, Section}; -use super::{ChiselModule, ModuleError, ModuleKind, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleTranslator}; /// Enum on which ModuleTranslator is implemented. pub enum DropSection { @@ -29,6 +32,36 @@ impl<'a> ChiselModule<'a> for DropSection { } } +impl From for ModuleError { + fn from(error: std::num::ParseIntError) -> Self { + ModuleError::Custom(error.description().to_string()) + } +} + +impl ModuleConfig for DropSection { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some((key, val)) = config.iter().next() { + return match key.as_str() { + "names" => Ok(DropSection::NamesSection), + "custom_by_name" => Ok(DropSection::CustomSectionByName(val.clone())), + "custom_by_index" => { + Ok(DropSection::CustomSectionByIndex(str::parse::(val)?)) + } + "unknown_by_index" => Ok(DropSection::UnknownSectionByIndex(str::parse::( + val, + )?)), + _ => Err(ModuleError::NotSupported), + }; + } else { + Err(ModuleError::NotFound) + } + } +} + // TODO: consider upstreaming this fn custom_section_index_for(module: &Module, name: &str) -> Option { module.sections().iter().position(|e| match e { From b31a4365efb5d6ed9fa502cbdc5593cd5f29ec36 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Sep 2019 20:20:46 +0100 Subject: [PATCH 09/17] Implement ModuleConfig in remapstart --- libchisel/src/remapstart.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libchisel/src/remapstart.rs b/libchisel/src/remapstart.rs index 5e59b05..3665404 100644 --- a/libchisel/src/remapstart.rs +++ b/libchisel/src/remapstart.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::{ExportEntry, ExportSection, Internal, Module, Section}; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; pub struct RemapStart; @@ -30,6 +32,21 @@ impl<'a> ChiselModule<'a> for RemapStart { } } +impl ModuleConfig for RemapStart { + fn with_defaults() -> Result { + Ok(RemapStart {}) + } + + // FIXME: drop this, no need for preset here + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + RemapStart::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl ModuleTranslator for RemapStart { fn translate_inplace(&self, module: &mut Module) -> Result { Ok(remap_start(module)) From 537aba82aab3804cf4ea1e91a05e7e427654df56 Mon Sep 17 00:00:00 2001 From: Jake Lang Date: Wed, 25 Sep 2019 18:33:08 -0400 Subject: [PATCH 10/17] Alternate with_config impl for DropSection --- libchisel/src/dropsection.rs | 62 ++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/libchisel/src/dropsection.rs b/libchisel/src/dropsection.rs index d6c26f8..673ac43 100644 --- a/libchisel/src/dropsection.rs +++ b/libchisel/src/dropsection.rs @@ -6,6 +6,7 @@ use parity_wasm::elements::{Module, Section}; use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleTranslator}; /// Enum on which ModuleTranslator is implemented. +#[derive(Debug)] pub enum DropSection { NamesSection, /// Name of the custom section. @@ -44,20 +45,42 @@ impl ModuleConfig for DropSection { } fn with_config(config: &HashMap) -> Result { - if let Some((key, val)) = config.iter().next() { - return match key.as_str() { - "names" => Ok(DropSection::NamesSection), - "custom_by_name" => Ok(DropSection::CustomSectionByName(val.clone())), - "custom_by_index" => { - Ok(DropSection::CustomSectionByIndex(str::parse::(val)?)) + // Query all possible modes + let modes: [(&'static str, Option<&String>); 4] = [ + ("names", config.get("names".into())), + ("custom_by_name", config.get("custom_by_name".into())), + ("custom_by_index", config.get("custom_by_index".into())), + ("unknown_by_index", config.get("unknown_by_index".into())), + ]; + + // Filter out modes which were provided. + let mut matches: Vec<(&'static str, &String)> = modes + .iter() + .filter_map(|(k, v)| { + if let Some(v) = v { + Some((*k, *v)) + } else { + None } - "unknown_by_index" => Ok(DropSection::UnknownSectionByIndex(str::parse::( - val, - )?)), - _ => Err(ModuleError::NotSupported), - }; - } else { - Err(ModuleError::NotFound) + }) + .collect(); + + // Reject multiple modes + if matches.len() != 1 { + return Err(ModuleError::Custom( + "Only one mode allowed at a time".to_string(), + )); + } + + let (mode, val) = matches.pop().expect("Verified that one match is present"); + match mode { + "names" => Ok(DropSection::NamesSection), + "custom_by_name" => Ok(DropSection::CustomSectionByName(val.clone())), + "custom_by_index" => Ok(DropSection::CustomSectionByIndex(str::parse::(val)?)), + "unknown_by_index" => Ok(DropSection::UnknownSectionByIndex(str::parse::( + val, + )?)), + _ => panic!("Only one of the above was present in the array"), } } } @@ -291,4 +314,17 @@ mod tests { assert!(custom_section_index_for(&module, "name").is_none()); assert!(custom_section_index_for(&module1, "name").is_none()); } + + #[test] + fn with_config_multiple_modes() { + let mut conf = HashMap::new(); + conf.insert("names".to_string(), "".to_string()); + conf.insert("custom_by_name".to_string(), "name".to_string()); + + let module = DropSection::with_config(&conf); + assert_eq!( + module.unwrap_err(), + ModuleError::Custom("Only one mode allowed at a time".to_string()) + ); + } } From 09c53cde6d20ac9fc647a79c8534374847b19a0a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:00:39 +0000 Subject: [PATCH 11/17] Implement ModuleConfig in checkfloat --- libchisel/src/checkfloat.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libchisel/src/checkfloat.rs b/libchisel/src/checkfloat.rs index 6bfed57..26c57be 100644 --- a/libchisel/src/checkfloat.rs +++ b/libchisel/src/checkfloat.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::{Instruction, Module}; -use super::{ChiselModule, ModuleError, ModuleKind, ModuleValidator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModuleValidator}; /// Struct on which ModuleValidator is implemented. pub struct CheckFloat {} @@ -21,6 +23,16 @@ impl<'a> ChiselModule<'a> for CheckFloat { } } +impl ModuleConfig for CheckFloat { + fn with_defaults() -> Result { + Ok(CheckFloat {}) + } + + fn with_config(_config: &HashMap) -> Result { + Err(ModuleError::NotSupported) + } +} + impl CheckFloat { pub fn new() -> Self { CheckFloat {} From 3bc0100e6805ebc0528e61361a3b0a74b223dd4a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:23:16 +0000 Subject: [PATCH 12/17] Implement ModuleConfig in verifyimports --- libchisel/src/verifyimports.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/verifyimports.rs b/libchisel/src/verifyimports.rs index 8cb9857..7e3ba95 100644 --- a/libchisel/src/verifyimports.rs +++ b/libchisel/src/verifyimports.rs @@ -1,8 +1,10 @@ +use std::collections::HashMap; + use parity_wasm::elements::{External, FunctionType, ImportSection, Module, Type}; use super::{ imports::{ImportList, ImportType}, - ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleValidator, + ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleValidator, }; /// Enum representing the state of an import in a module. @@ -51,6 +53,20 @@ impl<'a> ChiselModule<'a> for VerifyImports<'a> { } } +impl<'a> ModuleConfig for VerifyImports<'a> { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + VerifyImports::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl<'a> ModulePreset for VerifyImports<'a> { fn with_preset(preset: &str) -> Result { let mut import_set = ImportList::new(); From dbfc81cee3ea4b643872eba1407639e7047e99fd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:24:07 +0000 Subject: [PATCH 13/17] Implement ModuleConfig in verifyexports --- libchisel/src/verifyexports.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/verifyexports.rs b/libchisel/src/verifyexports.rs index 3d42832..036da6a 100644 --- a/libchisel/src/verifyexports.rs +++ b/libchisel/src/verifyexports.rs @@ -1,8 +1,10 @@ +use std::collections::HashMap; + use parity_wasm::elements::{ ExportSection, External, FunctionSection, FunctionType, ImportSection, Internal, Module, Type, }; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleValidator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleValidator}; /// Enum representing a type of export and any extra data to check. pub enum ExportType<'a> { @@ -39,6 +41,20 @@ impl<'a> ChiselModule<'a> for VerifyExports<'a> { } } +impl<'a> ModuleConfig for VerifyExports<'a> { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + VerifyExports::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl<'a> ModulePreset for VerifyExports<'a> { fn with_preset(preset: &str) -> Result { match preset { From b945c6f99a764ad5e0a3c12452f7c45c0f0b45ba Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:25:22 +0000 Subject: [PATCH 14/17] Implement ModuleConfig in trimstartfunc --- libchisel/src/trimstartfunc.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/trimstartfunc.rs b/libchisel/src/trimstartfunc.rs index 21bbf4a..2d403f3 100644 --- a/libchisel/src/trimstartfunc.rs +++ b/libchisel/src/trimstartfunc.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::Module; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; pub struct TrimStartFunc; @@ -31,6 +33,20 @@ impl<'a> ChiselModule<'a> for TrimStartFunc { } } +impl ModuleConfig for TrimStartFunc { + fn with_defaults() -> Result { + Err(ModuleError::NotSupported) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + TrimStartFunc::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl ModulePreset for TrimStartFunc { fn with_preset(preset: &str) -> Result { match preset { From 32df740e7f462c0d08073443cf3b763255b3e126 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:27:03 +0000 Subject: [PATCH 15/17] Implement ModuleConfig in trimexports --- libchisel/src/trimexports.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libchisel/src/trimexports.rs b/libchisel/src/trimexports.rs index 91c7c79..4a46a95 100644 --- a/libchisel/src/trimexports.rs +++ b/libchisel/src/trimexports.rs @@ -1,6 +1,8 @@ +use std::collections::HashMap; + use parity_wasm::elements::{ExportEntry, ExportSection, Internal, Module}; -use super::{ChiselModule, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; +use super::{ChiselModule, ModuleConfig, ModuleError, ModuleKind, ModulePreset, ModuleTranslator}; /// Struct containing a list of valid exports. struct ExportWhitelist { @@ -105,6 +107,20 @@ impl TrimExports { } } +impl ModuleConfig for TrimExports { + fn with_defaults() -> Result { + Ok(TrimExports::new()) + } + + fn with_config(config: &HashMap) -> Result { + if let Some(preset) = config.get("preset") { + TrimExports::with_preset(preset) + } else { + Err(ModuleError::NotSupported) + } + } +} + impl ModulePreset for TrimExports { /// Takes a given preset string and constructs a context with the /// corresponding whitelist. From 7fbba654acfc285d201c5077c6fff4a57d097d70 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 00:44:02 +0000 Subject: [PATCH 16/17] Implement with_config for snip --- libchisel/src/snip.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libchisel/src/snip.rs b/libchisel/src/snip.rs index 0a3e110..6f11ab2 100644 --- a/libchisel/src/snip.rs +++ b/libchisel/src/snip.rs @@ -34,14 +34,28 @@ impl<'a> ChiselModule<'a> for Snip { } } +// TODO: consider making this a generic helper? +fn check_bool_option(config: &HashMap, option: &str, default: bool) -> bool { + if let Some(value) = config.get(option) { + value == "true" + } else { + default + } +} + impl ModuleConfig for Snip { fn with_defaults() -> Result { Ok(Snip::new()) } - fn with_config(_config: &HashMap) -> Result { - // FIXME: expose the options - Err(ModuleError::NotSupported) + fn with_config(config: &HashMap) -> Result { + let mut options = wasm_snip::Options::default(); + options.snip_rust_fmt_code = check_bool_option(&config, "snip_rust_fmt_code", true); + options.snip_rust_panicking_code = + check_bool_option(&config, "snip_rust_panicking_code", true); + options.skip_producers_section = + check_bool_option(&config, "skip_producers_section", true); + Ok(Snip { 0: options }) } } From dc2568c29fffc9949375296f52e8d9026b48ceb9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 29 Dec 2019 00:25:46 +0100 Subject: [PATCH 17/17] Try implementing ModuleConfig in cli/driver.rs --- chisel/src/driver.rs | 262 ++++++++----------------------------------- 1 file changed, 47 insertions(+), 215 deletions(-) diff --git a/chisel/src/driver.rs b/chisel/src/driver.rs index 1452adc..dcc6172 100644 --- a/chisel/src/driver.rs +++ b/chisel/src/driver.rs @@ -17,11 +17,11 @@ use libchisel::{ checkfloat::CheckFloat, checkstartfunc::CheckStartFunc, deployer::Deployer, dropsection::DropSection, remapimports::RemapImports, remapstart::RemapStart, repack::Repack, snip::Snip, trimexports::TrimExports, trimstartfunc::TrimStartFunc, - verifyexports::VerifyExports, verifyimports::VerifyImports, Module, ModulePreset, - ModuleTranslator, ModuleValidator, + verifyexports::VerifyExports, verifyimports::VerifyImports, ChiselModule, Module, ModuleConfig, + ModuleError, ModuleKind, ModuleTranslator, ModuleValidator, }; -use crate::config::{ChiselConfig, ModuleConfig}; +use crate::config::ChiselConfig; use crate::result::{ChiselResult, ModuleResult, RulesetResult}; /// State machine implementing the main chisel execution loop. Consumes ChiselConfig and returns @@ -215,225 +215,57 @@ impl ChiselDriver { pub fn execute_module( &mut self, name: String, - module: ModuleConfig, + module: crate::config::ModuleConfig, wasm: &mut Module, ) -> Result { - let result = match name.as_str() { - "checkfloat" => { - let checkfloat = CheckFloat::new(); - let module_result = checkfloat.validate(wasm); - ModuleResult::Validator(name, module_result) - } - "checkstartfunc" => { - if let Some(require_start) = module.options().get("require_start") { - let require_start = match require_start.as_str() { - "true" => true, - "false" => false, - _ => { - return Err(DriverError::InvalidField( - name, - "require_start".to_string(), - )); - } - }; - let checkstartfunc = CheckStartFunc::new(require_start); - let module_result = checkstartfunc.validate(wasm); - ModuleResult::Validator(name, module_result) - } else { - chisel_debug!(1, "checkstartfunc missing field 'require_start'"); - return Err(DriverError::MissingRequiredField( - name, - "require_start".to_string(), - )); - } - } - "deployer" => { - if let Some(preset) = module.options().get("preset") { - match Deployer::with_preset(preset.as_str()) { - Ok(deployer) => match deployer.translate(wasm) { - Ok(new_wasm) => { - let did_mutate = if let Some(new_wasm) = new_wasm { - *wasm = new_wasm; - true - } else { - false - }; - - ModuleResult::Translator(name, Ok(did_mutate)) - } - Err(e) => ModuleResult::Translator(name, Err(e)), - }, - Err(_) => { - chisel_debug!(1, "deployer given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); - } - } - } else { - chisel_debug!(1, "deployer missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); - } - } - "dropnames" => { - let dropsection = DropSection::NamesSection; - ModuleResult::Translator(name, dropsection.translate_inplace(wasm)) - } - "remapimports" => { - if let Some(preset) = module.options().get("preset") { - let remapimports = RemapImports::with_preset(preset.as_str()); - if let Ok(remapimports) = remapimports { - let module_result = remapimports.translate_inplace(wasm); - ModuleResult::Translator(name, module_result) - } else { - chisel_debug!(1, "remapimports given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); - } - } else { - chisel_debug!(1, "remapimports missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); - } - } - "remapstart" => { - // NOTE: preset "ewasm" maps to the default and only mode. Fixing - // later. - let remapstart = RemapStart::with_preset("ewasm").expect("Should not fail"); - let module_result = remapstart.translate_inplace(wasm); - ModuleResult::Translator(name, module_result) - } - "repack" => { - let repack = Repack::new(); - let module_result = repack.translate(wasm).expect("No failure cases"); - - let did_mutate = if let Some(new_wasm) = module_result { - *wasm = new_wasm; - true - } else { - false - }; - - ModuleResult::Translator(name, Ok(did_mutate)) - } - "snip" => { - let snip = Snip::new(); - let module_result = match snip.translate(wasm) { - Ok(result) => result, - Err(e) => { - return Err(DriverError::Internal( - "snip".to_string(), - "Chisel module failed".to_string(), - e.into(), - )) - } - }; - - let did_mutate = if let Some(new_wasm) = module_result { - *wasm = new_wasm; - true - } else { - false - }; - - ModuleResult::Translator(name, Ok(did_mutate)) - } - "trimexports" => { - if let Some(preset) = module.options().get("preset") { - let trimexports = TrimExports::with_preset(preset.as_str()); - if let Ok(trimexports) = trimexports { - let module_result = trimexports.translate_inplace(wasm); - ModuleResult::Translator(name, module_result) - } else { - chisel_debug!(1, "trimexports given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); - } - } else { - chisel_debug!(1, "remapimports missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); - } - } - "trimstartfunc" => { - // NOTE: preset "ewasm" maps to the default and only mode. Fixing - // later. - let trimstartfunc = TrimStartFunc::with_preset("ewasm").expect("Should not fail"); - let module_result = trimstartfunc.translate_inplace(wasm); - ModuleResult::Translator(name, module_result) - } - "verifyexports" => { - if let Some(preset) = module.options().get("preset") { - let verifyexports = VerifyExports::with_preset(preset.as_str()); - if let Ok(verifyexports) = verifyexports { - let module_result = verifyexports.validate(wasm); - ModuleResult::Validator(name, module_result) - } else { - chisel_debug!(1, "verifyexports given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); - } - } else { - chisel_debug!(1, "verifyexports missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); - } - } - "verifyimports" => { - if let Some(preset) = module.options().get("preset") { - let verifyimports = VerifyImports::with_preset(preset.as_str()); - if let Ok(verifyimports) = verifyimports { - let module_result = verifyimports.validate(&wasm); - ModuleResult::Validator(name, module_result) - } else { - chisel_debug!(1, "verifyimports given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); - } - } else { - chisel_debug!(1, "verifyimports missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); - } - } + let chisel_module: Result = match name.as_str() { + "checkfloat" => CheckFloat::with_defaults(), + "checkstartfunc" => CheckStartFunc::with_config(module.options()), + "deployer" => Deployer::with_config(module.options()), + "dropnames" => Ok(DropSection::NamesSection), + "remapimports" => RemapImports::with_config(module.options()), + "remapstart" => RemapStart::with_config(module.options()), + "repack" => Repack::with_defaults(), + "snip" => Snip::with_config(module.options()), + "trimexports" => TrimExports::with_config(module.options()), + "trimstartfunc" => TrimStartFunc::with_config(module.options()), + "verifyexports" => VerifyExports::with_config(module.options()), + "verifyimports" => VerifyImports::with_config(module.options()), #[cfg(feature = "binaryen")] - "binaryenopt" => { - if let Some(preset) = module.options().get("preset") { - let binaryenopt = BinaryenOptimiser::with_preset(preset.as_str()); - if let Ok(binaryenopt) = binaryenopt { - match binaryenopt.translate(wasm) { - Ok(new_wasm) => { - let did_mutate = if let Some(new_wasm) = new_wasm { - *wasm = new_wasm; - true - } else { - false - }; - - ModuleResult::Translator(name, Ok(did_mutate)) - } - Err(e) => ModuleResult::Translator(name, Err(e)), - } - } else { - chisel_debug!(1, "binaryenopt given invalid preset"); - return Err(DriverError::InvalidField(name, "preset".to_string())); + "binaryenopt" => BinaryenOptimiser::with_config(module.options()), + _ => { + return Err(DriverError::ModuleNotFound(name.clone())); + } + }; + if chisel_module.is_err() { + // FIXME + panic!() + } + let chisel_module = chisel_module.unwrap(); + let result = match chisel_module.kind() { + ModuleKind::Creator => unimplemented!(), + ModuleKind::Translator => { + let as_trait: &dyn ModuleTranslator = chisel_module.as_abstract(); + // FIXME: can also optimize with translate_inplace + match as_trait.translate(wasm) { + Ok(new_wasm) => { + let did_mutate = if let Some(new_wasm) = new_wasm { + *wasm = new_wasm; + true + } else { + false + }; + ModuleResult::Translator(name, Ok(did_mutate)) } - } else { - chisel_debug!(1, "binaryenopt missing field 'preset'"); - return Err(DriverError::MissingRequiredField( - name, - "preset".to_string(), - )); + Err(e) => ModuleResult::Translator(name, Err(e)), } } - _ => { - return Err(DriverError::ModuleNotFound(name.clone())); + ModuleKind::Validator => { + let as_trait: &dyn ModuleValidator = chisel_module.as_abstract(); + let result = as_trait.validate(wasm); + ModuleResult::Validator(name, result) } + _ => unimplemented!(), }; Ok(result) }