From ac49c5ac0005f1efe0c6c2d216c150e0e3bab8f6 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 19 Apr 2024 07:56:48 +0300 Subject: [PATCH 1/3] test: draft a layout for intrinsics semantic tests, implement Felt plus op test; --- hir/src/component/mod.rs | 4 + tests/integration/expected/felt_plus.hir | 21 + tests/integration/expected/felt_plus.masm | 669 ++++++++++++++++++ tests/integration/expected/felt_plus.wat | 14 + .../miden_sdk_account_test.hir | 2 +- tests/integration/src/cargo_proj/mod.rs | 2 +- tests/integration/src/compiler_test.rs | 119 +++- tests/integration/src/felt_conversion.rs | 6 +- .../src/rust_masm_tests/instructions.rs | 14 +- .../src/rust_masm_tests/intrinsics.rs | 37 + tests/integration/src/rust_masm_tests/mod.rs | 25 + .../src/rust_masm_tests/rust_sdk.rs | 8 +- 12 files changed, 885 insertions(+), 36 deletions(-) create mode 100644 tests/integration/expected/felt_plus.hir create mode 100644 tests/integration/expected/felt_plus.masm create mode 100644 tests/integration/expected/felt_plus.wat create mode 100644 tests/integration/src/rust_masm_tests/intrinsics.rs diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index 6f0a2bbeb..f4e2a7f17 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -148,6 +148,10 @@ impl Component { &self.modules } + pub fn to_modules(mut self) -> Vec<(Ident, Box)> { + self.modules.drain(..).collect() + } + /// Return a mutable reference to the module table for this program pub fn modules_mut(&mut self) -> &mut IndexMap> { &mut self.modules diff --git a/tests/integration/expected/felt_plus.hir b/tests/integration/expected/felt_plus.hir new file mode 100644 index 000000000..e82141108 --- /dev/null +++ b/tests/integration/expected/felt_plus.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #felt_plus + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (add.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/felt_plus.masm b/tests/integration/expected/felt_plus.masm new file mode 100644 index 000000000..d222d29b0 --- /dev/null +++ b/tests/integration/expected/felt_plus.masm @@ -0,0 +1,669 @@ +mod felt_plus + +export.entrypoint + swap.1 + add +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use felt_plus + +begin + exec.felt_plus::entrypoint +end diff --git a/tests/integration/expected/felt_plus.wat b/tests/integration/expected/felt_plus.wat new file mode 100644 index 000000000..7495619fb --- /dev/null +++ b/tests/integration/expected/felt_plus.wat @@ -0,0 +1,14 @@ +(module $felt_plus.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "add" (func $miden_prelude::intrinsics::felt::extern_add (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_add + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.hir b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.hir index 76dbf97c5..ca5b433e3 100644 --- a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.hir +++ b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.hir @@ -12,7 +12,7 @@ (lower ((digest 0x0000000000000000000000000000000000000000000000000000000000000000) (type (func (abi canon) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (result felt)))) (#miden:tx_kernel/tx #create_note) ;; Modules - (module #miden_sdk_account_test.wasm + (module #miden_sdk_account_test ;; Data Segments (data (mut) (offset 1048576) 0x7e2f73646b2f7072656c7564652f7372632f7374646c69622f63727970746f2f6861736865732e727300000000001000290000008a000000280000000000100029000000d000000028000000) diff --git a/tests/integration/src/cargo_proj/mod.rs b/tests/integration/src/cargo_proj/mod.rs index cd0dbff1d..0b8d66419 100644 --- a/tests/integration/src/cargo_proj/mod.rs +++ b/tests/integration/src/cargo_proj/mod.rs @@ -341,7 +341,7 @@ pub fn project(proj_folder_name: &str) -> ProjectBuilder { let temp_dir = &std::env::temp_dir(); let cargo_projects_root = temp_dir.join("miden_test_cargo_projects"); let cargo_proj_path = cargo_projects_root.join(proj_folder_name); - dbg!(&cargo_proj_path); + // dbg!(&cargo_proj_path); ProjectBuilder::new(cargo_proj_path) } diff --git a/tests/integration/src/compiler_test.rs b/tests/integration/src/compiler_test.rs index 381fdeb41..fb73a1382 100644 --- a/tests/integration/src/compiler_test.rs +++ b/tests/integration/src/compiler_test.rs @@ -25,6 +25,8 @@ use miden_hir::{ use miden_stdlib::StdLibrary; use midenc_session::{InputFile, Session}; +use crate::cargo_proj::project; + pub enum CompilerTestSource { Rust(String), RustCargo { @@ -32,7 +34,6 @@ pub enum CompilerTestSource { artifact_name: String, }, RustCargoLib { - cargo_project_folder_name: String, artifact_name: String, }, RustCargoComponent { @@ -47,10 +48,7 @@ impl CompilerTestSource { cargo_project_folder_name: _, artifact_name, } => artifact_name.clone(), - CompilerTestSource::RustCargoLib { - cargo_project_folder_name: _, - artifact_name, - } => artifact_name.clone(), + CompilerTestSource::RustCargoLib { artifact_name } => artifact_name.clone(), CompilerTestSource::RustCargoComponent { artifact_name } => artifact_name.clone(), _ => panic!("Not a Rust Cargo project"), } @@ -113,7 +111,6 @@ impl CompilerTest { config: WasmTranslationConfig, ) -> Self { let manifest_path = cargo_project_folder.join("Cargo.toml"); - // dbg!(&pwd); let mut cargo_build_cmd = Command::new("cargo"); let compiler_workspace_dir = get_workspace_dir(); // Enable Wasm bulk-memory proposal (uses Wasm `memory.copy` op instead of `memcpy` import) @@ -174,9 +171,12 @@ impl CompilerTest { } /// Set the Rust source code to compile a library Cargo project to Wasm module - pub fn rust_source_cargo_lib(cargo_project_folder: &str) -> Self { - let manifest_path = format!("../rust-apps-wasm/{}/Cargo.toml", cargo_project_folder); - // dbg!(&pwd); + pub fn rust_source_cargo_lib( + cargo_project_folder: PathBuf, + is_build_std: bool, + entry_func_name: Option, + ) -> Self { + let manifest_path = cargo_project_folder.join("Cargo.toml"); let mut cargo_build_cmd = Command::new("cargo"); let compiler_workspace_dir = get_workspace_dir(); // Enable Wasm bulk-memory proposal (uses Wasm `memory.copy` op instead of `memcpy` import) @@ -193,14 +193,16 @@ impl CompilerTest { .arg("--manifest-path") .arg(manifest_path) .arg("--release") - .arg("--target=wasm32-wasi") + .arg("--target=wasm32-wasi"); + if is_build_std { // compile std as part of crate graph compilation // https://doc.rust-lang.org/cargo/reference/unstable.html#build-std - .arg("-Z") + cargo_build_cmd.arg("-Z") .arg("build-std=std,core,alloc,panic_abort") .arg("-Z") // abort on panic without message formatting (core::fmt uses call_indirect) .arg("build-std-features=panic_immediate_abort"); + } let mut child = cargo_build_cmd .arg("--message-format=json-render-diagnostics") .stdout(Stdio::piped()) @@ -227,18 +229,23 @@ impl CompilerTest { let path_str = path.to_str().unwrap(); !path_str.contains("release/deps") }); - dbg!(&wasm_artifacts); + // dbg!(&wasm_artifacts); assert_eq!(wasm_artifacts.len(), 1, "Expected one Wasm artifact"); let wasm_comp_path = &wasm_artifacts.first().unwrap(); let artifact_name = wasm_comp_path.file_stem().unwrap().to_str().unwrap().to_string(); + // dbg!(&artifact_name); + let entrypoint = entry_func_name.map(|func_name| FunctionIdent { + module: Ident::new(Symbol::intern(artifact_name.clone()), SourceSpan::default()), + function: Ident::new(Symbol::intern(func_name.to_string()), SourceSpan::default()), + }); Self { - config: Default::default(), - session: default_session(), - source: CompilerTestSource::RustCargoLib { - cargo_project_folder_name: cargo_project_folder.to_string(), - artifact_name, + config: WasmTranslationConfig { + override_name: Some(artifact_name.to_string().into()), + ..Default::default() }, - entrypoint: None, + session: default_session(), + source: CompilerTestSource::RustCargoLib { artifact_name }, + entrypoint, wasm_bytes: fs::read(wasm_artifacts.first().unwrap()).unwrap(), hir: None, ir_masm: None, @@ -374,6 +381,70 @@ impl CompilerTest { } } + /// Set the Rust source code to compile with `miden-prelude` (stdlib + intrinsics) + pub fn rust_fn_body_with_prelude(name: &str, rust_source: &str) -> Self { + let cwd = std::env::current_dir().unwrap(); + let miden_prelude_path = + cwd.parent().unwrap().parent().unwrap().join("sdk").join("prelude"); + let miden_prelude_path_str = miden_prelude_path.to_str().unwrap(); + // dbg!(&miden_prelude_path); + let proj = project(&name) + .file( + "Cargo.toml", + format!( + r#" + [package] + name = "{name}" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + wee_alloc = {{ version = "0.4.5", default-features = false}} + miden-prelude = {{ path = "{miden_prelude_path_str}" }} + + [lib] + crate-type = ["cdylib"] + + [profile.release] + panic = "abort" + # optimize for size + opt-level = "z" + "# + ) + .as_str(), + ) + .file( + "src/lib.rs", + format!( + r#" + #![no_std] + #![no_main] + + #[panic_handler] + fn my_panic(_info: &core::panic::PanicInfo) -> ! {{ + loop {{}} + }} + + + #[global_allocator] + static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + + extern crate miden_prelude; + use miden_prelude::*; + + #[no_mangle] + pub extern "C" fn entrypoint{} + "#, + rust_source + ) + .as_str(), + ) + .build(); + let test = Self::rust_source_cargo_lib(proj.root(), false, Some("entrypoint".to_string())); + test + } + /// Compare the compiled Wasm against the expected output pub fn expect_wasm(&self, expected_wat_file: expect_test::ExpectFile) { let wasm_bytes = self.wasm_bytes.as_ref(); @@ -507,8 +578,16 @@ impl CompilerTest { let hir = self.hir.take().expect("IR is not compiled"); let ir_masm = match hir { HirArtifact::Program(hir_program) => compiler.compile(hir_program).unwrap(), - HirArtifact::Component(_hir_component) => { - todo!("Component to MASM compilation is not implemented yet") + HirArtifact::Component(hir_component) => { + let ir_module = hir_component.to_modules().drain(..).next().unwrap().1; + let mut builder = ProgramBuilder::new(&self.session.diagnostics) + .with_module(ir_module) + .unwrap(); + if let Some(entrypoint) = self.entrypoint.as_ref() { + builder = builder.with_entrypoint(entrypoint.clone()); + } + let hir_program = builder.link().expect("Failed to link IR program"); + compiler.compile(hir_program).unwrap() } HirArtifact::Module(_) => { todo!("Module to MASM compilation is not implemented yet") diff --git a/tests/integration/src/felt_conversion.rs b/tests/integration/src/felt_conversion.rs index bfbb17404..b7381cb70 100644 --- a/tests/integration/src/felt_conversion.rs +++ b/tests/integration/src/felt_conversion.rs @@ -1,7 +1,7 @@ -use miden_core::Felt; -use miden_core::StarkField; +use miden_core::{Felt, StarkField}; -/// Wrapper around `Felt` that implements `From` for a bunch of types that are want to support in tests +/// Wrapper around `Felt` that implements `From` for a bunch of types that are want to support in +/// tests #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct TestFelt(pub Felt); diff --git a/tests/integration/src/rust_masm_tests/instructions.rs b/tests/integration/src/rust_masm_tests/instructions.rs index a089ad3ef..3c4003c8c 100644 --- a/tests/integration/src/rust_masm_tests/instructions.rs +++ b/tests/integration/src/rust_masm_tests/instructions.rs @@ -1,5 +1,3 @@ -#![allow(unused)] - use std::sync::Arc; use expect_test::expect_file; @@ -36,7 +34,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(rs_out, &vm_program, ir_masm.clone(), &args) + run_masm_vs_rust(rs_out, &vm_program, ir_masm.clone(), &args) }); match res { Err(TestError::Fail(_, value)) => { @@ -74,7 +72,7 @@ macro_rules! test_unary_op { let rs_out = $op a; dbg!(&rs_out); let args = [TestFelt::from(a).0]; - run_masm(rs_out, &vm_program, ir_masm.clone(), &args) + run_masm_vs_rust(rs_out, &vm_program, ir_masm.clone(), &args) }); match res { Err(TestError::Fail(_, value)) => { @@ -127,8 +125,6 @@ macro_rules! test_func_two_arg { }); }; } - -/// Arguments are expected to be in the order they are passed to the entrypoint function fn run_masm( rust_out: T, vm_program: &miden_core::Program, @@ -139,11 +135,9 @@ where T: Clone + From + std::cmp::PartialEq + std::fmt::Debug, { let vm_out: T = execute_vm(&vm_program, &args).first().unwrap().clone().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(); - // prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); + let emul_out: T = execute_emulator(ir_masm.clone(), &args).first().unwrap().clone().into(); + prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); Ok(()) } diff --git a/tests/integration/src/rust_masm_tests/intrinsics.rs b/tests/integration/src/rust_masm_tests/intrinsics.rs new file mode 100644 index 000000000..d4d5629f9 --- /dev/null +++ b/tests/integration/src/rust_masm_tests/intrinsics.rs @@ -0,0 +1,37 @@ +use core::panic; + +use expect_test::expect_file; +use proptest::{ + arbitrary::any, + test_runner::{TestError, TestRunner}, +}; + +use crate::{felt_conversion::TestFelt, rust_masm_tests::run_masm_vs_rust, CompilerTest}; + +#[test] +fn test_felt_plus() { + let main_fn = format!("(a: Felt, b: Felt) -> Felt {{ a + b }}"); + let artifact_name = "felt_plus"; + let mut test = CompilerTest::rust_fn_body_with_prelude(&artifact_name, &main_fn); + // Test expected compilation artifacts + 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 ir_masm = test.ir_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 + // TODO: generate proper felt values, i.e. in the range [0, M) + let res = TestRunner::default().run(&(any::(), any::()), move |(a, b)| { + let rust_out = a.wrapping_add(b); + let args = [TestFelt::from(a).0, TestFelt::from(b).0]; + run_masm_vs_rust(rust_out, &vm_program, ir_masm.clone(), &args) + }); + match res { + Err(TestError::Fail(_, value)) => { + panic!("Found minimal(shrinked) failing case: {:?}", value); + } + Ok(_) => (), + _ => panic!("Unexpected test result: {:?}", res), + } +} diff --git a/tests/integration/src/rust_masm_tests/mod.rs b/tests/integration/src/rust_masm_tests/mod.rs index d57893bf2..c6a0f98d5 100644 --- a/tests/integration/src/rust_masm_tests/mod.rs +++ b/tests/integration/src/rust_masm_tests/mod.rs @@ -1,5 +1,30 @@ +use std::sync::Arc; + +use miden_core::Felt; +use proptest::{prop_assert_eq, test_runner::TestCaseError}; + +use crate::{execute_emulator, execute_vm, felt_conversion::TestFelt}; + mod apps; mod components; mod instructions; +mod intrinsics; mod rust_sdk; mod wit_sdk; + +pub fn run_masm_vs_rust( + rust_out: T, + vm_program: &miden_core::Program, + ir_masm: Arc, + args: &[Felt], +) -> Result<(), TestCaseError> +where + T: Clone + From + std::cmp::PartialEq + std::fmt::Debug, +{ + let vm_out: T = execute_vm(&vm_program, &args).first().unwrap().clone().into(); + dbg!(&vm_out); + prop_assert_eq!(rust_out.clone(), vm_out, "VM output mismatch"); + let emul_out: T = execute_emulator(ir_masm.clone(), &args).first().unwrap().clone().into(); + prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); + Ok(()) +} diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index fb5ec4466..98fac4cf1 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -1,10 +1,16 @@ +use std::path::PathBuf; + use expect_test::expect_file; use crate::CompilerTest; #[test] fn account() { - let mut test = CompilerTest::rust_source_cargo_lib("rust-sdk/account-test"); + let mut test = CompilerTest::rust_source_cargo_lib( + PathBuf::from("../rust-apps-wasm/rust-sdk/account-test"), + true, + None, + ); let artifact_name = test.source.artifact_name(); test.expect_wasm(expect_file![format!( "../../expected/rust_sdk_account_test/{artifact_name}.wat" From 9397872bad309e11603b3aabf616fc4f01da36ec Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 19 Apr 2024 08:02:44 +0300 Subject: [PATCH 2/3] fix build after rebase --- .../src/rust_masm_tests/instructions.rs | 21 ++----------------- tests/integration/src/rust_masm_tests/mod.rs | 9 ++++---- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/tests/integration/src/rust_masm_tests/instructions.rs b/tests/integration/src/rust_masm_tests/instructions.rs index 3c4003c8c..3ff477118 100644 --- a/tests/integration/src/rust_masm_tests/instructions.rs +++ b/tests/integration/src/rust_masm_tests/instructions.rs @@ -1,13 +1,11 @@ -use std::sync::Arc; - use expect_test::expect_file; -use miden_core::Felt; use proptest::{ prelude::*, test_runner::{TestError, TestRunner}, }; -use crate::{execute_emulator, execute_vm, felt_conversion::TestFelt, CompilerTest}; +use super::run_masm_vs_rust; +use crate::{felt_conversion::TestFelt, CompilerTest}; macro_rules! test_bin_op { ($name:ident, $op:tt, $op_ty:tt, $res_ty:tt, $a_range:expr, $b_range:expr) => { @@ -125,21 +123,6 @@ macro_rules! test_func_two_arg { }); }; } -fn run_masm( - rust_out: T, - vm_program: &miden_core::Program, - ir_masm: Arc, - args: &[Felt], -) -> Result<(), TestCaseError> -where - T: Clone + From + std::cmp::PartialEq + std::fmt::Debug, -{ - let vm_out: T = execute_vm(&vm_program, &args).first().unwrap().clone().into(); - prop_assert_eq!(rust_out.clone(), vm_out, "VM output mismatch"); - let emul_out: T = execute_emulator(ir_masm.clone(), &args).first().unwrap().clone().into(); - prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); - Ok(()) -} macro_rules! test_bool_op_total { ($name:ident, $op:tt, $op_ty:tt) => { diff --git a/tests/integration/src/rust_masm_tests/mod.rs b/tests/integration/src/rust_masm_tests/mod.rs index c6a0f98d5..1ecfae127 100644 --- a/tests/integration/src/rust_masm_tests/mod.rs +++ b/tests/integration/src/rust_masm_tests/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use miden_core::Felt; use proptest::{prop_assert_eq, test_runner::TestCaseError}; -use crate::{execute_emulator, execute_vm, felt_conversion::TestFelt}; +use crate::{execute_vm, felt_conversion::TestFelt}; mod apps; mod components; @@ -15,7 +15,7 @@ mod wit_sdk; pub fn run_masm_vs_rust( rust_out: T, vm_program: &miden_core::Program, - ir_masm: Arc, + _ir_masm: Arc, args: &[Felt], ) -> Result<(), TestCaseError> where @@ -24,7 +24,8 @@ where let vm_out: T = execute_vm(&vm_program, &args).first().unwrap().clone().into(); dbg!(&vm_out); prop_assert_eq!(rust_out.clone(), vm_out, "VM output mismatch"); - let emul_out: T = execute_emulator(ir_masm.clone(), &args).first().unwrap().clone().into(); - prop_assert_eq!(rust_out, emul_out, "Emulator 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(); + // prop_assert_eq!(rust_out, emul_out, "Emulator output mismatch"); Ok(()) } From 2ac171fa16bd24e43d4f133b6dc49c6f7cfe7ea5 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 19 Apr 2024 16:52:06 +0300 Subject: [PATCH 3/3] test: add semantic tests for Felt intrinsics (add, sub, mul, div, neg, eq) --- sdk/prelude/src/intrinsics/felt.rs | 30 +- tests/integration/Cargo.toml | 2 +- tests/integration/expected/add_felt.hir | 21 + tests/integration/expected/add_felt.masm | 669 +++++++++++++++++ tests/integration/expected/add_felt.wat | 14 + tests/integration/expected/div_felt.hir | 21 + tests/integration/expected/div_felt.masm | 669 +++++++++++++++++ tests/integration/expected/div_felt.wat | 14 + tests/integration/expected/eq_felt.hir | 25 + tests/integration/expected/eq_felt.masm | 671 ++++++++++++++++++ tests/integration/expected/eq_felt.wat | 16 + tests/integration/expected/ge_felt.hir | 25 + tests/integration/expected/ge_felt.masm | 671 ++++++++++++++++++ tests/integration/expected/ge_felt.wat | 16 + tests/integration/expected/gt_felt.hir | 25 + tests/integration/expected/gt_felt.masm | 671 ++++++++++++++++++ tests/integration/expected/gt_felt.wat | 16 + tests/integration/expected/le_felt.hir | 25 + tests/integration/expected/le_felt.masm | 670 +++++++++++++++++ tests/integration/expected/le_felt.wat | 16 + tests/integration/expected/lt_felt.hir | 25 + tests/integration/expected/lt_felt.masm | 670 +++++++++++++++++ tests/integration/expected/lt_felt.wat | 16 + tests/integration/expected/mul_felt.hir | 21 + tests/integration/expected/mul_felt.masm | 669 +++++++++++++++++ tests/integration/expected/mul_felt.wat | 14 + tests/integration/expected/neg_felt.hir | 21 + tests/integration/expected/neg_felt.masm | 669 +++++++++++++++++ tests/integration/expected/neg_felt.wat | 14 + tests/integration/expected/sub_felt.hir | 21 + tests/integration/expected/sub_felt.masm | 669 +++++++++++++++++ tests/integration/expected/sub_felt.wat | 14 + tests/integration/src/felt_conversion.rs | 19 + .../src/rust_masm_tests/intrinsics.rs | 117 ++- 34 files changed, 7219 insertions(+), 27 deletions(-) create mode 100644 tests/integration/expected/add_felt.hir create mode 100644 tests/integration/expected/add_felt.masm create mode 100644 tests/integration/expected/add_felt.wat create mode 100644 tests/integration/expected/div_felt.hir create mode 100644 tests/integration/expected/div_felt.masm create mode 100644 tests/integration/expected/div_felt.wat create mode 100644 tests/integration/expected/eq_felt.hir create mode 100644 tests/integration/expected/eq_felt.masm create mode 100644 tests/integration/expected/eq_felt.wat create mode 100644 tests/integration/expected/ge_felt.hir create mode 100644 tests/integration/expected/ge_felt.masm create mode 100644 tests/integration/expected/ge_felt.wat create mode 100644 tests/integration/expected/gt_felt.hir create mode 100644 tests/integration/expected/gt_felt.masm create mode 100644 tests/integration/expected/gt_felt.wat create mode 100644 tests/integration/expected/le_felt.hir create mode 100644 tests/integration/expected/le_felt.masm create mode 100644 tests/integration/expected/le_felt.wat create mode 100644 tests/integration/expected/lt_felt.hir create mode 100644 tests/integration/expected/lt_felt.masm create mode 100644 tests/integration/expected/lt_felt.wat create mode 100644 tests/integration/expected/mul_felt.hir create mode 100644 tests/integration/expected/mul_felt.masm create mode 100644 tests/integration/expected/mul_felt.wat create mode 100644 tests/integration/expected/neg_felt.hir create mode 100644 tests/integration/expected/neg_felt.masm create mode 100644 tests/integration/expected/neg_felt.wat create mode 100644 tests/integration/expected/sub_felt.hir create mode 100644 tests/integration/expected/sub_felt.masm create mode 100644 tests/integration/expected/sub_felt.wat diff --git a/sdk/prelude/src/intrinsics/felt.rs b/sdk/prelude/src/intrinsics/felt.rs index 141123837..460d55c02 100644 --- a/sdk/prelude/src/intrinsics/felt.rs +++ b/sdk/prelude/src/intrinsics/felt.rs @@ -1,4 +1,4 @@ -use core::ops::{Add, Div, Mul, Neg, Sub}; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; #[link(wasm_import_module = "miden:prelude/intrinsics_felt")] extern "C" { @@ -171,6 +171,13 @@ impl Add for Felt { } } +impl AddAssign for Felt { + #[inline(always)] + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} + impl Sub for Felt { type Output = Self; @@ -180,6 +187,13 @@ impl Sub for Felt { } } +impl SubAssign for Felt { + #[inline(always)] + fn sub_assign(&mut self, other: Self) { + *self = *self - other; + } +} + impl Mul for Felt { type Output = Self; @@ -189,6 +203,13 @@ impl Mul for Felt { } } +impl MulAssign for Felt { + #[inline(always)] + fn mul_assign(&mut self, other: Self) { + *self = *self * other; + } +} + impl Div for Felt { type Output = Self; @@ -198,6 +219,13 @@ impl Div for Felt { } } +impl DivAssign for Felt { + #[inline(always)] + fn div_assign(&mut self, other: Self) { + *self = *self / other; + } +} + impl Neg for Felt { type Output = Self; diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml index 2cd94ab01..89e707eca 100644 --- a/tests/integration/Cargo.toml +++ b/tests/integration/Cargo.toml @@ -33,8 +33,8 @@ cargo-util = "0.2" filetime = "0.2.23" glob = "0.3.1" walkdir = "2.5.0" +proptest.workspace = true [dev-dependencies] miden-core.workspace = true -proptest.workspace = true concat-idents = "1.1" diff --git a/tests/integration/expected/add_felt.hir b/tests/integration/expected/add_felt.hir new file mode 100644 index 000000000..7bdcb4680 --- /dev/null +++ b/tests/integration/expected/add_felt.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #add_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (add.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/add_felt.masm b/tests/integration/expected/add_felt.masm new file mode 100644 index 000000000..2262c117f --- /dev/null +++ b/tests/integration/expected/add_felt.masm @@ -0,0 +1,669 @@ +mod add_felt + +export.entrypoint + swap.1 + add +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use add_felt + +begin + exec.add_felt::entrypoint +end diff --git a/tests/integration/expected/add_felt.wat b/tests/integration/expected/add_felt.wat new file mode 100644 index 000000000..ee7953121 --- /dev/null +++ b/tests/integration/expected/add_felt.wat @@ -0,0 +1,14 @@ +(module $add_felt.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "add" (func $miden_prelude::intrinsics::felt::extern_add (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_add + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/div_felt.hir b/tests/integration/expected/div_felt.hir new file mode 100644 index 000000000..4f0d41b79 --- /dev/null +++ b/tests/integration/expected/div_felt.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #div_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (div.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/div_felt.masm b/tests/integration/expected/div_felt.masm new file mode 100644 index 000000000..5288db37a --- /dev/null +++ b/tests/integration/expected/div_felt.masm @@ -0,0 +1,669 @@ +mod div_felt + +export.entrypoint + swap.1 + div +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use div_felt + +begin + exec.div_felt::entrypoint +end diff --git a/tests/integration/expected/div_felt.wat b/tests/integration/expected/div_felt.wat new file mode 100644 index 000000000..a47436670 --- /dev/null +++ b/tests/integration/expected/div_felt.wat @@ -0,0 +1,14 @@ +(module $div_felt.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "div" (func $miden_prelude::intrinsics::felt::extern_div (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_div + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/eq_felt.hir b/tests/integration/expected/eq_felt.hir new file mode 100644 index 000000000..934012644 --- /dev/null +++ b/tests/integration/expected/eq_felt.hir @@ -0,0 +1,25 @@ +(component + ;; Modules + (module #eq_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result i32) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 i1) (eq v0 v1)) + (let (v4 i32) (cast v3)) + (let (v5 i32) (const.i32 1)) + (let (v6 i1) (eq v4 v5)) + (let (v7 i32) (cast v6)) + (br (block 1 v7))) + + (block 1 (param v2 i32) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/eq_felt.masm b/tests/integration/expected/eq_felt.masm new file mode 100644 index 000000000..347ec3797 --- /dev/null +++ b/tests/integration/expected/eq_felt.masm @@ -0,0 +1,671 @@ +mod eq_felt + +export.entrypoint + swap.1 + eq + push.1 + eq +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use eq_felt + +begin + exec.eq_felt::entrypoint +end diff --git a/tests/integration/expected/eq_felt.wat b/tests/integration/expected/eq_felt.wat new file mode 100644 index 000000000..8f8212ea1 --- /dev/null +++ b/tests/integration/expected/eq_felt.wat @@ -0,0 +1,16 @@ +(module $eq_felt.wasm + (type (;0;) (func (param f64 f64) (result i32))) + (import "miden:prelude/intrinsics_felt" "eq" (func $miden_prelude::intrinsics::felt::extern_eq (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result i32) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_eq + i32.const 1 + i32.eq + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/ge_felt.hir b/tests/integration/expected/ge_felt.hir new file mode 100644 index 000000000..46a832676 --- /dev/null +++ b/tests/integration/expected/ge_felt.hir @@ -0,0 +1,25 @@ +(component + ;; Modules + (module #ge_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result i32) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 i1) (gte v0 v1)) + (let (v4 i32) (cast v3)) + (let (v5 i32) (const.i32 0)) + (let (v6 i1) (neq v4 v5)) + (let (v7 i32) (cast v6)) + (br (block 1 v7))) + + (block 1 (param v2 i32) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/ge_felt.masm b/tests/integration/expected/ge_felt.masm new file mode 100644 index 000000000..9b95bf20b --- /dev/null +++ b/tests/integration/expected/ge_felt.masm @@ -0,0 +1,671 @@ +mod ge_felt + +export.entrypoint + swap.1 + gte + push.0 + neq +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use ge_felt + +begin + exec.ge_felt::entrypoint +end diff --git a/tests/integration/expected/ge_felt.wat b/tests/integration/expected/ge_felt.wat new file mode 100644 index 000000000..c57434a6a --- /dev/null +++ b/tests/integration/expected/ge_felt.wat @@ -0,0 +1,16 @@ +(module $ge_felt.wasm + (type (;0;) (func (param f64 f64) (result i32))) + (import "miden:prelude/intrinsics_felt" "ge" (func $miden_prelude::intrinsics::felt::extern_ge (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result i32) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_ge + i32.const 0 + i32.ne + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/gt_felt.hir b/tests/integration/expected/gt_felt.hir new file mode 100644 index 000000000..317326cab --- /dev/null +++ b/tests/integration/expected/gt_felt.hir @@ -0,0 +1,25 @@ +(component + ;; Modules + (module #gt_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result i32) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 i1) (gt v0 v1)) + (let (v4 i32) (cast v3)) + (let (v5 i32) (const.i32 0)) + (let (v6 i1) (neq v4 v5)) + (let (v7 i32) (cast v6)) + (br (block 1 v7))) + + (block 1 (param v2 i32) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/gt_felt.masm b/tests/integration/expected/gt_felt.masm new file mode 100644 index 000000000..e3b73e749 --- /dev/null +++ b/tests/integration/expected/gt_felt.masm @@ -0,0 +1,671 @@ +mod gt_felt + +export.entrypoint + swap.1 + gt + push.0 + neq +end + +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +program + +use gt_felt + +begin + exec.gt_felt::entrypoint +end diff --git a/tests/integration/expected/gt_felt.wat b/tests/integration/expected/gt_felt.wat new file mode 100644 index 000000000..ca81b7a5f --- /dev/null +++ b/tests/integration/expected/gt_felt.wat @@ -0,0 +1,16 @@ +(module $gt_felt.wasm + (type (;0;) (func (param f64 f64) (result i32))) + (import "miden:prelude/intrinsics_felt" "gt" (func $miden_prelude::intrinsics::felt::extern_gt (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result i32) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_gt + i32.const 0 + i32.ne + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/le_felt.hir b/tests/integration/expected/le_felt.hir new file mode 100644 index 000000000..5b7305e90 --- /dev/null +++ b/tests/integration/expected/le_felt.hir @@ -0,0 +1,25 @@ +(component + ;; Modules + (module #le_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result i32) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 i1) (lte v1 v0)) + (let (v4 i32) (cast v3)) + (let (v5 i32) (const.i32 0)) + (let (v6 i1) (neq v4 v5)) + (let (v7 i32) (cast v6)) + (br (block 1 v7))) + + (block 1 (param v2 i32) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/le_felt.masm b/tests/integration/expected/le_felt.masm new file mode 100644 index 000000000..4e272906c --- /dev/null +++ b/tests/integration/expected/le_felt.masm @@ -0,0 +1,670 @@ +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +mod le_felt + +export.entrypoint + lte + push.0 + neq +end + +program + +use le_felt + +begin + exec.le_felt::entrypoint +end diff --git a/tests/integration/expected/le_felt.wat b/tests/integration/expected/le_felt.wat new file mode 100644 index 000000000..94ad3c26a --- /dev/null +++ b/tests/integration/expected/le_felt.wat @@ -0,0 +1,16 @@ +(module $le_felt.wasm + (type (;0;) (func (param f64 f64) (result i32))) + (import "miden:prelude/intrinsics_felt" "le" (func $miden_prelude::intrinsics::felt::extern_le (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result i32) + local.get 1 + local.get 0 + call $miden_prelude::intrinsics::felt::extern_le + i32.const 0 + i32.ne + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/lt_felt.hir b/tests/integration/expected/lt_felt.hir new file mode 100644 index 000000000..60ab39c69 --- /dev/null +++ b/tests/integration/expected/lt_felt.hir @@ -0,0 +1,25 @@ +(component + ;; Modules + (module #lt_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result i32) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 i1) (lt v1 v0)) + (let (v4 i32) (cast v3)) + (let (v5 i32) (const.i32 0)) + (let (v6 i1) (neq v4 v5)) + (let (v7 i32) (cast v6)) + (br (block 1 v7))) + + (block 1 (param v2 i32) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/lt_felt.masm b/tests/integration/expected/lt_felt.masm new file mode 100644 index 000000000..c31efc284 --- /dev/null +++ b/tests/integration/expected/lt_felt.masm @@ -0,0 +1,670 @@ +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +mod lt_felt + +export.entrypoint + lt + push.0 + neq +end + +program + +use lt_felt + +begin + exec.lt_felt::entrypoint +end diff --git a/tests/integration/expected/lt_felt.wat b/tests/integration/expected/lt_felt.wat new file mode 100644 index 000000000..04c79aee6 --- /dev/null +++ b/tests/integration/expected/lt_felt.wat @@ -0,0 +1,16 @@ +(module $lt_felt.wasm + (type (;0;) (func (param f64 f64) (result i32))) + (import "miden:prelude/intrinsics_felt" "lt" (func $miden_prelude::intrinsics::felt::extern_lt (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result i32) + local.get 1 + local.get 0 + call $miden_prelude::intrinsics::felt::extern_lt + i32.const 0 + i32.ne + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/mul_felt.hir b/tests/integration/expected/mul_felt.hir new file mode 100644 index 000000000..4b1b8b2c1 --- /dev/null +++ b/tests/integration/expected/mul_felt.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #mul_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (mul.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/mul_felt.masm b/tests/integration/expected/mul_felt.masm new file mode 100644 index 000000000..dbc7ad2d3 --- /dev/null +++ b/tests/integration/expected/mul_felt.masm @@ -0,0 +1,669 @@ +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +mod mul_felt + +export.entrypoint + swap.1 + mul +end + +program + +use mul_felt + +begin + exec.mul_felt::entrypoint +end diff --git a/tests/integration/expected/mul_felt.wat b/tests/integration/expected/mul_felt.wat new file mode 100644 index 000000000..fb3b00151 --- /dev/null +++ b/tests/integration/expected/mul_felt.wat @@ -0,0 +1,14 @@ +(module $mul_felt.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "mul" (func $miden_prelude::intrinsics::felt::extern_mul (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_mul + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/neg_felt.hir b/tests/integration/expected/neg_felt.hir new file mode 100644 index 000000000..3a2d32653 --- /dev/null +++ b/tests/integration/expected/neg_felt.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #neg_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (sub.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/neg_felt.masm b/tests/integration/expected/neg_felt.masm new file mode 100644 index 000000000..7401d4e96 --- /dev/null +++ b/tests/integration/expected/neg_felt.masm @@ -0,0 +1,669 @@ +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +mod neg_felt + +export.entrypoint + swap.1 + sub +end + +program + +use neg_felt + +begin + exec.neg_felt::entrypoint +end diff --git a/tests/integration/expected/neg_felt.wat b/tests/integration/expected/neg_felt.wat new file mode 100644 index 000000000..0d2ae43b3 --- /dev/null +++ b/tests/integration/expected/neg_felt.wat @@ -0,0 +1,14 @@ +(module $neg_felt.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "sub" (func $miden_prelude::intrinsics::felt::extern_sub (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_sub + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/expected/sub_felt.hir b/tests/integration/expected/sub_felt.hir new file mode 100644 index 000000000..9ff0f4a57 --- /dev/null +++ b/tests/integration/expected/sub_felt.hir @@ -0,0 +1,21 @@ +(component + ;; Modules + (module #sub_felt + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func (export #entrypoint) (param felt) (param felt) (result felt) + (block 0 (param v0 felt) (param v1 felt) + (let (v3 felt) (sub.unchecked v0 v1)) + (br (block 1 v3))) + + (block 1 (param v2 felt) + (ret v2)) + ) + ) + +) diff --git a/tests/integration/expected/sub_felt.masm b/tests/integration/expected/sub_felt.masm new file mode 100644 index 000000000..7e239c846 --- /dev/null +++ b/tests/integration/expected/sub_felt.masm @@ -0,0 +1,669 @@ +mod intrinsics::i32 + +export.is_signed + push.2147483648 + u32and + push.2147483648 + eq +end + +export.unchecked_neg + u32not + u32wrapping_add.1 +end + +export.checked_neg + dup.0 + push.2147483648 + eq + assertz + exec.unchecked_neg +end + +export.overflowing_add + u32assert2 + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + eq + movup.3 + movup.3 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and +end + +export.wrapping_add + exec.overflowing_add + drop +end + +export.checked_add + exec.overflowing_add + assertz +end + +export.overflowing_sub + u32assert2 + dup.0 + push.2147483648 + eq + if.true + drop + push.2147483647 + dup.1 + exec.is_signed + dup.0 + eq.0 + movup.3 + movup.3 + u32wrapping_add + push.1 + u32wrapping_add + dup.0 + exec.is_signed + movup.3 + neq + movup.2 + and + else + exec.unchecked_neg + exec.overflowing_add + end +end + +export.wrapping_sub + exec.overflowing_sub + drop +end + +export.checked_sub + exec.overflowing_sub + assertz +end + +export.overflowing_mul + u32assert2 + dup.0 + push.2147483648 + eq + dup.2 + push.2147483648 + eq + or + if.true + dup.0 + eq.1 + dup.2 + eq.1 + or + movup.2 + push.4294967295 + eq + movup.2 + push.4294967295 + eq + or + dup.1 + or + push.2147483648 + push.0 + swap.2 + cdrop + swap.1 + not + else + dup.0 + exec.is_signed + dup.2 + exec.is_signed + dup.1 + dup.1 + neq + movdn.4 + movup.3 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + swap.2 + dup.0 + exec.unchecked_neg + movup.2 + cdrop + u32overflowing_mul + dup.1 + exec.is_signed + or + swap.1 + dup.0 + exec.unchecked_neg + movup.3 + cdrop + swap.1 + end +end + +export.wrapping_mul + exec.overflowing_mul + drop +end + +export.checked_mul + exec.overflowing_mul + assertz +end + +export.checked_div + u32assert2 + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.4 + cdrop + dup.1 + exec.unchecked_neg + dup.2 + swap.1 + movup.3 + exec.is_signed + dup.0 + movdn.5 + cdrop + u32div + movdn.2 + neq + dup.1 + exec.unchecked_neg + swap.1 + cdrop +end + +export.icmp + dup.1 + dup.1 + push.2147483648 + u32and + swap.1 + push.2147483648 + u32and + eq.0 + swap.1 + eq.0 + swap.1 + dup.1 + neq + if.true + movdn.2 + drop + drop + push.4294967295 + push.1 + swap.2 + cdrop + else + drop + dup.1 + dup.1 + u32gt + movdn.2 + u32lt + push.0 + push.4294967295 + push.1 + swap.3 + cdrop + swap.2 + cdrop + end +end + +export.is_lt + exec.icmp + push.4294967295 + eq +end + +export.is_lte + exec.icmp + neq.1 +end + +export.is_gt + exec.icmp + eq.1 +end + +export.is_gte + exec.icmp + push.4294967295 + neq +end + +export.pow2 + dup.0 + push.31 + u32lt + assert + push.1 + swap.1 + u32shl +end + +export.ipow + dup.0 + push.31 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + push.1 + push.0 + swap.2 + cdrop + swap.1 + drop + else + push.1 + dup.1 + push.1 + u32gt + while.true + dup.2 + dup.1 + u32wrapping_mul + dup.2 + push.1 + u32and + eq.1 + cdrop + swap.1 + u32div.2 + movup.2 + dup.0 + u32wrapping_mul + swap.1 + movup.2 + dup.1 + push.1 + u32gt + end + swap.1 + drop + u32wrapping_mul + end +end + +export.checked_shr + dup.0 + push.32 + u32lt + assert + dup.0 + eq.0 + dup.2 + eq.0 + or + if.true + eq.0 + swap.1 + push.0 + swap.2 + cdrop + else + dup.1 + push.2147483648 + u32and + push.2147483648 + eq + if.true + swap.1 + dup.1 + u32shr + push.1 + dup.2 + u32shl + sub.1 + push.32 + movup.3 + sub + u32shl + u32or + u32assert + else + u32shr + u32assert + end + end +end + +mod intrinsics::mem + +export.extract_element + dup.0 + push.3 + lte + assert + dup.0 + push.3 + lt + movdn.5 + dup.0 + push.2 + lt + movdn.5 + push.1 + lt + cdrop + movup.3 + cdrop + movup.2 + cdrop +end + +proc.load_felt_unchecked + padw + movup.4 + mem_loadw + movup.4 + exec.extract_element +end + +export.load_felt + movup.2 + assertz + exec.load_felt_unchecked +end + +export.load_sw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + exec.load_felt_unchecked + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.3 + movup.3 + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movdn.2 + movdn.2 + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + dup.2 + u32shl + swap.1 + push.32 + movup.3 + u32overflowing_sub + assertz + u32shr + u32or + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movdn.4 + drop + drop + drop + push.32 + dup.3 + u32overflowing_sub + assertz + u32shr + swap.1 + padw + movup.4 + mem_loadw + drop + drop + drop + movup.2 + u32shl + u32or + end + end + end + end +end + +export.realign_dw + dup.3 + u32shl + movdn.2 + dup.0 + push.32 + dup.4 + u32shr + movup.4 + u32or + movdn.2 + dup.3 + u32shl + swap.1 + push.32 + movup.4 + u32shr + u32or + swap.1 +end + +export.load_dw + dup.2 + eq.0 + dup.3 + push.8 + u32lt + assert + if.true + movup.2 + drop + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + movup.3 + drop + else + swap.1 + eq.2 + if.true + padw + movup.4 + mem_loadw + drop + drop + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + movup.4 + padw + movup.4 + mem_loadw + drop + drop + drop + end + end + end + else + dup.1 + eq.0 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + movup.4 + drop + exec.realign_dw + else + dup.1 + eq.1 + if.true + swap.1 + drop + padw + movup.4 + mem_loadw + drop + exec.realign_dw + else + swap.1 + eq.2 + if.true + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + movup.4 + drop + drop + drop + swap.1 + padw + movup.4 + mem_loadw + drop + drop + exec.realign_dw + else + dup.0 + u32overflowing_add.1 + assertz + padw + movup.4 + mem_loadw + movup.4 + movup.4 + drop + drop + movup.2 + padw + movup.4 + mem_loadw + drop + drop + drop + exec.realign_dw + end + end + end + end +end + +mod sub_felt + +export.entrypoint + swap.1 + sub +end + +program + +use sub_felt + +begin + exec.sub_felt::entrypoint +end diff --git a/tests/integration/expected/sub_felt.wat b/tests/integration/expected/sub_felt.wat new file mode 100644 index 000000000..733dd10a0 --- /dev/null +++ b/tests/integration/expected/sub_felt.wat @@ -0,0 +1,14 @@ +(module $sub_felt.wasm + (type (;0;) (func (param f64 f64) (result f64))) + (import "miden:prelude/intrinsics_felt" "sub" (func $miden_prelude::intrinsics::felt::extern_sub (;0;) (type 0))) + (func $entrypoint (;1;) (type 0) (param f64 f64) (result f64) + local.get 0 + local.get 1 + call $miden_prelude::intrinsics::felt::extern_sub + ) + (table (;0;) 1 1 funcref) + (memory (;0;) 16) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "entrypoint" (func $entrypoint)) +) \ No newline at end of file diff --git a/tests/integration/src/felt_conversion.rs b/tests/integration/src/felt_conversion.rs index b7381cb70..c4578b683 100644 --- a/tests/integration/src/felt_conversion.rs +++ b/tests/integration/src/felt_conversion.rs @@ -1,10 +1,20 @@ use miden_core::{Felt, StarkField}; +use proptest::{ + arbitrary::Arbitrary, + strategy::{BoxedStrategy, Strategy}, +}; /// Wrapper around `Felt` that implements `From` for a bunch of types that are want to support in /// tests #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct TestFelt(pub Felt); +impl From for Felt { + fn from(f: TestFelt) -> Self { + f.0 + } +} + impl From for TestFelt { fn from(b: bool) -> Self { Self(Felt::from(b as u32)) @@ -114,3 +124,12 @@ impl From for i64 { f.0.as_int() as i64 } } + +impl Arbitrary for TestFelt { + type Parameters = (); + type Strategy = BoxedStrategy; + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + (0u64..u64::MAX).prop_map(|v| TestFelt(Felt::from(v))).boxed() + } +} diff --git a/tests/integration/src/rust_masm_tests/intrinsics.rs b/tests/integration/src/rust_masm_tests/intrinsics.rs index d4d5629f9..aa7a76a85 100644 --- a/tests/integration/src/rust_masm_tests/intrinsics.rs +++ b/tests/integration/src/rust_masm_tests/intrinsics.rs @@ -1,6 +1,7 @@ use core::panic; use expect_test::expect_file; +use miden_core::Felt; use proptest::{ arbitrary::any, test_runner::{TestError, TestRunner}, @@ -8,30 +9,96 @@ use proptest::{ use crate::{felt_conversion::TestFelt, rust_masm_tests::run_masm_vs_rust, CompilerTest}; -#[test] -fn test_felt_plus() { - let main_fn = format!("(a: Felt, b: Felt) -> Felt {{ a + b }}"); - let artifact_name = "felt_plus"; - let mut test = CompilerTest::rust_fn_body_with_prelude(&artifact_name, &main_fn); - // Test expected compilation artifacts - 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 ir_masm = test.ir_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 - // TODO: generate proper felt values, i.e. in the range [0, M) - let res = TestRunner::default().run(&(any::(), any::()), move |(a, b)| { - let rust_out = a.wrapping_add(b); - let args = [TestFelt::from(a).0, TestFelt::from(b).0]; - run_masm_vs_rust(rust_out, &vm_program, ir_masm.clone(), &args) - }); - match res { - Err(TestError::Fail(_, value)) => { - panic!("Found minimal(shrinked) failing case: {:?}", value); - } - Ok(_) => (), - _ => panic!("Unexpected test result: {:?}", res), +/// Compiles, runs VM vs. Rust fuzzing the inputs via proptest +macro_rules! test_bin_op { + ($name:ident, $op:tt, $op_ty:tt, $res_ty:tt, $a_range:expr, $b_range:expr) => { + concat_idents::concat_idents!(test_name = $name { + #[test] + fn test_name() { + let op_str = stringify!($op); + let op_ty_str = stringify!($op_ty); + let res_ty_str = stringify!($res_ty); + let main_fn = format!("(a: {op_ty_str}, b: {op_ty_str}) -> {res_ty_str} {{ a {op_str} b }}"); + let artifact_name = format!("{}_{}", stringify!($name), stringify!($op_ty).to_lowercase()); + let mut test = CompilerTest::rust_fn_body_with_prelude(&artifact_name, &main_fn); + // Test expected compilation artifacts + 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 ir_masm = test.ir_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(&($a_range, $b_range), move |(a, b)| { + dbg!(a, b); + let a_felt: Felt = a.0; + let b_felt: Felt = b.0; + 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, ir_masm.clone(), &args) + }); + match res { + Err(TestError::Fail(_, value)) => { + panic!("Found minimal(shrinked) failing case: {:?}", value); + }, + Ok(_) => (), + _ => panic!("Unexpected test result: {:?}", res), } + } + }); + }; +} + +/// Compiles given binary operation +macro_rules! test_compile_comparison_op { + ($name:ident, $op:tt) => { + concat_idents::concat_idents!(test_name = $name { + #[test] + fn test_name() { + let op_str = stringify!($op); + let main_fn = format!("(a: Felt, b: Felt) -> bool {{ a {op_str} b }}"); + let artifact_name = format!("{}_felt", stringify!($name)); + let mut test = CompilerTest::rust_fn_body_with_prelude(&artifact_name, &main_fn); + // Test expected compilation artifacts + 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")]); + } + }); + }; } + +macro_rules! test_bin_op_total { + ($name:ident, $op:tt) => { + test_bin_op!($name, $op, Felt, Felt, any::(), any::()); + }; +} + +macro_rules! test_bool_op_total { + ($name:ident, $op:tt) => { + test_bin_op!($name, $op, Felt, bool, any::(), any::()); + }; +} + +test_bin_op_total!(add, +); +test_bin_op_total!(sub, -); +test_bin_op_total!(mul, *); +test_bin_op_total!(div, /); +test_bin_op_total!(neg, -); + +test_bool_op_total!(eq, ==); + +// TODO: Comparison operators are not defined for Felt, so we cannot compile a Rust equivalent for +// the semantic test +// see https://github.com/0xPolygonMiden/compiler/issues/175 +// test_bool_op_total!(gt, >); +// test_bool_op_total!(lt, <); +// test_bool_op_total!(ge, >=); +// test_bool_op_total!(le, <=); + +test_compile_comparison_op!(gt, >); +test_compile_comparison_op!(lt, <); +test_compile_comparison_op!(ge, >=); +test_compile_comparison_op!(le, <=);