Skip to content

Commit

Permalink
Merge pull request #227 from 0xPolygonMiden/greenhat/restore-emu-in-i…
Browse files Browse the repository at this point in the history
…tests

[4/x] Restore running MASM in the emulator along the VM in integration tests
  • Loading branch information
greenhat authored Jul 11, 2024
2 parents 55691fa + b7d447e commit f059d61
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 42 deletions.
7 changes: 5 additions & 2 deletions codegen/masm/src/emulator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub struct Emulator {
step_over: Option<InstructionPointer>,
clk: usize,
clk_limit: usize,
entrypoint: Option<FunctionIdent>,
}
impl Default for Emulator {
fn default() -> Self {
Expand Down Expand Up @@ -170,6 +171,7 @@ impl Emulator {
step_over: None,
clk: 0,
clk_limit: usize::MAX,
entrypoint: None,
}
}

Expand Down Expand Up @@ -292,6 +294,7 @@ impl Emulator {
self.load_module(module)?;
cursor.move_next();
}
self.entrypoint = program.entrypoint;

// TODO: Load data segments

Expand Down Expand Up @@ -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 {
Expand Down
80 changes: 52 additions & 28 deletions tests/integration/src/compiler_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -93,14 +92,16 @@ pub struct CompilerTest {
pub source: CompilerTestSource,
/// The entrypoint function to use when building the IR
entrypoint: Option<FunctionIdent>,
/// The compiled IR
pub hir: Option<HirArtifact>,
/// The compiled MASM
pub masm_program: Option<Box<miden_core::Program>>,
/// The MASM source code
pub masm_src: Option<String>,
/// The extra MASM modules to link to the compiled MASM program
pub link_masm_modules: LinkMasmModules,
/// The compiled IR
hir: Option<HirArtifact>,
/// The MASM source code
masm_src: Option<String>,
/// The compiled IR MASM program
ir_masm_program: Option<Result<Arc<midenc_codegen_masm::Program>, String>>,
/// The compiled VM program
vm_masm_program: Option<Result<Arc<miden_core::Program>, String>>,
}

impl Default for CompilerTest {
Expand All @@ -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,
}
}
}
Expand Down Expand Up @@ -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<midenc_codegen_masm::Program> {
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<miden_core::Program> {
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<miden_core::Program> {
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()
}
Expand All @@ -588,9 +593,7 @@ impl CompilerTest {
}
}

pub(crate) fn compile_wasm_to_masm_program(
&self,
) -> (Result<miden_core::Program, Report>, 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) => {
Expand All @@ -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)));
}
}
}
Expand All @@ -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<Box<midenc_codegen_masm::Module>>,
entrypoint: Option<FunctionIdent>,
link_masm_modules: &LinkMasmModules,
) -> Result<Arc<midenc_codegen_masm::Program>, 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<midenc_codegen_masm::Module>],
entrypoint: Option<FunctionIdent>,
link_masm_modules: &LinkMasmModules,
) -> Result<Program, Report> {
) -> Result<Arc<miden_core::Program>, Report> {
let mut assembler = Assembler::default().with_library(&StdLibrary::default())?;
for (path, src) in link_masm_modules {
let options = miden_assembly::CompileOptions {
Expand All @@ -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!()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn test_get_inputs(test_name: &str, expected_inputs: Vec<Felt>) {
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, &[]);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/src/rust_masm_tests/apps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
10 changes: 6 additions & 4 deletions tests/integration/src/rust_masm_tests/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)) => {
Expand Down Expand Up @@ -60,15 +61,16 @@ 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()
.run(&($range), move |a| {
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)) => {
Expand Down
5 changes: 3 additions & 2 deletions tests/integration/src/rust_masm_tests/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)) => {
Expand Down
12 changes: 9 additions & 3 deletions tests/integration/src/rust_masm_tests/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,6 +19,7 @@ mod wit_sdk;
pub fn run_masm_vs_rust<T>(
rust_out: T,
vm_program: &miden_core::Program,
ir_program: Arc<midenc_codegen_masm::Program>,
args: &[Felt],
) -> Result<(), TestCaseError>
where
Expand All @@ -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(())
}

0 comments on commit f059d61

Please sign in to comment.