From b7d447e45469b4020ad2f67fd05de323602342b8 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 2 Jul 2024 13:14:55 +0300 Subject: [PATCH] test: restore running MASM on the emulator along the VM in integration tests --- codegen/masm/src/emulator/mod.rs | 7 +- tests/integration/src/compiler_test.rs | 80 ++++++++++++------- .../rust_masm_tests/abi_transform/stdlib.rs | 2 +- .../abi_transform/tx_kernel.rs | 2 +- tests/integration/src/rust_masm_tests/apps.rs | 2 +- .../src/rust_masm_tests/instructions.rs | 10 ++- .../src/rust_masm_tests/intrinsics.rs | 5 +- tests/integration/src/rust_masm_tests/mod.rs | 12 ++- 8 files changed, 78 insertions(+), 42 deletions(-) diff --git a/codegen/masm/src/emulator/mod.rs b/codegen/masm/src/emulator/mod.rs index bdca49524..46f983239 100644 --- a/codegen/masm/src/emulator/mod.rs +++ b/codegen/masm/src/emulator/mod.rs @@ -132,6 +132,7 @@ pub struct Emulator { step_over: Option, clk: usize, clk_limit: usize, + entrypoint: Option, } impl Default for Emulator { fn default() -> Self { @@ -170,6 +171,7 @@ impl Emulator { step_over: None, clk: 0, clk_limit: usize::MAX, + entrypoint: None, } } @@ -292,6 +294,7 @@ impl Emulator { self.load_module(module)?; cursor.move_next(); } + self.entrypoint = program.entrypoint; // TODO: Load data segments @@ -508,10 +511,10 @@ impl Emulator { Status::Faulted(ref err) => return Err(err.clone()), } - let main_fn = FunctionIdent { + let main_fn = self.entrypoint.unwrap_or_else(|| FunctionIdent { module: LibraryNamespace::EXEC_PATH.into(), function: ProcedureName::MAIN_PROC_NAME.into(), - }; + }); // Run to completion let stack = self.invoke(main_fn, &[]).map_err(|err| match err { diff --git a/tests/integration/src/compiler_test.rs b/tests/integration/src/compiler_test.rs index e2f6854dd..8947e96f8 100644 --- a/tests/integration/src/compiler_test.rs +++ b/tests/integration/src/compiler_test.rs @@ -11,7 +11,6 @@ use std::{ }; use miden_assembly::{ast::ModuleKind, diagnostics::Report, Assembler, LibraryPath}; -use miden_core::Program; use miden_diagnostics::SourceSpan; use miden_stdlib::StdLibrary; use midenc_frontend_wasm::{translate, WasmTranslationConfig}; @@ -93,14 +92,16 @@ pub struct CompilerTest { pub source: CompilerTestSource, /// The entrypoint function to use when building the IR entrypoint: Option, - /// The compiled IR - pub hir: Option, - /// The compiled MASM - pub masm_program: Option>, - /// The MASM source code - pub masm_src: Option, /// The extra MASM modules to link to the compiled MASM program pub link_masm_modules: LinkMasmModules, + /// The compiled IR + hir: Option, + /// The MASM source code + masm_src: Option, + /// The compiled IR MASM program + ir_masm_program: Option, String>>, + /// The compiled VM program + vm_masm_program: Option, String>>, } impl Default for CompilerTest { @@ -110,10 +111,11 @@ impl Default for CompilerTest { session: Arc::new(dummy_session()), source: CompilerTestSource::Rust(String::new()), entrypoint: None, + link_masm_modules: Vec::new(), hir: None, - masm_program: None, masm_src: None, - link_masm_modules: Vec::new(), + ir_masm_program: None, + vm_masm_program: None, } } } @@ -558,23 +560,26 @@ impl CompilerTest { expected_masm_file.assert_eq(&program); } + /// Get the compiled IR MASM program + pub fn ir_masm_program(&mut self) -> Arc { + if self.ir_masm_program.is_none() { + self.compile_wasm_to_masm_program(); + } + self.ir_masm_program.as_ref().unwrap().as_ref().unwrap().clone() + } + /// Get the compiled MASM as [`miden_core::Program`] - pub fn masm_program(&mut self) -> Box { - if self.masm_program.is_none() { - let (masm, src) = self.compile_wasm_to_masm_program(); - self.masm_src = Some(src); - let unwrapped = masm.unwrap_or_else(|e| panic!("Failed to assemble MASM: {:?}", e)); - self.masm_program = Some(unwrapped.into()); + pub fn vm_masm_program(&mut self) -> Arc { + if self.vm_masm_program.is_none() { + self.compile_wasm_to_masm_program(); } - self.masm_program.clone().unwrap() + self.vm_masm_program.as_ref().unwrap().as_ref().unwrap().clone() } /// Get the MASM source code pub fn masm_src(&mut self) -> String { if self.masm_src.is_none() { - let (masm, src) = self.compile_wasm_to_masm_program(); - self.masm_src = Some(src); - self.masm_program = masm.ok().map(Box::from); + self.compile_wasm_to_masm_program(); } self.masm_src.clone().unwrap() } @@ -588,9 +593,7 @@ impl CompilerTest { } } - pub(crate) fn compile_wasm_to_masm_program( - &self, - ) -> (Result, String) { + pub(crate) fn compile_wasm_to_masm_program(&mut self) { match midenc_compile::compile_to_memory(self.session.clone()).unwrap() { midenc_compile::Compiled::Program(_p) => todo!("Program compilation not yet supported"), midenc_compile::Compiled::Modules(modules) => { @@ -599,9 +602,13 @@ impl CompilerTest { self.entrypoint, &self.link_masm_modules, ); - let prog = - masm_prog_from_modules(&modules, self.entrypoint, &self.link_masm_modules); - (prog, src) + self.masm_src = Some(src); + let vm_prog = + vm_masm_prog_from_modules(&modules, self.entrypoint, &self.link_masm_modules); + self.vm_masm_program = Some(vm_prog.map_err(|e| format!("{:?}", e))); + let ir_prog = + ir_masm_prog_from_modules(modules, self.entrypoint, &self.link_masm_modules); + self.ir_masm_program = Some(ir_prog.map_err(|e| format!("{:?}", e))); } } } @@ -627,12 +634,29 @@ pub fn skip_rust_compilation(cargo_project_folder: &Path, artifact_name: &str) - skip_rust } +#[allow(clippy::vec_box)] +fn ir_masm_prog_from_modules( + modules: Vec>, + entrypoint: Option, + link_masm_modules: &LinkMasmModules, +) -> Result, Report> { + let mut p = midenc_codegen_masm::Program::empty(); + for (_path, _src) in link_masm_modules { + // TODO: implement linking of MASM source code + } + for module in modules.into_iter() { + p.insert(module); + } + p.entrypoint = entrypoint; + Ok(Box::new(p).freeze()) +} + // Assemble the VM MASM program from the compiled IR MASM modules -fn masm_prog_from_modules( +fn vm_masm_prog_from_modules( modules: &[Box], entrypoint: Option, link_masm_modules: &LinkMasmModules, -) -> Result { +) -> Result, Report> { let mut assembler = Assembler::default().with_library(&StdLibrary::default())?; for (path, src) in link_masm_modules { let options = miden_assembly::CompileOptions { @@ -657,7 +681,7 @@ fn masm_prog_from_modules( } if let Some(entrypoint) = entrypoint { let prog_source = masm_prog_source(entrypoint); - assembler.assemble_program(prog_source) + assembler.assemble_program(prog_source).map(Arc::new) } else { todo!() } diff --git a/tests/integration/src/rust_masm_tests/abi_transform/stdlib.rs b/tests/integration/src/rust_masm_tests/abi_transform/stdlib.rs index a23165343..34e5e0491 100644 --- a/tests/integration/src/rust_masm_tests/abi_transform/stdlib.rs +++ b/tests/integration/src/rust_masm_tests/abi_transform/stdlib.rs @@ -23,7 +23,7 @@ fn test_blake3_hash() { test.expect_wasm(expect_file![format!("../../../expected/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../../expected/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../../expected/{artifact_name}.masm")]); - let vm_program = test.masm_program(); + let vm_program = test.vm_masm_program(); // Run the Rust and compiled MASM code against a bunch of random inputs and compare the results let res = TestRunner::default().run(&any::<[u8; 64]>(), move |ibytes| { diff --git a/tests/integration/src/rust_masm_tests/abi_transform/tx_kernel.rs b/tests/integration/src/rust_masm_tests/abi_transform/tx_kernel.rs index bef992492..1f712f15b 100644 --- a/tests/integration/src/rust_masm_tests/abi_transform/tx_kernel.rs +++ b/tests/integration/src/rust_masm_tests/abi_transform/tx_kernel.rs @@ -48,7 +48,7 @@ fn test_get_inputs(test_name: &str, expected_inputs: Vec) { test.expect_ir(expect_file![format!("../../../expected/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../../expected/{artifact_name}.masm")]); - let _vm_program = test.masm_program(); + let _vm_program = test.vm_masm_program(); // let _vm_out = execute_vm(&vm_program, &[]); } diff --git a/tests/integration/src/rust_masm_tests/apps.rs b/tests/integration/src/rust_masm_tests/apps.rs index f05d755c2..653c8ea3a 100644 --- a/tests/integration/src/rust_masm_tests/apps.rs +++ b/tests/integration/src/rust_masm_tests/apps.rs @@ -13,7 +13,7 @@ fn fib() { test.expect_ir(expect_file!["../../expected/fib.hir"]); test.expect_masm(expect_file!["../../expected/fib.masm"]); // let ir_masm = test.ir_masm_program(); - let vm_program = &test.masm_program(); + let vm_program = &test.vm_masm_program(); // Run the Rust and compiled MASM code against a bunch of random inputs and compare the results TestRunner::default() diff --git a/tests/integration/src/rust_masm_tests/instructions.rs b/tests/integration/src/rust_masm_tests/instructions.rs index 1ca96d7cb..598990a33 100644 --- a/tests/integration/src/rust_masm_tests/instructions.rs +++ b/tests/integration/src/rust_masm_tests/instructions.rs @@ -22,7 +22,8 @@ macro_rules! test_bin_op { test.expect_wasm(expect_file![format!("../../expected/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../expected/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../expected/{artifact_name}.masm")]); - let vm_program = test.masm_program(); + let vm_program = test.vm_masm_program(); + let ir_program = test.ir_masm_program(); // Run the Rust and compiled MASM code against a bunch of random inputs and compare the results let res = TestRunner::default() @@ -31,7 +32,7 @@ macro_rules! test_bin_op { let rs_out = a $op b; dbg!(&rs_out); let args = [TestFelt::from(a).0, TestFelt::from(b).0]; - run_masm_vs_rust(rs_out, &vm_program, &args) + run_masm_vs_rust(rs_out, &vm_program, ir_program.clone(), &args) }); match res { Err(TestError::Fail(_, value)) => { @@ -60,7 +61,8 @@ macro_rules! test_unary_op { test.expect_wasm(expect_file![format!("../../expected/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../expected/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../expected/{artifact_name}.masm")]); - let vm_program = test.masm_program(); + let vm_program = test.vm_masm_program(); + let ir_program = test.ir_masm_program(); // Run the Rust and compiled MASM code against a bunch of random inputs and compare the results let res = TestRunner::default() @@ -68,7 +70,7 @@ macro_rules! test_unary_op { let rs_out = $op a; dbg!(&rs_out); let args = [TestFelt::from(a).0]; - run_masm_vs_rust(rs_out, &vm_program, &args) + run_masm_vs_rust(rs_out, &vm_program, ir_program.clone(), &args) }); match res { Err(TestError::Fail(_, value)) => { diff --git a/tests/integration/src/rust_masm_tests/intrinsics.rs b/tests/integration/src/rust_masm_tests/intrinsics.rs index 3d995b59f..0deb2a22a 100644 --- a/tests/integration/src/rust_masm_tests/intrinsics.rs +++ b/tests/integration/src/rust_masm_tests/intrinsics.rs @@ -25,7 +25,8 @@ macro_rules! test_bin_op { test.expect_wasm(expect_file![format!("../../expected/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../expected/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../expected/{artifact_name}.masm")]); - let vm_program = test.masm_program(); + let vm_program = test.vm_masm_program(); + let ir_program = test.ir_masm_program(); // Run the Rust and compiled MASM code against a bunch of random inputs and compare the results let res = TestRunner::default() @@ -36,7 +37,7 @@ macro_rules! test_bin_op { let rs_out = a_felt $op b_felt; dbg!(&rs_out); let args = [a.0, b.0]; - run_masm_vs_rust(rs_out, &vm_program, &args) + run_masm_vs_rust(rs_out, &vm_program, ir_program.clone(), &args) }); match res { Err(TestError::Fail(_, value)) => { diff --git a/tests/integration/src/rust_masm_tests/mod.rs b/tests/integration/src/rust_masm_tests/mod.rs index 286cc6537..eb1d29742 100644 --- a/tests/integration/src/rust_masm_tests/mod.rs +++ b/tests/integration/src/rust_masm_tests/mod.rs @@ -1,7 +1,12 @@ +#![allow(unused_imports)] +#![allow(unused_variables)] + +use std::sync::Arc; + use miden_core::Felt; use proptest::{prop_assert_eq, test_runner::TestCaseError}; -use crate::{execute_vm, felt_conversion::TestFelt}; +use crate::{execute_emulator, execute_vm, felt_conversion::TestFelt}; mod abi_transform; mod apps; @@ -14,6 +19,7 @@ mod wit_sdk; pub fn run_masm_vs_rust( rust_out: T, vm_program: &miden_core::Program, + ir_program: Arc, args: &[Felt], ) -> Result<(), TestCaseError> where @@ -22,8 +28,8 @@ where let vm_out: T = (*execute_vm(vm_program, args).first().unwrap()).into(); dbg!(&vm_out); prop_assert_eq!(rust_out.clone(), vm_out, "VM output mismatch"); - // TODO: eq for i64 and u64 fails with invalid operand stack size error - // let emul_out: T = execute_emulator(ir_masm.clone(), &args).first().unwrap().clone().into(); + // TODO: Uncomment after https://github.com/0xPolygonMiden/compiler/issues/228 is fixed + // let emul_out: T = (*execute_emulator(ir_program.clone(), args).first().unwrap()).into(); // prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); Ok(()) }