diff --git a/Cargo.toml b/Cargo.toml index 544e857..95cc25f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,3 +32,7 @@ path = "pack/src/main.rs" [[bin]] name = "wasm-build" path = "build/src/main.rs" + +[[bin]] +name = "indeterminism-check" +path = "indeterminism_check/src/main.rs" diff --git a/non_determinism_checker/.gitignore b/indeterminism_check/.gitignore similarity index 100% rename from non_determinism_checker/.gitignore rename to indeterminism_check/.gitignore diff --git a/non_determinism_checker/Cargo.toml b/indeterminism_check/Cargo.toml similarity index 82% rename from non_determinism_checker/Cargo.toml rename to indeterminism_check/Cargo.toml index 20a8b9f..b85adfd 100644 --- a/non_determinism_checker/Cargo.toml +++ b/indeterminism_check/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "non_determinism_checker" +name = "indeterminism_check" version = "0.1.0" authors = ["NikVolf "] diff --git a/non_determinism_checker/src/main.rs b/indeterminism_check/src/main.rs similarity index 75% rename from non_determinism_checker/src/main.rs rename to indeterminism_check/src/main.rs index eee51bd..44eb125 100644 --- a/non_determinism_checker/src/main.rs +++ b/indeterminism_check/src/main.rs @@ -17,10 +17,10 @@ fn main() { // Loading module let module = parity_wasm::deserialize_file(&args[1]).expect("Module deserialization to succeed"); - if wasm_utils::have_non_determinism(module) { - println!("Yes"); + if wasm_utils::have_indeterminism(module) { + println!("Non-determinism found"); } else { - println!("No"); + println!("Non-determinism not found"); } } diff --git a/src/indeterminism_check.rs b/src/indeterminism_check.rs new file mode 100644 index 0000000..e041edf --- /dev/null +++ b/src/indeterminism_check.rs @@ -0,0 +1,152 @@ +use parity_wasm::{elements}; +use parity_wasm::elements::{ Section, Opcode }; +use parity_wasm::elements::Opcode::*; + +fn check_opcodes (opcodes: &[Opcode]) -> bool { + for opcode in opcodes { + match *opcode { + F32Abs | + F32Neg | + F32Ceil | + F32Floor | + F32Trunc | + F32Nearest | + F32Sqrt | + F32Add | + F32Sub | + F32Mul | + F32Div | + F32Min | + F32Max | + F32Copysign | + F64Abs | + F64Neg | + F64Ceil | + F64Floor | + F64Trunc | + F64Nearest | + F64Sqrt | + F64Add | + F64Sub | + F64Mul | + F64Div | + F64Min | + F64Max | + F64Copysign | + I32TruncSF32 | + I32TruncUF32 | + I32TruncSF64 | + I32TruncUF64 | + I64TruncSF32 | + I64TruncUF32 | + I64TruncSF64 | + I64TruncUF64 | + F32ConvertSI32 | + F32ConvertUI32 | + F32ConvertSI64 | + F32ConvertUI64 | + F32DemoteF64 | + F64ConvertSI32 | + F64ConvertUI32 | + F64ConvertSI64 | + F64ConvertUI64 | + F64PromoteF32 | + I32ReinterpretF32 | + I64ReinterpretF64 | + F32ReinterpretI32 | + F64ReinterpretI64 | + F32Eq | + F32Ne | + F32Lt | + F32Gt | + F32Le | + F32Ge | + F64Eq | + F64Ne | + F64Lt | + F64Gt | + F64Le | + F64Ge + => return true, + _ => continue + } + } + false +} + + + + +pub fn have_indeterminism(module: elements::Module) -> bool { + for section in module.sections() { + match *section { + Section::Code(ref cs) => { + for body in cs.bodies() { + if check_opcodes(body.code().elements()) { + return true; + } + } + }, + Section::Global(ref global) => { + for entry in global.entries() { + if check_opcodes(entry.init_expr().code()) { + return true; + } + } + }, + Section::Element(ref element) => { + for entry in element.entries() { + if check_opcodes(entry.offset().code()) { + return true; + } + } + } + _ => continue + } + } + false +} + +#[cfg(test)] +mod tests { + use parity_wasm::{builder, elements}; + use super::*; + + #[test] + fn indeterminism_found() { + let module = builder::module() + .function().signature().return_type().f32().build() + .body() + .with_opcodes(elements::Opcodes::new( + vec![ + elements::Opcode::F32Const(1), // unrelated to this test matter + elements::Opcode::F32Const(1), // unrelated to this test matter + elements::Opcode::F32Add, + elements::Opcode::End + ] + )) + .build() + .build() + .build(); + assert_eq!(true, have_indeterminism(module)); + } + + #[test] + fn indeterminism_not() { + let module = builder::module() + .function().signature().return_type().f32().build() + .body() + .with_opcodes(elements::Opcodes::new( + vec![ + elements::Opcode::I32Const(1), + elements::Opcode::I32Const(1), + elements::Opcode::I32Add, + elements::Opcode::End + ] + )) + .build() + .build() + .build(); + assert_eq!(false, have_indeterminism(module)); + } +} diff --git a/src/lib.rs b/src/lib.rs index af09f6c..57d8aaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,11 +11,11 @@ mod symbols; mod logger; mod ext; mod pack; -mod non_determinism_checker; +mod indeterminism_check; pub use optimizer::{optimize, Error as OptimizerError}; pub use gas::inject_gas_counter; pub use logger::init_log; pub use ext::externalize; pub use pack::pack_instance; -pub use non_determinism_checker::have_non_determinism; +pub use indeterminism_check::have_indeterminism; diff --git a/src/non_determinism_checker.rs b/src/non_determinism_checker.rs deleted file mode 100644 index 13777e4..0000000 --- a/src/non_determinism_checker.rs +++ /dev/null @@ -1,102 +0,0 @@ -use parity_wasm::{elements}; -use parity_wasm::elements::{ Section, Opcodes }; -use parity_wasm::elements::Opcode::*; - -fn check_opcodes (opcodes: &Opcodes) -> bool { - for opcode in opcodes.elements() { - match *opcode { - F32Abs | - F32Neg | - F32Ceil | - F32Floor | - F32Trunc | - F32Nearest | - F32Sqrt | - F32Add | - F32Sub | - F32Mul | - F32Div | - F32Min | - F32Max | - F32Copysign | - F64Abs | - F64Neg | - F64Ceil | - F64Floor | - F64Trunc | - F64Nearest | - F64Sqrt | - F64Add | - F64Sub | - F64Mul | - F64Div | - F64Min | - F64Max | - F64Copysign | - I32TruncSF32 | - I32TruncUF32 | - I32TruncSF64 | - I32TruncUF64 | - I64TruncSF32 | - I64TruncUF32 | - I64TruncSF64 | - I64TruncUF64 | - F32ConvertSI32 | - F32ConvertUI32 | - F32ConvertSI64 | - F32ConvertUI64 | - F32DemoteF64 | - F64ConvertSI32 | - F64ConvertUI32 | - F64ConvertSI64 | - F64ConvertUI64 | - F64PromoteF32 | - I32ReinterpretF32 | - I64ReinterpretF64 | - F32ReinterpretI32 | - F64ReinterpretI64 | - F32Eq | - F32Ne | - F32Lt | - F32Gt | - F32Le | - F32Ge | - F64Eq | - F64Ne | - F64Lt | - F64Gt | - F64Le | - F64Ge - => return true, - _ => continue - } - } - false -} - - -pub fn have_non_determinism(module: elements::Module) -> bool { - - for section in module.sections() { - match *section { - Section::Code(ref cs) => { - for body in cs.bodies() { - if check_opcodes(body.code()) { - return true; - } else { - continue - } - } - }, - _ => continue - } - } - false -} - -#[cfg(test)] -mod tests { - use parity_wasm::{builder, elements}; - use super::*; - -}