From 7fbe165029149369537e43ea4d7291045a77b62a Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 26 Nov 2024 16:08:55 +0200 Subject: [PATCH 01/26] refactor: switch from passing `Module` to `Component` in the compiler stages --- hir/src/component/mod.rs | 38 ++++++++++++++++++++++++++++ midenc-compile/src/stages/link.rs | 8 +++--- midenc-compile/src/stages/parse.rs | 19 ++++++++------ midenc-compile/src/stages/rewrite.rs | 7 +++-- midenc-compile/src/stages/sema.rs | 20 +++++++++------ 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index cc9d25fe4..b3b85db1c 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -1,6 +1,7 @@ use alloc::collections::BTreeMap; use core::ops::{Deref, DerefMut}; +use diagnostics::Spanned; use indexmap::IndexMap; use midenc_hir_type::Abi; @@ -187,6 +188,19 @@ impl Component { Self::default() } + /// Return the name of this component + pub fn name(&self) -> Ident { + // Temporary imterim solution until we have a proper way to name components + let module_names = self.modules.keys().fold(String::new(), |acc, name| { + if acc.is_empty() { + name.to_string() + } else { + acc + "+" + name.as_str() + } + }); + Ident::new(Symbol::intern(&module_names), self.modules.first().unwrap().0.span()) + } + /// Return a reference to the module table for this program pub fn modules(&self) -> &IndexMap> { &self.modules @@ -306,6 +320,30 @@ impl formatter::PrettyPrint for Component { } } +impl midenc_session::Emit for Component { + fn name(&self) -> Option { + Some(self.name().as_symbol()) + } + + fn output_type(&self, _mode: midenc_session::OutputMode) -> midenc_session::OutputType { + midenc_session::OutputType::Hir + } + + fn write_to( + &self, + mut writer: W, + mode: midenc_session::OutputMode, + _session: &midenc_session::Session, + ) -> std::io::Result<()> { + assert_eq!( + mode, + midenc_session::OutputMode::Text, + "binary mode is not supported for HIR Components" + ); + writer.write_fmt(format_args!("{}", self)) + } +} + /// This struct provides an ergonomic way to construct a [Component] in an imperative fashion. /// /// Simply create the builder, add/build one or more modules, then call `link` to obtain a diff --git a/midenc-compile/src/stages/link.rs b/midenc-compile/src/stages/link.rs index cbd55d44f..a3c2f5dea 100644 --- a/midenc-compile/src/stages/link.rs +++ b/midenc-compile/src/stages/link.rs @@ -1,7 +1,7 @@ use super::*; pub enum LinkerInput { - Hir(Box), + Hir(Box), Masm(Box), } @@ -28,8 +28,10 @@ impl Stage for LinkerStage { let mut masm = masm::ModuleTree::default(); for input in inputs { match input { - LinkerInput::Hir(module) => { - ir.push_back(module); + LinkerInput::Hir(component) => { + for (_id, module) in component.to_modules().into_iter() { + ir.push_back(module); + } } LinkerInput::Masm(module) => { masm.insert(module); diff --git a/midenc-compile/src/stages/parse.rs b/midenc-compile/src/stages/parse.rs index 1d188c75c..ea0501c6e 100644 --- a/midenc-compile/src/stages/parse.rs +++ b/midenc-compile/src/stages/parse.rs @@ -14,7 +14,7 @@ pub enum ParseOutput { /// We parsed HIR into the AST from text Ast(Box), /// We parsed HIR from a Wasm module or other binary format - Hir(Box), + Hir(Box), /// We parsed MASM from a Miden Assembly module or other binary format Masm(Box), } @@ -129,10 +129,13 @@ impl ParseStage { session: &Session, config: &WasmTranslationConfig, ) -> CompilerResult { - let module = wasm::translate(bytes, config, session)?.unwrap_one_module(); - log::debug!("parsed hir module from wasm bytes: {}", module.name.as_str()); + let component = wasm::translate(bytes, config, session)?; + log::debug!( + "parsed hir component from wasm bytes with first module name: {}", + component.name() + ); - Ok(ParseOutput::Hir(module)) + Ok(ParseOutput::Hir(component.into())) } fn parse_hir_from_wat_file( @@ -146,9 +149,9 @@ impl ParseStage { ..Default::default() }; let wasm = wat::parse_file(path).into_diagnostic().wrap_err("failed to parse wat")?; - let module = wasm::translate(&wasm, &config, session)?.unwrap_one_module(); + let component = wasm::translate(&wasm, &config, session)?; - Ok(ParseOutput::Hir(module)) + Ok(ParseOutput::Hir(component.into())) } fn parse_hir_from_wat_bytes( @@ -158,9 +161,9 @@ impl ParseStage { config: &WasmTranslationConfig, ) -> CompilerResult { let wasm = wat::parse_bytes(bytes).into_diagnostic().wrap_err("failed to parse wat")?; - let module = wasm::translate(&wasm, config, session)?.unwrap_one_module(); + let component = wasm::translate(&wasm, config, session)?; - Ok(ParseOutput::Hir(module)) + Ok(ParseOutput::Hir(component.into())) } fn parse_masm_from_file(&self, path: &Path, session: &Session) -> CompilerResult { diff --git a/midenc-compile/src/stages/rewrite.rs b/midenc-compile/src/stages/rewrite.rs index 3b9c16fda..86b2b2e90 100644 --- a/midenc-compile/src/stages/rewrite.rs +++ b/midenc-compile/src/stages/rewrite.rs @@ -24,7 +24,7 @@ impl Stage for ApplyRewritesStage { input } LinkerInput::Hir(mut input) => { - log::debug!("applying rewrite passes to '{}'", input.name.as_str()); + log::debug!("applying rewrite passes to '{}'", input.name().as_str()); // Get all registered module rewrites and apply them in the order they appear let mut registered = vec![]; let matches = session.matches(); @@ -50,7 +50,10 @@ impl Stage for ApplyRewritesStage { // specific passes selected. let mut rewrites = masm::default_rewrites(registered.into_iter().map(|(_, r)| r), session); - rewrites.apply(&mut input, analyses, session)?; + + for (_, module) in input.modules_mut() { + rewrites.apply(module, analyses, session)?; + } log::debug!("rewrites successful"); LinkerInput::Hir(input) diff --git a/midenc-compile/src/stages/sema.rs b/midenc-compile/src/stages/sema.rs index 118222cf8..d3c1cdb58 100644 --- a/midenc-compile/src/stages/sema.rs +++ b/midenc-compile/src/stages/sema.rs @@ -1,3 +1,5 @@ +use midenc_hir::ComponentBuilder; + use super::*; /// This stage of compilation takes the output of the parsing @@ -27,20 +29,22 @@ impl Stage for SemanticAnalysisStage { session.emit(OutputMode::Text, &ast).into_diagnostic()?; let mut convert_to_hir = ast::ConvertAstToHir; let module = Box::new(convert_to_hir.convert(ast, analyses, session)?); - LinkerInput::Hir(module) + let component = + ComponentBuilder::new(&session.diagnostics).with_module(module)?.build(); + LinkerInput::Hir(component.into()) } - ParseOutput::Hir(module) if parse_only => { + ParseOutput::Hir(component) if parse_only => { log::debug!("skipping semantic analysis (parse-only=true)"); - session.emit(OutputMode::Text, &module).into_diagnostic()?; + session.emit(OutputMode::Text, &component).into_diagnostic()?; return Err(CompilerStopped.into()); } - ParseOutput::Hir(module) => { + ParseOutput::Hir(component) => { log::debug!( - "no semantic analysis required, '{}' is already valid hir", - module.name.as_str() + "no semantic analysis required, '{}' is already valid hir Compinent", + component.name() ); - session.emit(OutputMode::Text, &module).into_diagnostic()?; - LinkerInput::Hir(module) + session.emit(OutputMode::Text, &component).into_diagnostic()?; + LinkerInput::Hir(component) } ParseOutput::Masm(masm) if parse_only => { log::debug!("skipping semantic analysis (parse-only=true)"); From da54519399fae451b77f6e57806ac4ad2a548879 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 26 Nov 2024 17:08:55 +0200 Subject: [PATCH 02/26] chore: add stages scaffolding for lifting/lowering cross-context calls --- midenc-compile/src/lib.rs | 4 +++ .../src/stages/lift_cross_ctx/mod.rs | 28 +++++++++++++++ .../src/stages/lower_cross_ctx/mod.rs | 34 +++++++++++++++++++ midenc-compile/src/stages/mod.rs | 4 +++ 4 files changed, 70 insertions(+) create mode 100644 midenc-compile/src/stages/lift_cross_ctx/mod.rs create mode 100644 midenc-compile/src/stages/lower_cross_ctx/mod.rs diff --git a/midenc-compile/src/lib.rs b/midenc-compile/src/lib.rs index 2b40da2b7..474b28125 100644 --- a/midenc-compile/src/lib.rs +++ b/midenc-compile/src/lib.rs @@ -84,6 +84,8 @@ where }; let mut stages = ParseStage .next(SemanticAnalysisStage) + .next(LowerExportsCrossCtxStage) + .next(LiftImportsCrossCtxStage) .next_optional(ApplyRewritesStage) .collect(LinkerStage) .next(CodegenStage) @@ -108,6 +110,8 @@ fn compile_inputs( ) -> CompilerResult { let mut stages = ParseStage .next(SemanticAnalysisStage) + .next(LowerExportsCrossCtxStage) + .next(LiftImportsCrossCtxStage) .next_optional(ApplyRewritesStage) .collect(LinkerStage) .next(CodegenStage) diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs new file mode 100644 index 000000000..cdefca9e6 --- /dev/null +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -0,0 +1,28 @@ +//! Lifting the imports into the Miden ABI for the cross-context calls + +use midenc_hir::pass::AnalysisManager; +use midenc_session::Session; + +use super::LinkerInput; +use crate::{stage::Stage, CompilerResult}; + +/// Generates lifting for imports for the cross-context calls according to the Miden ABI. +/// +/// For every imported function call put the arguments on the stack or the advice provider and load +/// the result from the stack/advice provider into the memory according to the pointer after the +/// call. +pub struct LiftImportsCrossCtxStage; + +impl Stage for LiftImportsCrossCtxStage { + type Input = LinkerInput; + type Output = LinkerInput; + + fn run( + &mut self, + input: Self::Input, + _analyses: &mut AnalysisManager, + _session: &Session, + ) -> CompilerResult { + Ok(input) + } +} diff --git a/midenc-compile/src/stages/lower_cross_ctx/mod.rs b/midenc-compile/src/stages/lower_cross_ctx/mod.rs new file mode 100644 index 000000000..2e2278744 --- /dev/null +++ b/midenc-compile/src/stages/lower_cross_ctx/mod.rs @@ -0,0 +1,34 @@ +//! Lowering the exports for cross-context calls. + +use midenc_hir::pass::AnalysisManager; +use midenc_session::Session; + +use super::LinkerInput; +use crate::{stage::Stage, CompilerResult}; + +/// Generates lowering for exports for the cross-context calls according to the Miden ABI. +/// +/// For every exported function load the arguments from the stack or the advice provider and put +/// the result on the stack/advice provider. +/// +/// After this stage all exported functons are expected to be called using the Miden ABI for +/// cross-context calls, i.e. using the stack and the advice provider for arguments and results. +pub struct LowerExportsCrossCtxStage; + +// TODO: load the rodata into the memory in the lowering to ensure that the fresh context is +// correctly initialized +// TODO: Don't lower the note script's entry point + +impl Stage for LowerExportsCrossCtxStage { + type Input = LinkerInput; + type Output = LinkerInput; + + fn run( + &mut self, + input: Self::Input, + _analyses: &mut AnalysisManager, + _session: &Session, + ) -> CompilerResult { + Ok(input) + } +} diff --git a/midenc-compile/src/stages/mod.rs b/midenc-compile/src/stages/mod.rs index d60f86c54..bb81c2d8c 100644 --- a/midenc-compile/src/stages/mod.rs +++ b/midenc-compile/src/stages/mod.rs @@ -16,7 +16,9 @@ use crate::{CompilerResult, CompilerStopped}; mod assemble; mod codegen; +mod lift_cross_ctx; mod link; +mod lower_cross_ctx; mod parse; mod rewrite; mod sema; @@ -24,7 +26,9 @@ mod sema; pub use self::{ assemble::{Artifact, AssembleStage}, codegen::CodegenStage, + lift_cross_ctx::LiftImportsCrossCtxStage, link::{LinkerInput, LinkerOutput, LinkerStage}, + lower_cross_ctx::LowerExportsCrossCtxStage, parse::{ParseOutput, ParseStage}, rewrite::ApplyRewritesStage, sema::SemanticAnalysisStage, From c7bdec8304c67ffe37130eb475deec3632301cbf Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 26 Nov 2024 17:45:55 +0200 Subject: [PATCH 03/26] test: add cross-ctx-account and cross-ctx-note tests For testing cross-context lifting/lowering. --- .../expected/rust_sdk/cross_ctx_account.hir | 285 ++++++++++++ .../expected/rust_sdk/cross_ctx_account.masm | 424 +++++++++++++++++ .../expected/rust_sdk/cross_ctx_account.wat | 249 ++++++++++ .../expected/rust_sdk/cross_ctx_note.hir | 290 ++++++++++++ .../expected/rust_sdk/cross_ctx_note.masm | 434 ++++++++++++++++++ .../expected/rust_sdk/cross_ctx_note.wat | 260 +++++++++++ .../src/rust_masm_tests/rust_sdk.rs | 75 +++ .../rust-sdk/cross-ctx-account/.gitignore | 1 + .../rust-sdk/cross-ctx-account/Cargo.lock | 41 ++ .../rust-sdk/cross-ctx-account/Cargo.toml | 45 ++ .../cross-ctx-account/src/bindings.rs | 387 ++++++++++++++++ .../rust-sdk/cross-ctx-account/src/lib.rs | 36 ++ .../wit/cross-ctx-account.wit | 15 + .../rust-sdk/cross-ctx-note/.gitignore | 1 + .../rust-sdk/cross-ctx-note/Cargo.lock | 41 ++ .../rust-sdk/cross-ctx-note/Cargo.toml | 45 ++ .../rust-sdk/cross-ctx-note/src/bindings.rs | 414 +++++++++++++++++ .../rust-sdk/cross-ctx-note/src/lib.rs | 37 ++ .../cross-ctx-note/wit/cross-ctx-note.wit | 8 + 19 files changed, 3088 insertions(+) create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_account.hir create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_account.masm create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_account.wat create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_note.hir create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_note.masm create mode 100644 tests/integration/expected/rust_sdk/cross_ctx_note.wat create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/.gitignore create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.lock create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-account/wit/cross-ctx-account.wit create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/.gitignore create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.lock create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/lib.rs create mode 100644 tests/rust-apps-wasm/rust-sdk/cross-ctx-note/wit/cross-ctx-note.wit diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.hir b/tests/integration/expected/rust_sdk/cross_ctx_account.hir new file mode 100644 index 000000000..50b448b9e --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.hir @@ -0,0 +1,285 @@ +(component + ;; Component Imports + (lower ( (type (func (abi canon) (result u32)))) (#cross_ctx_account #miden_sdk_alloc::heap_base) + + ;; Modules + (module #cross_ctx_account + ;; Data Segments + (data (mut) (offset 1048576) 0x010000000100000001000000010000000100000001000000010000000100000002000000) + + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func #__wasm_call_ctors + (block 0 + (br (block 1))) + + (block 1 + (ret)) + ) + + (func #cross_ctx_account::bindings::__link_custom_section_describing_imports + + (block 0 + (br (block 1))) + + (block 1 + (ret)) + ) + + (func #__rust_alloc (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) + (let (v3 i32) (const.i32 1048612)) + (let (v4 i32) (exec #::alloc v3 v1 v0)) + (br (block 1 v4))) + + (block 1 (param v2 i32) + (ret v2)) + ) + + (func #__rust_realloc + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (const.i32 1048612)) + (let (v6 i32) (exec #::alloc v5 v2 v3)) + (let (v7 i1) (eq v6 0)) + (let (v8 i32) (zext v7)) + (let (v9 i1) (neq v8 0)) + (condbr v9 (block 2 v6) (block 3))) + + (block 1 (param v4 i32) + (ret v4)) + + (block 2 (param v21 i32) + (br (block 1 v21))) + + (block 3 + (let (v10 u32) (bitcast v1)) + (let (v11 u32) (bitcast v3)) + (let (v12 i1) (lt v10 v11)) + (let (v13 i32) (sext v12)) + (let (v14 i1) (neq v13 0)) + (let (v15 i32) (select v14 v1 v3)) + (let (v16 u32) (bitcast v15)) + (let (v17 u32) (bitcast v6)) + (let (v18 (ptr u8)) (inttoptr v17)) + (let (v19 u32) (bitcast v0)) + (let (v20 (ptr u8)) (inttoptr v19)) + (memcpy v20 v18 v16) + (br (block 2 v6))) + ) + + (func (export #miden:cross-ctx-account/foo@1.0.0#process-felt) + (param felt) (result felt) + (block 0 (param v0 felt) + (exec #wit_bindgen_rt::run_ctors_once) + (let (v2 i32) (const.i32 3)) + (let (v3 felt) (bitcast v2)) + (let (v4 felt) (add.unchecked v0 v3)) + (br (block 1 v4))) + + (block 1 (param v1 felt) + (ret v1)) + ) + + (func (export #cabi_realloc_wit_bindgen_0_28_0) + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (exec #wit_bindgen_rt::cabi_realloc v0 v1 v2 v3)) + (br (block 1 v5))) + + (block 1 (param v4 i32) + (ret v4)) + ) + + (func #wit_bindgen_rt::cabi_realloc + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i1) (neq v1 0)) + (condbr v5 (block 4) (block 5))) + + (block 1 (param v4 i32) + (ret v4)) + + (block 2 (param v19 i32) + (br (block 1 v19))) + + (block 3 (param v17 i32) + (let (v18 i1) (neq v17 0)) + (condbr v18 (block 2 v17) (block 7))) + + (block 4 + (let (v16 i32) (exec #__rust_realloc v0 v1 v2 v3)) + (br (block 3 v16))) + + (block 5 + (let (v6 i1) (eq v3 0)) + (let (v7 i32) (zext v6)) + (let (v8 i1) (neq v7 0)) + (condbr v8 (block 2 v2) (block 6))) + + (block 6 + (let (v9 i32) (const.i32 0)) + (let (v10 u32) (bitcast v9)) + (let (v11 u32) (add.checked v10 1048616)) + (let (v12 (ptr u8)) (inttoptr v11)) + (let (v13 u8) (load v12)) + (let (v14 i32) (zext v13)) + (let (v15 i32) (exec #__rust_alloc v3 v2)) + (br (block 3 v15))) + + (block 7 + (unreachable)) + ) + + (func #wit_bindgen_rt::run_ctors_once + (block 0 + (let (v0 i32) (const.i32 0)) + (let (v1 u32) (bitcast v0)) + (let (v2 u32) (add.checked v1 1048617)) + (let (v3 (ptr u8)) (inttoptr v2)) + (let (v4 u8) (load v3)) + (let (v5 i32) (zext v4)) + (let (v6 i1) (neq v5 0)) + (condbr v6 (block 2) (block 3))) + + (block 1 + (ret)) + + (block 2 + (br (block 1))) + + (block 3 + (exec #__wasm_call_ctors) + (let (v7 i32) (const.i32 0)) + (let (v8 i32) (const.i32 1)) + (let (v9 u32) (bitcast v8)) + (let (v10 u8) (trunc v9)) + (let (v11 u32) (bitcast v7)) + (let (v12 u32) (add.checked v11 1048617)) + (let (v13 (ptr u8)) (inttoptr v12)) + (store v13 v10) + (br (block 2))) + ) + + (func #::alloc + (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) + (let (v4 i32) (const.i32 0)) + (let (v5 i32) (const.i32 32)) + (let (v6 i32) (const.i32 32)) + (let (v7 u32) (bitcast v1)) + (let (v8 u32) (bitcast v6)) + (let (v9 i1) (gt v7 v8)) + (let (v10 i32) (sext v9)) + (let (v11 i1) (neq v10 0)) + (let (v12 i32) (select v11 v1 v5)) + (let (v13 u32) (popcnt v12)) + (let (v14 i32) (bitcast v13)) + (let (v15 i32) (const.i32 1)) + (let (v16 i1) (neq v14 v15)) + (let (v17 i32) (zext v16)) + (let (v18 i1) (neq v17 0)) + (condbr v18 (block 2) (block 3))) + + (block 1 (param v3 i32)) + + (block 2 + (unreachable)) + + (block 3 + (let (v19 i32) (const.i32 -2147483648)) + (let (v20 i32) (sub.wrapping v19 v12)) + (let (v21 u32) (bitcast v20)) + (let (v22 u32) (bitcast v2)) + (let (v23 i1) (lt v21 v22)) + (let (v24 i32) (sext v23)) + (let (v25 i1) (neq v24 0)) + (condbr v25 (block 2) (block 4))) + + (block 4 + (let (v26 i32) (const.i32 0)) + (let (v27 i32) (add.wrapping v12 v2)) + (let (v28 i32) (const.i32 -1)) + (let (v29 i32) (add.wrapping v27 v28)) + (let (v30 i32) (const.i32 0)) + (let (v31 i32) (sub.wrapping v30 v12)) + (let (v32 i32) (band v29 v31)) + (let (v33 u32) (bitcast v0)) + (let (v34 u32) (mod.unchecked v33 4)) + (assertz 250 v34) + (let (v35 (ptr i32)) (inttoptr v33)) + (let (v36 i32) (load v35)) + (let (v37 i1) (neq v36 0)) + (condbr v37 (block 5 v0 v32 v12 v26) (block 6))) + + (block 5 + (param v49 i32) + (param v55 i32) + (param v65 i32) + (param v68 i32) + (let (v48 i32) (const.i32 268435456)) + (let (v50 u32) (bitcast v49)) + (let (v51 u32) (mod.unchecked v50 4)) + (assertz 250 v51) + (let (v52 (ptr i32)) (inttoptr v50)) + (let (v53 i32) (load v52)) + (let (v54 i32) (sub.wrapping v48 v53)) + (let (v56 u32) (bitcast v54)) + (let (v57 u32) (bitcast v55)) + (let (v58 i1) (lt v56 v57)) + (let (v59 i32) (sext v58)) + (let (v60 i1) (neq v59 0)) + (condbr v60 (block 7 v68) (block 8))) + + (block 6 + (let (v38 u32) (exec (#intrinsics::mem #heap_base))) + (let (v39 u32) (memory.size)) + (let (v40 i32) (const.i32 16)) + (let (v41 u32) (bitcast v40)) + (let (v42 u32) (shl.wrapping v39 v41)) + (let (v43 u32) (add.wrapping v38 v42)) + (let (v44 i32) (bitcast v43)) + (let (v45 u32) (bitcast v0)) + (let (v46 u32) (mod.unchecked v45 4)) + (assertz 250 v46) + (let (v47 (ptr i32)) (inttoptr v45)) + (store v47 v44) + (br (block 5 v0 v32 v12 v26))) + + (block 7 (param v67 i32) + (ret v67)) + + (block 8 + (let (v61 i32) (add.wrapping v53 v55)) + (let (v62 u32) (bitcast v49)) + (let (v63 u32) (mod.unchecked v62 4)) + (assertz 250 v63) + (let (v64 (ptr i32)) (inttoptr v62)) + (store v64 v61) + (let (v66 i32) (add.wrapping v53 v65)) + (br (block 7 v66))) + ) + + (func (export #cabi_realloc) + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (exec #cabi_realloc_wit_bindgen_0_28_0 v0 v1 v2 v3)) + (br (block 1 v5))) + + (block 1 (param v4 i32) + (ret v4)) + ) + + ;; Imports + (func (import #intrinsics::mem #heap_base) (result u32)) + ) + + + ;; Component Exports + (lift (miden:cross-ctx-account/foo@1.0.0#process-felt) (#cross_ctx_account #miden:cross-ctx-account/foo@1.0.0#process-felt (func (abi wasm) (param (struct felt)) (result (struct felt))) ) +) diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.masm b/tests/integration/expected/rust_sdk/cross_ctx_account.masm new file mode 100644 index 000000000..5217b54af --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.masm @@ -0,0 +1,424 @@ +# mod cross_ctx_account + +use.intrinsics::mem + +proc."wit_bindgen_rt::cabi_realloc" + dup.1 + neq.0 + if.true + exec."__rust_realloc" + dup.0 + neq.0 + if.true + + else + push.0 assert + end + else + drop + drop + dup.1 + eq.0 + neq.0 + if.true + swap.1 drop + else + swap.1 + exec."__rust_alloc" + dup.0 + neq.0 + if.true + + else + push.0 assert + end + end + end +end + + +proc."wit_bindgen_rt::run_ctors_once" + push.0 + add.1048617 + u32assert + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + push.128 + u32and + neq.0 + if.true + + else + exec."__wasm_call_ctors" + push.1 + push.128 + u32and + push.0 + add.1048617 + u32assert + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + dup.2 + dup.2 + dup.2 + exec.::intrinsics::mem::load_sw + push.4294967040 + u32and + movup.5 + u32or + movdn.4 + exec.::intrinsics::mem::store_sw + end +end + + +proc."cross_ctx_account::bindings::__link_custom_section_describing_imports" + +end + + +proc."::alloc" + push.32 + dup.2 + push.32 + u32gt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + movup.3 + swap.1 + cdrop + dup.0 + u32popcnt + push.1 + neq + neq.0 + if.true + push.0 assert + else + push.2147483648 + dup.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + push.0 assert + else + dup.1 + dup.0 + u32mod.4 + assertz.err=250 + dup.1 + swap.1 + swap.4 + u32wrapping_add + push.4294967295 + u32wrapping_add + push.0 + dup.2 + u32wrapping_sub + u32and + push.0 + movup.4 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + neq.0 + if.true + dup.3 + dup.0 + u32mod.4 + assertz.err=250 + push.268435456 + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + dup.0 + swap.1 + swap.2 + swap.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + drop + movdn.3 + drop + drop + drop + else + swap.1 + drop + movup.3 + dup.1 + swap.1 + swap.3 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + swap.1 + u32mod.4 + assertz.err=250 + swap.1 + u32wrapping_add + end + else + dup.3 + exec.::intrinsics::mem::heap_base + dup.5 + exec.::intrinsics::mem::memory_size + push.16 + u32shl + movup.2 + swap.1 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + dup.0 + u32mod.4 + assertz.err=250 + swap.1 + u32mod.4 + assertz.err=250 + push.268435456 + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + dup.0 + swap.1 + swap.2 + swap.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + drop + movdn.3 + drop + drop + drop + else + swap.1 + drop + movup.3 + dup.1 + swap.1 + swap.3 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + swap.1 + u32mod.4 + assertz.err=250 + swap.1 + u32wrapping_add + end + end + end + end +end + + +proc."__rust_alloc" + push.1048612 + movup.2 + swap.1 + exec."::alloc" +end + + +proc."__rust_realloc" + push.1048612 + dup.4 + swap.2 + swap.4 + swap.1 + exec."::alloc" + dup.0 + eq.0 + neq.0 + if.true + movdn.3 drop drop drop + else + dup.1 + dup.4 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + swap.1 + swap.4 + swap.2 + swap.1 + cdrop + dup.2 + movup.2 + push.0 + dup.3 + gte.0 + while.true + dup.2 + dup.1 + push.1 + u32overflowing_madd + assertz + dup.2 + dup.2 + push.1 + u32overflowing_madd + assertz + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + push.128 + u32and + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + dup.2 + dup.2 + dup.2 + exec.::intrinsics::mem::load_sw + push.4294967040 + u32and + movup.5 + u32or + movdn.4 + exec.::intrinsics::mem::store_sw + u32wrapping_add.1 + dup.0 + dup.4 + u32gte + end + dropw + end +end + + +proc."__wasm_call_ctors" + +end + + +export.cabi_realloc + exec.cabi_realloc_wit_bindgen_0_28_0 +end + + +export.cabi_realloc_wit_bindgen_0_28_0 + exec."wit_bindgen_rt::cabi_realloc" +end + + +export."miden:cross-ctx-account/foo@1.0.0#process-felt" + exec."wit_bindgen_rt::run_ctors_once" + push.0.1 + dup.1 + dup.1 + push.4294967295.1 + exec.::std::math::u64::lt + assert + mul.4294967296 + add + add +end + + diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.wat b/tests/integration/expected/rust_sdk/cross_ctx_account.wat new file mode 100644 index 000000000..7e0aac95b --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.wat @@ -0,0 +1,249 @@ +(component + (type (;0;) + (instance + (type (;0;) (record (field "inner" float32))) + (export (;1;) "felt" (type (eq 0))) + ) + ) + (import "miden:base/core-types@1.0.0" (instance (;0;) (type 0))) + (type (;1;) + (instance + (type (;0;) (func (result s32))) + (export (;0;) "heap-base" (func (type 0))) + ) + ) + (import "miden:core-import/intrinsics-mem@1.0.0" (instance (;1;) (type 1))) + (type (;2;) + (instance + (type (;0;) (func (param "a" float32) (param "b" float32) (result float32))) + (export (;0;) "add" (func (type 0))) + (type (;1;) (func (param "a" u64) (result float32))) + (export (;1;) "from-u64-unchecked" (func (type 1))) + ) + ) + (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;2;) (type 2))) + (core module (;0;) + (type (;0;) (func (param i64) (result f32))) + (type (;1;) (func (param f32 f32) (result f32))) + (type (;2;) (func (result i32))) + (type (;3;) (func)) + (type (;4;) (func (param i32 i32) (result i32))) + (type (;5;) (func (param i32 i32 i32 i32) (result i32))) + (type (;6;) (func (param f32) (result f32))) + (type (;7;) (func (param i32 i32 i32) (result i32))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;1;) (type 1))) + (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;2;) (type 2))) + (func $__wasm_call_ctors (;3;) (type 3)) + (func $cross_ctx_account::bindings::__link_custom_section_describing_imports (;4;) (type 3)) + (func $__rust_alloc (;5;) (type 4) (param i32 i32) (result i32) + i32.const 1048612 + local.get 1 + local.get 0 + call $::alloc + ) + (func $__rust_realloc (;6;) (type 5) (param i32 i32 i32 i32) (result i32) + block ;; label = @1 + i32.const 1048612 + local.get 2 + local.get 3 + call $::alloc + local.tee 2 + i32.eqz + br_if 0 (;@1;) + local.get 2 + local.get 0 + local.get 1 + local.get 3 + local.get 1 + local.get 3 + i32.lt_u + select + memory.copy + end + local.get 2 + ) + (func $miden:cross-ctx-account/foo@1.0.0#process-felt (;7;) (type 6) (param f32) (result f32) + call $wit_bindgen_rt::run_ctors_once + local.get 0 + i64.const 1 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_add + ) + (func $cabi_realloc_wit_bindgen_0_28_0 (;8;) (type 5) (param i32 i32 i32 i32) (result i32) + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $wit_bindgen_rt::cabi_realloc + ) + (func $wit_bindgen_rt::cabi_realloc (;9;) (type 5) (param i32 i32 i32 i32) (result i32) + block ;; label = @1 + block ;; label = @2 + block ;; label = @3 + local.get 1 + br_if 0 (;@3;) + local.get 3 + i32.eqz + br_if 2 (;@1;) + i32.const 0 + i32.load8_u offset=1048616 + drop + local.get 3 + local.get 2 + call $__rust_alloc + local.set 2 + br 1 (;@2;) + end + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $__rust_realloc + local.set 2 + end + local.get 2 + br_if 0 (;@1;) + unreachable + end + local.get 2 + ) + (func $wit_bindgen_rt::run_ctors_once (;10;) (type 3) + block ;; label = @1 + i32.const 0 + i32.load8_u offset=1048617 + br_if 0 (;@1;) + call $__wasm_call_ctors + i32.const 0 + i32.const 1 + i32.store8 offset=1048617 + end + ) + (func $::alloc (;11;) (type 7) (param i32 i32 i32) (result i32) + (local i32 i32) + block ;; label = @1 + local.get 1 + i32.const 32 + local.get 1 + i32.const 32 + i32.gt_u + select + local.tee 1 + i32.popcnt + i32.const 1 + i32.ne + br_if 0 (;@1;) + i32.const -2147483648 + local.get 1 + i32.sub + local.get 2 + i32.lt_u + br_if 0 (;@1;) + i32.const 0 + local.set 3 + local.get 1 + local.get 2 + i32.add + i32.const -1 + i32.add + i32.const 0 + local.get 1 + i32.sub + i32.and + local.set 2 + block ;; label = @2 + local.get 0 + i32.load + br_if 0 (;@2;) + local.get 0 + call $miden_sdk_alloc::heap_base + memory.size + i32.const 16 + i32.shl + i32.add + i32.store + end + block ;; label = @2 + i32.const 268435456 + local.get 0 + i32.load + local.tee 4 + i32.sub + local.get 2 + i32.lt_u + br_if 0 (;@2;) + local.get 0 + local.get 4 + local.get 2 + i32.add + i32.store + local.get 4 + local.get 1 + i32.add + local.set 3 + end + local.get 3 + return + end + unreachable + ) + (func $cabi_realloc (;12;) (type 5) (param i32 i32 i32 i32) (result i32) + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $cabi_realloc_wit_bindgen_0_28_0 + ) + (table (;0;) 3 3 funcref) + (memory (;0;) 17) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "miden:cross-ctx-account/foo@1.0.0#process-felt" (func $miden:cross-ctx-account/foo@1.0.0#process-felt)) + (export "cabi_realloc_wit_bindgen_0_28_0" (func $cabi_realloc_wit_bindgen_0_28_0)) + (export "cabi_realloc" (func $cabi_realloc)) + (elem (;0;) (i32.const 1) func $cross_ctx_account::bindings::__link_custom_section_describing_imports $cabi_realloc) + (data $.rodata (;0;) (i32.const 1048576) "\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00") + ) + (alias export 2 "add" (func (;0;))) + (core func (;0;) (canon lower (func 0))) + (alias export 2 "from-u64-unchecked" (func (;1;))) + (core func (;1;) (canon lower (func 1))) + (core instance (;0;) + (export "add" (func 0)) + (export "from-u64-unchecked" (func 1)) + ) + (alias export 1 "heap-base" (func (;2;))) + (core func (;2;) (canon lower (func 2))) + (core instance (;1;) + (export "heap-base" (func 2)) + ) + (core instance (;2;) (instantiate 0 + (with "miden:core-import/intrinsics-felt@1.0.0" (instance 0)) + (with "miden:core-import/intrinsics-mem@1.0.0" (instance 1)) + ) + ) + (alias core export 2 "memory" (core memory (;0;))) + (alias core export 2 "cabi_realloc" (core func (;3;))) + (alias export 0 "felt" (type (;3;))) + (type (;4;) (func (param "input" 3) (result 3))) + (alias core export 2 "miden:cross-ctx-account/foo@1.0.0#process-felt" (core func (;4;))) + (func (;3;) (type 4) (canon lift (core func 4))) + (alias export 0 "felt" (type (;5;))) + (component (;0;) + (type (;0;) (record (field "inner" float32))) + (import "import-type-felt" (type (;1;) (eq 0))) + (import "import-type-felt0" (type (;2;) (eq 1))) + (type (;3;) (func (param "input" 2) (result 2))) + (import "import-func-process-felt" (func (;0;) (type 3))) + (export (;4;) "felt" (type 1)) + (type (;5;) (func (param "input" 4) (result 4))) + (export (;1;) "process-felt" (func 0) (func (type 5))) + ) + (instance (;3;) (instantiate 0 + (with "import-func-process-felt" (func 3)) + (with "import-type-felt" (type 5)) + (with "import-type-felt0" (type 3)) + ) + ) + (export (;4;) "miden:cross-ctx-account/foo@1.0.0" (instance 3)) +) \ No newline at end of file diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.hir b/tests/integration/expected/rust_sdk/cross_ctx_note.hir new file mode 100644 index 000000000..a1c9adcb0 --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.hir @@ -0,0 +1,290 @@ +(component + ;; Component Imports + (lower ((miden:cross-ctx-account/foo@1.0.0#process-felt) (type (func (abi wasm) (param (struct felt)) (result (struct felt))))) (#cross_ctx_note #cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import) + (lower ( (type (func (abi canon) (result u32)))) (#cross_ctx_note #miden_sdk_alloc::heap_base) + + ;; Modules + (module #cross_ctx_note + ;; Data Segments + (data (mut) (offset 1048576) 0x01000000010000000100000001000000010000000100000001000000010000000100000002000000) + + ;; Constants + (const (id 0) 0x00100000) + + ;; Global Variables + (global (export #__stack_pointer) (id 0) (type i32) (const 0)) + + ;; Functions + (func #__wasm_call_ctors + (block 0 + (br (block 1))) + + (block 1 + (ret)) + ) + + (func #cross_ctx_note::bindings::__link_custom_section_describing_imports + + (block 0 + (br (block 1))) + + (block 1 + (ret)) + ) + + (func #__rust_alloc (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) + (let (v3 i32) (const.i32 1048616)) + (let (v4 i32) (exec #::alloc v3 v1 v0)) + (br (block 1 v4))) + + (block 1 (param v2 i32) + (ret v2)) + ) + + (func #__rust_realloc + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (const.i32 1048616)) + (let (v6 i32) (exec #::alloc v5 v2 v3)) + (let (v7 i1) (eq v6 0)) + (let (v8 i32) (zext v7)) + (let (v9 i1) (neq v8 0)) + (condbr v9 (block 2 v6) (block 3))) + + (block 1 (param v4 i32) + (ret v4)) + + (block 2 (param v21 i32) + (br (block 1 v21))) + + (block 3 + (let (v10 u32) (bitcast v1)) + (let (v11 u32) (bitcast v3)) + (let (v12 i1) (lt v10 v11)) + (let (v13 i32) (sext v12)) + (let (v14 i1) (neq v13 0)) + (let (v15 i32) (select v14 v1 v3)) + (let (v16 u32) (bitcast v15)) + (let (v17 u32) (bitcast v6)) + (let (v18 (ptr u8)) (inttoptr v17)) + (let (v19 u32) (bitcast v0)) + (let (v20 (ptr u8)) (inttoptr v19)) + (memcpy v20 v18 v16) + (br (block 2 v6))) + ) + + (func (export #miden:base/note-script@1.0.0#note-script) + (block 0 + (exec #wit_bindgen_rt::run_ctors_once) + (let (v0 i32) (const.i32 7)) + (let (v1 felt) (bitcast v0)) + (let (v2 felt) (exec (#miden:cross-ctx-account/foo@1.0.0 #process-felt) v1)) + (let (v3 i32) (const.i32 10)) + (let (v4 felt) (bitcast v3)) + (assert.eq v4 v2) + (br (block 1))) + + (block 1 + (ret)) + ) + + (func (export #cabi_realloc_wit_bindgen_0_28_0) + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (exec #wit_bindgen_rt::cabi_realloc v0 v1 v2 v3)) + (br (block 1 v5))) + + (block 1 (param v4 i32) + (ret v4)) + ) + + (func #wit_bindgen_rt::cabi_realloc + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i1) (neq v1 0)) + (condbr v5 (block 4) (block 5))) + + (block 1 (param v4 i32) + (ret v4)) + + (block 2 (param v19 i32) + (br (block 1 v19))) + + (block 3 (param v17 i32) + (let (v18 i1) (neq v17 0)) + (condbr v18 (block 2 v17) (block 7))) + + (block 4 + (let (v16 i32) (exec #__rust_realloc v0 v1 v2 v3)) + (br (block 3 v16))) + + (block 5 + (let (v6 i1) (eq v3 0)) + (let (v7 i32) (zext v6)) + (let (v8 i1) (neq v7 0)) + (condbr v8 (block 2 v2) (block 6))) + + (block 6 + (let (v9 i32) (const.i32 0)) + (let (v10 u32) (bitcast v9)) + (let (v11 u32) (add.checked v10 1048620)) + (let (v12 (ptr u8)) (inttoptr v11)) + (let (v13 u8) (load v12)) + (let (v14 i32) (zext v13)) + (let (v15 i32) (exec #__rust_alloc v3 v2)) + (br (block 3 v15))) + + (block 7 + (unreachable)) + ) + + (func #wit_bindgen_rt::run_ctors_once + (block 0 + (let (v0 i32) (const.i32 0)) + (let (v1 u32) (bitcast v0)) + (let (v2 u32) (add.checked v1 1048621)) + (let (v3 (ptr u8)) (inttoptr v2)) + (let (v4 u8) (load v3)) + (let (v5 i32) (zext v4)) + (let (v6 i1) (neq v5 0)) + (condbr v6 (block 2) (block 3))) + + (block 1 + (ret)) + + (block 2 + (br (block 1))) + + (block 3 + (exec #__wasm_call_ctors) + (let (v7 i32) (const.i32 0)) + (let (v8 i32) (const.i32 1)) + (let (v9 u32) (bitcast v8)) + (let (v10 u8) (trunc v9)) + (let (v11 u32) (bitcast v7)) + (let (v12 u32) (add.checked v11 1048621)) + (let (v13 (ptr u8)) (inttoptr v12)) + (store v13 v10) + (br (block 2))) + ) + + (func #::alloc + (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) + (let (v4 i32) (const.i32 0)) + (let (v5 i32) (const.i32 32)) + (let (v6 i32) (const.i32 32)) + (let (v7 u32) (bitcast v1)) + (let (v8 u32) (bitcast v6)) + (let (v9 i1) (gt v7 v8)) + (let (v10 i32) (sext v9)) + (let (v11 i1) (neq v10 0)) + (let (v12 i32) (select v11 v1 v5)) + (let (v13 u32) (popcnt v12)) + (let (v14 i32) (bitcast v13)) + (let (v15 i32) (const.i32 1)) + (let (v16 i1) (neq v14 v15)) + (let (v17 i32) (zext v16)) + (let (v18 i1) (neq v17 0)) + (condbr v18 (block 2) (block 3))) + + (block 1 (param v3 i32)) + + (block 2 + (unreachable)) + + (block 3 + (let (v19 i32) (const.i32 -2147483648)) + (let (v20 i32) (sub.wrapping v19 v12)) + (let (v21 u32) (bitcast v20)) + (let (v22 u32) (bitcast v2)) + (let (v23 i1) (lt v21 v22)) + (let (v24 i32) (sext v23)) + (let (v25 i1) (neq v24 0)) + (condbr v25 (block 2) (block 4))) + + (block 4 + (let (v26 i32) (const.i32 0)) + (let (v27 i32) (add.wrapping v12 v2)) + (let (v28 i32) (const.i32 -1)) + (let (v29 i32) (add.wrapping v27 v28)) + (let (v30 i32) (const.i32 0)) + (let (v31 i32) (sub.wrapping v30 v12)) + (let (v32 i32) (band v29 v31)) + (let (v33 u32) (bitcast v0)) + (let (v34 u32) (mod.unchecked v33 4)) + (assertz 250 v34) + (let (v35 (ptr i32)) (inttoptr v33)) + (let (v36 i32) (load v35)) + (let (v37 i1) (neq v36 0)) + (condbr v37 (block 5 v0 v32 v12 v26) (block 6))) + + (block 5 + (param v49 i32) + (param v55 i32) + (param v65 i32) + (param v68 i32) + (let (v48 i32) (const.i32 268435456)) + (let (v50 u32) (bitcast v49)) + (let (v51 u32) (mod.unchecked v50 4)) + (assertz 250 v51) + (let (v52 (ptr i32)) (inttoptr v50)) + (let (v53 i32) (load v52)) + (let (v54 i32) (sub.wrapping v48 v53)) + (let (v56 u32) (bitcast v54)) + (let (v57 u32) (bitcast v55)) + (let (v58 i1) (lt v56 v57)) + (let (v59 i32) (sext v58)) + (let (v60 i1) (neq v59 0)) + (condbr v60 (block 7 v68) (block 8))) + + (block 6 + (let (v38 u32) (exec (#intrinsics::mem #heap_base))) + (let (v39 u32) (memory.size)) + (let (v40 i32) (const.i32 16)) + (let (v41 u32) (bitcast v40)) + (let (v42 u32) (shl.wrapping v39 v41)) + (let (v43 u32) (add.wrapping v38 v42)) + (let (v44 i32) (bitcast v43)) + (let (v45 u32) (bitcast v0)) + (let (v46 u32) (mod.unchecked v45 4)) + (assertz 250 v46) + (let (v47 (ptr i32)) (inttoptr v45)) + (store v47 v44) + (br (block 5 v0 v32 v12 v26))) + + (block 7 (param v67 i32) + (ret v67)) + + (block 8 + (let (v61 i32) (add.wrapping v53 v55)) + (let (v62 u32) (bitcast v49)) + (let (v63 u32) (mod.unchecked v62 4)) + (assertz 250 v63) + (let (v64 (ptr i32)) (inttoptr v62)) + (store v64 v61) + (let (v66 i32) (add.wrapping v53 v65)) + (br (block 7 v66))) + ) + + (func (export #cabi_realloc) + (param i32) (param i32) (param i32) (param i32) (result i32) + (block 0 (param v0 i32) (param v1 i32) (param v2 i32) (param v3 i32) + (let (v5 i32) (exec #cabi_realloc_wit_bindgen_0_28_0 v0 v1 v2 v3)) + (br (block 1 v5))) + + (block 1 (param v4 i32) + (ret v4)) + ) + + ;; Imports + (func (import #intrinsics::mem #heap_base) (result u32)) + (func (import #miden:cross-ctx-account/foo@1.0.0 #process-felt) + (param felt) (result felt)) + ) + + + ;; Component Exports + (lift (miden:base/note-script@1.0.0#note-script) (#cross_ctx_note #miden:base/note-script@1.0.0#note-script (func (abi wasm) ) ) +) diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.masm b/tests/integration/expected/rust_sdk/cross_ctx_note.masm new file mode 100644 index 000000000..6afb63166 --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.masm @@ -0,0 +1,434 @@ +# mod cross_ctx_note + +use.intrinsics::mem +use.miden:cross-ctx-account/foo@1.0.0 + +proc."cross_ctx_note::bindings::__link_custom_section_describing_imports" + +end + + +proc."wit_bindgen_rt::cabi_realloc" + dup.1 + neq.0 + if.true + exec."__rust_realloc" + dup.0 + neq.0 + if.true + + else + push.0 assert + end + else + drop + drop + dup.1 + eq.0 + neq.0 + if.true + swap.1 drop + else + swap.1 + exec."__rust_alloc" + dup.0 + neq.0 + if.true + + else + push.0 assert + end + end + end +end + + +proc."wit_bindgen_rt::run_ctors_once" + push.0 + add.1048621 + u32assert + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + push.128 + u32and + neq.0 + if.true + + else + exec."__wasm_call_ctors" + push.1 + push.128 + u32and + push.0 + add.1048621 + u32assert + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + dup.2 + dup.2 + dup.2 + exec.::intrinsics::mem::load_sw + push.4294967040 + u32and + movup.5 + u32or + movdn.4 + exec.::intrinsics::mem::store_sw + end +end + + +proc."::alloc" + push.32 + dup.2 + push.32 + u32gt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + movup.3 + swap.1 + cdrop + dup.0 + u32popcnt + push.1 + neq + neq.0 + if.true + push.0 assert + else + push.2147483648 + dup.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + push.0 assert + else + dup.1 + dup.0 + u32mod.4 + assertz.err=250 + dup.1 + swap.1 + swap.4 + u32wrapping_add + push.4294967295 + u32wrapping_add + push.0 + dup.2 + u32wrapping_sub + u32and + push.0 + movup.4 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + neq.0 + if.true + dup.3 + dup.0 + u32mod.4 + assertz.err=250 + push.268435456 + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + dup.0 + swap.1 + swap.2 + swap.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + drop + movdn.3 + drop + drop + drop + else + swap.1 + drop + movup.3 + dup.1 + swap.1 + swap.3 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + swap.1 + u32mod.4 + assertz.err=250 + swap.1 + u32wrapping_add + end + else + dup.3 + exec.::intrinsics::mem::heap_base + dup.5 + exec.::intrinsics::mem::memory_size + push.16 + u32shl + movup.2 + swap.1 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + dup.0 + u32mod.4 + assertz.err=250 + swap.1 + u32mod.4 + assertz.err=250 + push.268435456 + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + dup.0 + swap.1 + swap.2 + swap.1 + u32wrapping_sub + dup.3 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + if.true + drop + movdn.3 + drop + drop + drop + else + swap.1 + drop + movup.3 + dup.1 + swap.1 + swap.3 + u32wrapping_add + dup.2 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::store_sw + swap.1 + u32mod.4 + assertz.err=250 + swap.1 + u32wrapping_add + end + end + end + end +end + + +proc."__rust_alloc" + push.1048616 + movup.2 + swap.1 + exec."::alloc" +end + + +proc."__rust_realloc" + push.1048616 + dup.4 + swap.2 + swap.4 + swap.1 + exec."::alloc" + dup.0 + eq.0 + neq.0 + if.true + movdn.3 drop drop drop + else + dup.1 + dup.4 + u32lt + push.0 + push.0 + push.4294967294 + movup.2 + cdrop + u32or + neq.0 + swap.1 + swap.4 + swap.2 + swap.1 + cdrop + dup.2 + movup.2 + push.0 + dup.3 + gte.0 + while.true + dup.2 + dup.1 + push.1 + u32overflowing_madd + assertz + dup.2 + dup.2 + push.1 + u32overflowing_madd + assertz + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + exec.::intrinsics::mem::load_sw + push.128 + u32and + swap.1 + dup.0 + u32mod.16 + dup.0 + u32mod.4 + swap.1 + u32div.4 + movup.2 + u32div.16 + dup.2 + dup.2 + dup.2 + exec.::intrinsics::mem::load_sw + push.4294967040 + u32and + movup.5 + u32or + movdn.4 + exec.::intrinsics::mem::store_sw + u32wrapping_add.1 + dup.0 + dup.4 + u32gte + end + dropw + end +end + + +proc."__wasm_call_ctors" + +end + + +export.cabi_realloc + exec.cabi_realloc_wit_bindgen_0_28_0 +end + + +export.cabi_realloc_wit_bindgen_0_28_0 + exec."wit_bindgen_rt::cabi_realloc" +end + + +export."miden:base/note-script@1.0.0#note-script" + exec."wit_bindgen_rt::run_ctors_once" + push.0.7 + dup.1 + dup.1 + push.4294967295.1 + exec.::std::math::u64::lt + assert + mul.4294967296 + add + exec.::miden:cross-ctx-account/foo@1.0.0::"process-felt" + push.0.10 + dup.1 + dup.1 + push.4294967295.1 + exec.::std::math::u64::lt + assert + mul.4294967296 + add + assert_eq +end + + diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.wat b/tests/integration/expected/rust_sdk/cross_ctx_note.wat new file mode 100644 index 000000000..d88055d4e --- /dev/null +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.wat @@ -0,0 +1,260 @@ +(component + (type (;0;) + (instance + (type (;0;) (record (field "inner" float32))) + (export (;1;) "felt" (type (eq 0))) + ) + ) + (import "miden:base/core-types@1.0.0" (instance (;0;) (type 0))) + (alias export 0 "felt" (type (;1;))) + (type (;2;) + (instance + (alias outer 1 1 (type (;0;))) + (export (;1;) "felt" (type (eq 0))) + (type (;2;) (func (param "input" 1) (result 1))) + (export (;0;) "process-felt" (func (type 2))) + ) + ) + (import "miden:cross-ctx-account/foo@1.0.0" (instance (;1;) (type 2))) + (type (;3;) + (instance + (type (;0;) (func (result s32))) + (export (;0;) "heap-base" (func (type 0))) + ) + ) + (import "miden:core-import/intrinsics-mem@1.0.0" (instance (;2;) (type 3))) + (type (;4;) + (instance + (type (;0;) (func (param "a" u64) (result float32))) + (export (;0;) "from-u64-unchecked" (func (type 0))) + (type (;1;) (func (param "a" float32) (param "b" float32))) + (export (;1;) "assert-eq" (func (type 1))) + ) + ) + (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;3;) (type 4))) + (core module (;0;) + (type (;0;) (func (param i64) (result f32))) + (type (;1;) (func (param f32) (result f32))) + (type (;2;) (func (param f32 f32))) + (type (;3;) (func (result i32))) + (type (;4;) (func)) + (type (;5;) (func (param i32 i32) (result i32))) + (type (;6;) (func (param i32 i32 i32 i32) (result i32))) + (type (;7;) (func (param i32 i32 i32) (result i32))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0))) + (import "miden:cross-ctx-account/foo@1.0.0" "process-felt" (func $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import (;1;) (type 1))) + (import "miden:core-import/intrinsics-felt@1.0.0" "assert-eq" (func $miden_stdlib_sys::intrinsics::felt::extern_assert_eq (;2;) (type 2))) + (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;3;) (type 3))) + (func $__wasm_call_ctors (;4;) (type 4)) + (func $cross_ctx_note::bindings::__link_custom_section_describing_imports (;5;) (type 4)) + (func $__rust_alloc (;6;) (type 5) (param i32 i32) (result i32) + i32.const 1048616 + local.get 1 + local.get 0 + call $::alloc + ) + (func $__rust_realloc (;7;) (type 6) (param i32 i32 i32 i32) (result i32) + block ;; label = @1 + i32.const 1048616 + local.get 2 + local.get 3 + call $::alloc + local.tee 2 + i32.eqz + br_if 0 (;@1;) + local.get 2 + local.get 0 + local.get 1 + local.get 3 + local.get 1 + local.get 3 + i32.lt_u + select + memory.copy + end + local.get 2 + ) + (func $miden:base/note-script@1.0.0#note-script (;8;) (type 4) + call $wit_bindgen_rt::run_ctors_once + i64.const 7 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + call $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import + i64.const 10 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_assert_eq + ) + (func $cabi_realloc_wit_bindgen_0_28_0 (;9;) (type 6) (param i32 i32 i32 i32) (result i32) + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $wit_bindgen_rt::cabi_realloc + ) + (func $wit_bindgen_rt::cabi_realloc (;10;) (type 6) (param i32 i32 i32 i32) (result i32) + block ;; label = @1 + block ;; label = @2 + block ;; label = @3 + local.get 1 + br_if 0 (;@3;) + local.get 3 + i32.eqz + br_if 2 (;@1;) + i32.const 0 + i32.load8_u offset=1048620 + drop + local.get 3 + local.get 2 + call $__rust_alloc + local.set 2 + br 1 (;@2;) + end + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $__rust_realloc + local.set 2 + end + local.get 2 + br_if 0 (;@1;) + unreachable + end + local.get 2 + ) + (func $wit_bindgen_rt::run_ctors_once (;11;) (type 4) + block ;; label = @1 + i32.const 0 + i32.load8_u offset=1048621 + br_if 0 (;@1;) + call $__wasm_call_ctors + i32.const 0 + i32.const 1 + i32.store8 offset=1048621 + end + ) + (func $::alloc (;12;) (type 7) (param i32 i32 i32) (result i32) + (local i32 i32) + block ;; label = @1 + local.get 1 + i32.const 32 + local.get 1 + i32.const 32 + i32.gt_u + select + local.tee 1 + i32.popcnt + i32.const 1 + i32.ne + br_if 0 (;@1;) + i32.const -2147483648 + local.get 1 + i32.sub + local.get 2 + i32.lt_u + br_if 0 (;@1;) + i32.const 0 + local.set 3 + local.get 1 + local.get 2 + i32.add + i32.const -1 + i32.add + i32.const 0 + local.get 1 + i32.sub + i32.and + local.set 2 + block ;; label = @2 + local.get 0 + i32.load + br_if 0 (;@2;) + local.get 0 + call $miden_sdk_alloc::heap_base + memory.size + i32.const 16 + i32.shl + i32.add + i32.store + end + block ;; label = @2 + i32.const 268435456 + local.get 0 + i32.load + local.tee 4 + i32.sub + local.get 2 + i32.lt_u + br_if 0 (;@2;) + local.get 0 + local.get 4 + local.get 2 + i32.add + i32.store + local.get 4 + local.get 1 + i32.add + local.set 3 + end + local.get 3 + return + end + unreachable + ) + (func $cabi_realloc (;13;) (type 6) (param i32 i32 i32 i32) (result i32) + local.get 0 + local.get 1 + local.get 2 + local.get 3 + call $cabi_realloc_wit_bindgen_0_28_0 + ) + (table (;0;) 3 3 funcref) + (memory (;0;) 17) + (global $__stack_pointer (;0;) (mut i32) i32.const 1048576) + (export "memory" (memory 0)) + (export "miden:base/note-script@1.0.0#note-script" (func $miden:base/note-script@1.0.0#note-script)) + (export "cabi_realloc_wit_bindgen_0_28_0" (func $cabi_realloc_wit_bindgen_0_28_0)) + (export "cabi_realloc" (func $cabi_realloc)) + (elem (;0;) (i32.const 1) func $cross_ctx_note::bindings::__link_custom_section_describing_imports $cabi_realloc) + (data $.rodata (;0;) (i32.const 1048576) "\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00") + ) + (alias export 3 "from-u64-unchecked" (func (;0;))) + (core func (;0;) (canon lower (func 0))) + (alias export 3 "assert-eq" (func (;1;))) + (core func (;1;) (canon lower (func 1))) + (core instance (;0;) + (export "from-u64-unchecked" (func 0)) + (export "assert-eq" (func 1)) + ) + (alias export 1 "process-felt" (func (;2;))) + (core func (;2;) (canon lower (func 2))) + (core instance (;1;) + (export "process-felt" (func 2)) + ) + (alias export 2 "heap-base" (func (;3;))) + (core func (;3;) (canon lower (func 3))) + (core instance (;2;) + (export "heap-base" (func 3)) + ) + (core instance (;3;) (instantiate 0 + (with "miden:core-import/intrinsics-felt@1.0.0" (instance 0)) + (with "miden:cross-ctx-account/foo@1.0.0" (instance 1)) + (with "miden:core-import/intrinsics-mem@1.0.0" (instance 2)) + ) + ) + (alias core export 3 "memory" (core memory (;0;))) + (alias core export 3 "cabi_realloc" (core func (;4;))) + (type (;5;) (func)) + (alias core export 3 "miden:base/note-script@1.0.0#note-script" (core func (;5;))) + (func (;4;) (type 5) (canon lift (core func 5))) + (component (;0;) + (type (;0;) (func)) + (import "import-func-note-script" (func (;0;) (type 0))) + (type (;1;) (func)) + (export (;1;) "note-script" (func 0) (func (type 1))) + ) + (instance (;4;) (instantiate 0 + (with "import-func-note-script" (func 4)) + ) + ) + (export (;5;) "miden:base/note-script@1.0.0" (instance 4)) +) \ No newline at end of file diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index 3cc99949b..f2ac1d6b8 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -110,3 +110,78 @@ fn rust_sdk_p2id_note_script() { test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); } + +#[test] +fn rust_sdk_cross_ctx_account() { + let _ = env_logger::builder().is_test(true).try_init(); + let config = WasmTranslationConfig::default(); + let mut test = CompilerTest::rust_source_cargo_miden( + "../rust-apps-wasm/rust-sdk/cross-ctx-account", + config, + [], + ); + let artifact_name = test.artifact_name().to_string(); + test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); + test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); + test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); + let package = test.compiled_package(); + let lib = package.unwrap_library(); + let expected_module = "#anon::miden:cross-ctx-account/foo@1.0.0"; + let expected_function = "process-felt"; + let exports = lib + .exports() + .filter(|e| !e.module.to_string().starts_with("intrinsics")) + .map(|e| format!("{}::{}", e.module, e.name.as_str())) + .collect::>(); + dbg!(&exports); + assert!(lib.exports().any(|export| { + export.module.to_string() == expected_module && export.name.as_str() == expected_function + })); +} + +#[test] +fn rust_sdk_cross_ctx_note() { + // Build cross-ctx-account package + let args: Vec = [ + "cargo", + "miden", + "build", + "--manifest-path", + "../rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml", + "--release", + // Use the target dir of this test's cargo project to avoid issues running tests in parallel + // i.e. avoid using the same target dir as the basic-wallet test (see above) + "--target-dir", + "../rust-apps-wasm/rust-sdk/cross-ctx-note/target", + ] + .iter() + .map(|s| s.to_string()) + .collect(); + dbg!(env::current_dir().unwrap().display()); + let outputs = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm) + .expect("Failed to compile the cross-ctx-account package for cross-ctx-note"); + let masp_path: PathBuf = outputs.first().unwrap().clone(); + dbg!(&masp_path); + + let _ = env_logger::builder().is_test(true).try_init(); + + let config = WasmTranslationConfig::default(); + let mut test = CompilerTest::rust_source_cargo_miden( + "../rust-apps-wasm/rust-sdk/cross-ctx-note", + config, + [ + "-l".into(), + "std".into(), + "-l".into(), + "base".into(), + "--link-library".into(), + masp_path.into_os_string().into_string().unwrap().into(), + ], + ); + let artifact_name = test.artifact_name().to_string(); + test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); + test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); + test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); + + // TODO: run it in the VM (outpit is checked via assert_eq! in the note code) +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/.gitignore b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/.gitignore new file mode 100644 index 000000000..c41cc9e35 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.lock b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.lock new file mode 100644 index 000000000..7e6450c13 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.lock @@ -0,0 +1,41 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cross-ctx-account" +version = "0.1.0" +dependencies = [ + "miden", + "wit-bindgen-rt", +] + +[[package]] +name = "miden" +version = "0.0.7" +dependencies = [ + "miden-base-sys", + "miden-sdk-alloc", + "miden-stdlib-sys", +] + +[[package]] +name = "miden-base-sys" +version = "0.0.7" +dependencies = [ + "miden-stdlib-sys", +] + +[[package]] +name = "miden-sdk-alloc" +version = "0.0.7" + +[[package]] +name = "miden-stdlib-sys" +version = "0.0.7" + +[[package]] +name = "wit-bindgen-rt" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a37bd9274cb2d4754b915d624447ec0dce9105d174361841c0826efc79ceb9" diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml new file mode 100644 index 000000000..14dc3efbe --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "cross-ctx-account" +version = "0.1.0" +edition = "2021" + +[lib] +# Build this crate as a self-contained, C-style dynamic library +# This is required to emit the proper Wasm module type +crate-type = ["cdylib"] + +[dependencies] +# Miden SDK consists of a stdlib (intrinsic functions for VM ops, stdlib functions and types) +# and transaction kernel API for the Miden rollup +miden = { path = "../../../../sdk/sdk" } +wit-bindgen-rt = "0.28" + + +[profile.release] +# optimize the output for size +opt-level = "z" +# Explicitly disable panic infrastructure on Wasm, as +# there is no proper support for them anyway, and it +# ensures that panics do not pull in a bunch of standard +# library code unintentionally +panic = "abort" + +[profile.dev] +# Explicitly disable panic infrastructure on Wasm, as +# there is no proper support for them anyway, and it +# ensures that panics do not pull in a bunch of standard +# library code unintentionally +panic = "abort" +opt-level = 1 +debug-assertions = false +overflow-checks = false +debug = true + +# TODO: switch to miden table +[package.metadata.component] +package = "miden:cross-ctx-account" + +[package.metadata.component.target.dependencies] +"miden:base" = { path = "../wit-sdk/miden.wit" } +"miden:core-import" = { path = "../wit-sdk/miden-core-import.wit" } + diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs new file mode 100644 index 000000000..112e7c543 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs @@ -0,0 +1,387 @@ +#[allow(dead_code)] +pub mod miden { + #[allow(dead_code)] + pub mod base { + #[allow(dead_code, clippy::all)] + pub mod core_types { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + } + #[allow(dead_code)] + pub mod core_import { + #[allow(dead_code, clippy::all)] + pub mod intrinsics_mem { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + #[allow(dead_code, clippy::all)] + pub mod intrinsics_felt { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + pub fn eq(a: f32, b: f32) -> bool { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "eq"] + fn wit_import(_: f32, _: f32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: f32, _: f32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_f32(&a), _rt::as_f32(&b)); + _rt::bool_lift(ret as u8) + } + } + #[allow(unused_unsafe, clippy::all)] + pub fn from_u64_unchecked(a: u64) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u64-unchecked"] + fn wit_import(_: i64) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i64) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i64(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] + pub fn assert_eq(a: f32, b: f32) { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "assert-eq"] + fn wit_import(_: f32, _: f32); + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: f32, _: f32) { + unreachable!() + } + wit_import(_rt::as_f32(&a), _rt::as_f32(&b)); + } + } + } + #[allow(dead_code, clippy::all)] + pub mod stdlib_crypto_hashes_blake3 { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + #[allow(dead_code, clippy::all)] + pub mod account { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + #[allow(unused_unsafe, clippy::all)] + /// Get the id of the currently executing account + pub fn get_id() -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/account@1.0.0")] + extern "C" { + #[link_name = "get-id"] + fn wit_import() -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import() -> f32 { + unreachable!() + } + let ret = wit_import(); + ret + } + } + } + #[allow(dead_code, clippy::all)] + pub mod note { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + /// Get the inputs of the currently executed note + pub fn get_inputs(ptr: i32) -> i32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/note@1.0.0")] + extern "C" { + #[link_name = "get-inputs"] + fn wit_import(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&ptr)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] + /// Get the assets of the currently executing note + pub fn get_assets(ptr: i32) -> i32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/note@1.0.0")] + extern "C" { + #[link_name = "get-assets"] + fn wit_import(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&ptr)); + ret + } + } + } + #[allow(dead_code, clippy::all)] + pub mod tx { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + } +} +#[allow(dead_code)] +pub mod exports { + #[allow(dead_code)] + pub mod miden { + #[allow(dead_code)] + pub mod cross_ctx_account { + #[allow(dead_code, clippy::all)] + pub mod foo { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_process_felt_cabi(arg0: f32) -> f32 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::process_felt(miden::Felt { inner: arg0 }); + let miden::Felt { inner: inner1 } = result0; + _rt::as_f32(inner1) + } + pub trait Guest { + fn process_felt(input: miden::Felt) -> miden::Felt; + } + #[doc(hidden)] + macro_rules! __export_miden_cross_ctx_account_foo_1_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[export_name = + "miden:cross-ctx-account/foo@1.0.0#process-felt"] unsafe extern + "C" fn export_process_felt(arg0 : f32,) -> f32 { + $($path_to_types)*:: _export_process_felt_cabi::<$ty > (arg0) } + }; + }; + } + #[doc(hidden)] + pub(crate) use __export_miden_cross_ctx_account_foo_1_0_0_cabi; + } + } + } +} +mod _rt { + pub fn as_f32(t: T) -> f32 { + t.as_f32() + } + pub trait AsF32 { + fn as_f32(self) -> f32; + } + impl<'a, T: Copy + AsF32> AsF32 for &'a T { + fn as_f32(self) -> f32 { + (*self).as_f32() + } + } + impl AsF32 for f32 { + #[inline] + fn as_f32(self) -> f32 { + self as f32 + } + } + pub unsafe fn bool_lift(val: u8) -> bool { + if cfg!(debug_assertions) { + match val { + 0 => false, + 1 => true, + _ => panic!("invalid bool discriminant"), + } + } else { + val != 0 + } + } + pub fn as_i64(t: T) -> i64 { + t.as_i64() + } + pub trait AsI64 { + fn as_i64(self) -> i64; + } + impl<'a, T: Copy + AsI64> AsI64 for &'a T { + fn as_i64(self) -> i64 { + (*self).as_i64() + } + } + impl AsI64 for i64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + impl AsI64 for u64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + pub trait AsI32 { + fn as_i32(self) -> i32; + } + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen_rt::run_ctors_once(); + } +} +/// Generates `#[no_mangle]` functions to export the specified type as the +/// root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! export{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// export!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] +macro_rules! __export_foo_world_impl { + ($ty:ident) => { + self::export!($ty with_types_in self); + }; + ($ty:ident with_types_in $($path_to_types_root:tt)*) => { + $($path_to_types_root)*:: + exports::miden::cross_ctx_account::foo::__export_miden_cross_ctx_account_foo_1_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::miden::cross_ctx_account::foo); + }; +} +#[doc(inline)] +pub(crate) use __export_foo_world_impl as export; +#[cfg(target_arch = "wasm32")] +#[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-account@1.0.0:foo-world:encoded world"] +#[doc(hidden)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1390] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xee\x09\x01A\x02\x01\ +A\x11\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ +\x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ +count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ +inner\x01\x04\0\x03tag\x03\0\x09\x01r\x01\x05inner\x04\x04\0\x0acore-asset\x03\0\ +\x0b\x01r\x01\x05inner\x01\x04\0\x05nonce\x03\0\x0d\x01r\x01\x05inner\x04\x04\0\x0c\ +account-hash\x03\0\x0f\x01r\x01\x05inner\x04\x04\0\x0ablock-hash\x03\0\x11\x01r\x01\ +\x05inner\x04\x04\0\x0dstorage-value\x03\0\x13\x01r\x01\x05inner\x04\x04\0\x0cst\ +orage-root\x03\0\x15\x01r\x01\x05inner\x04\x04\0\x11account-code-root\x03\0\x17\x01\ +r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04\ +\0\x07note-id\x03\0\x1b\x01r\x01\x05inner\x01\x04\0\x09note-type\x03\0\x1d\x03\x01\ +\x1bmiden:base/core-types@1.0.0\x05\0\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\0\ +\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x08\x01@\x02\x01av\x01\ +bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01@\x01\ +\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\0\x04\0\x09\ +assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\ +\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\ +\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-ha\ +shes-blake3@1.0.0\x05\x03\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06\ +asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\ +\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\ +\x04\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\ +\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06\ +asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1\ +v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:c\ +ore-import/tx@1.0.0\x05\x06\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\x07\x04\ +\0\x04felt\x03\0\0\x01@\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\x02\x04\ +\x01!miden:cross-ctx-account/foo@1.0.0\x05\x08\x04\x01'miden:cross-ctx-account/f\ +oo-world@1.0.0\x04\0\x0b\x0f\x01\0\x09foo-world\x03\0\0\0G\x09producers\x01\x0cp\ +rocessed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs new file mode 100644 index 000000000..6add6ea3e --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs @@ -0,0 +1,36 @@ +// Do not link against libstd (i.e. anything defined in `std::`) +#![no_std] + +// However, we could still use some standard library types while +// remaining no-std compatible, if we uncommented the following lines: +// +extern crate alloc; +use alloc::vec::Vec; + +// Global allocator to use heap memory in no-std environment +#[global_allocator] +static ALLOC: miden::BumpAlloc = miden::BumpAlloc::new(); + +// Required for no-std crates +#[panic_handler] +fn my_panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +use bindings::exports::miden::cross_ctx_account::*; + +bindings::export!(MyFoo with_types_in bindings); + +mod bindings; + +use miden::{felt, Felt}; + +struct MyFoo; + +impl foo::Guest for MyFoo { + fn process_felt(input: Felt) -> Felt { + // TODO: load increment from the global variable to test rodata initialization on fresh + // context creation + input + felt!(1) + } +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/wit/cross-ctx-account.wit b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/wit/cross-ctx-account.wit new file mode 100644 index 000000000..3e6c4650c --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/wit/cross-ctx-account.wit @@ -0,0 +1,15 @@ +package miden:cross-ctx-account@1.0.0; + +use miden:base/core-types@1.0.0; + +interface foo { + use core-types.{felt}; + + process-felt: func(input: felt) -> felt; +} + +world foo-world { + include miden:core-import/all@1.0.0; + + export foo; +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/.gitignore b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/.gitignore new file mode 100644 index 000000000..c41cc9e35 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.lock b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.lock new file mode 100644 index 000000000..ff3b04cf3 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.lock @@ -0,0 +1,41 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cross-ctx-note" +version = "0.1.0" +dependencies = [ + "miden", + "wit-bindgen-rt", +] + +[[package]] +name = "miden" +version = "0.0.7" +dependencies = [ + "miden-base-sys", + "miden-sdk-alloc", + "miden-stdlib-sys", +] + +[[package]] +name = "miden-base-sys" +version = "0.0.7" +dependencies = [ + "miden-stdlib-sys", +] + +[[package]] +name = "miden-sdk-alloc" +version = "0.0.7" + +[[package]] +name = "miden-stdlib-sys" +version = "0.0.7" + +[[package]] +name = "wit-bindgen-rt" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a37bd9274cb2d4754b915d624447ec0dce9105d174361841c0826efc79ceb9" diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml new file mode 100644 index 000000000..03c508fad --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "cross-ctx-note" +version = "0.1.0" +edition = "2021" + +[lib] +# Build this crate as a self-contained, C-style dynamic library +# This is required to emit the proper Wasm module type +crate-type = ["cdylib"] + +[dependencies] +# Miden SDK consists of a stdlib (intrinsic functions for VM ops, stdlib functions and types) +# and transaction kernel API for the Miden rollup +miden = { path = "../../../../sdk/sdk" } +wit-bindgen-rt = "0.28" + + +[profile.release] +# optimize the output for size +opt-level = "z" +# Explicitly disable panic infrastructure on Wasm, as +# there is no proper support for them anyway, and it +# ensures that panics do not pull in a bunch of standard +# library code unintentionally +panic = "abort" + +[profile.dev] +# Explicitly disable panic infrastructure on Wasm, as +# there is no proper support for them anyway, and it +# ensures that panics do not pull in a bunch of standard +# library code unintentionally +panic = "abort" +opt-level = 1 +debug-assertions = false +overflow-checks = false +debug = true + +# TODO: switch to miden table +[package.metadata.component] +package = "miden:cross-ctx-note" + +[package.metadata.component.target.dependencies] +"miden:base" = { path = "../wit-sdk/miden.wit" } +"miden:core-import" = { path = "../wit-sdk/miden-core-import.wit" } +"miden:cross-ctx-account" = { path = "../cross-ctx-account/wit/cross-ctx-account.wit" } diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs new file mode 100644 index 000000000..479e29062 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs @@ -0,0 +1,414 @@ +#[allow(dead_code)] +pub mod miden { + #[allow(dead_code)] + pub mod base { + #[allow(dead_code, clippy::all)] + pub mod core_types { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + } + #[allow(dead_code)] + pub mod core_import { + #[allow(dead_code, clippy::all)] + pub mod intrinsics_mem { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + #[allow(dead_code, clippy::all)] + pub mod intrinsics_felt { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + pub fn eq(a: f32, b: f32) -> bool { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "eq"] + fn wit_import(_: f32, _: f32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: f32, _: f32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_f32(&a), _rt::as_f32(&b)); + _rt::bool_lift(ret as u8) + } + } + #[allow(unused_unsafe, clippy::all)] + pub fn from_u64_unchecked(a: u64) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u64-unchecked"] + fn wit_import(_: i64) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i64) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i64(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] + pub fn assert_eq(a: f32, b: f32) { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "assert-eq"] + fn wit_import(_: f32, _: f32); + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: f32, _: f32) { + unreachable!() + } + wit_import(_rt::as_f32(&a), _rt::as_f32(&b)); + } + } + } + #[allow(dead_code, clippy::all)] + pub mod stdlib_crypto_hashes_blake3 { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + #[allow(dead_code, clippy::all)] + pub mod account { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + #[allow(unused_unsafe, clippy::all)] + /// Get the id of the currently executing account + pub fn get_id() -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/account@1.0.0")] + extern "C" { + #[link_name = "get-id"] + fn wit_import() -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import() -> f32 { + unreachable!() + } + let ret = wit_import(); + ret + } + } + } + #[allow(dead_code, clippy::all)] + pub mod note { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + /// Get the inputs of the currently executed note + pub fn get_inputs(ptr: i32) -> i32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/note@1.0.0")] + extern "C" { + #[link_name = "get-inputs"] + fn wit_import(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&ptr)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] + /// Get the assets of the currently executing note + pub fn get_assets(ptr: i32) -> i32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:core-import/note@1.0.0")] + extern "C" { + #[link_name = "get-assets"] + fn wit_import(_: i32) -> i32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> i32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&ptr)); + ret + } + } + } + #[allow(dead_code, clippy::all)] + pub mod tx { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + } + } + #[allow(dead_code)] + pub mod cross_ctx_account { + #[allow(dead_code, clippy::all)] + pub mod foo { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + #[allow(unused_unsafe, clippy::all)] + pub fn process_felt(input: miden::Felt) -> miden::Felt { + unsafe { + let miden::Felt { inner: inner0 } = input; + #[cfg(target_arch = "wasm32")] + #[link(wasm_import_module = "miden:cross-ctx-account/foo@1.0.0")] + extern "C" { + #[link_name = "process-felt"] + fn wit_import(_: f32) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: f32) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_f32(inner0)); + miden::Felt { inner: ret } + } + } + } + } +} +#[allow(dead_code)] +pub mod exports { + #[allow(dead_code)] + pub mod miden { + #[allow(dead_code)] + pub mod base { + #[allow(dead_code, clippy::all)] + pub mod note_script { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_note_script_cabi() { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + T::note_script(); + } + pub trait Guest { + fn note_script(); + } + #[doc(hidden)] + macro_rules! __export_miden_base_note_script_1_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[export_name = + "miden:base/note-script@1.0.0#note-script"] unsafe extern "C" fn + export_note_script() { $($path_to_types)*:: + _export_note_script_cabi::<$ty > () } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_miden_base_note_script_1_0_0_cabi; + } + } + } +} +mod _rt { + pub fn as_f32(t: T) -> f32 { + t.as_f32() + } + pub trait AsF32 { + fn as_f32(self) -> f32; + } + impl<'a, T: Copy + AsF32> AsF32 for &'a T { + fn as_f32(self) -> f32 { + (*self).as_f32() + } + } + impl AsF32 for f32 { + #[inline] + fn as_f32(self) -> f32 { + self as f32 + } + } + pub unsafe fn bool_lift(val: u8) -> bool { + if cfg!(debug_assertions) { + match val { + 0 => false, + 1 => true, + _ => panic!("invalid bool discriminant"), + } + } else { + val != 0 + } + } + pub fn as_i64(t: T) -> i64 { + t.as_i64() + } + pub trait AsI64 { + fn as_i64(self) -> i64; + } + impl<'a, T: Copy + AsI64> AsI64 for &'a T { + fn as_i64(self) -> i64 { + (*self).as_i64() + } + } + impl AsI64 for i64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + impl AsI64 for u64 { + #[inline] + fn as_i64(self) -> i64 { + self as i64 + } + } + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + pub trait AsI32 { + fn as_i32(self) -> i32; + } + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + #[cfg(target_arch = "wasm32")] + pub fn run_ctors_once() { + wit_bindgen_rt::run_ctors_once(); + } +} +/// Generates `#[no_mangle]` functions to export the specified type as the +/// root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! export{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// export!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] +macro_rules! __export_cross_ctx_note_world_impl { + ($ty:ident) => { + self::export!($ty with_types_in self); + }; + ($ty:ident with_types_in $($path_to_types_root:tt)*) => { + $($path_to_types_root)*:: + exports::miden::base::note_script::__export_miden_base_note_script_1_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::miden::base::note_script); + }; +} +#[doc(inline)] +pub(crate) use __export_cross_ctx_note_world_impl as export; +#[cfg(target_arch = "wasm32")] +#[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-note@1.0.0:cross-ctx-note-world:encoded world"] +#[doc(hidden)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1466] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xaf\x0a\x01A\x02\x01\ +A\x13\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ +\x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ +count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ +inner\x01\x04\0\x03tag\x03\0\x09\x01r\x01\x05inner\x04\x04\0\x0acore-asset\x03\0\ +\x0b\x01r\x01\x05inner\x01\x04\0\x05nonce\x03\0\x0d\x01r\x01\x05inner\x04\x04\0\x0c\ +account-hash\x03\0\x0f\x01r\x01\x05inner\x04\x04\0\x0ablock-hash\x03\0\x11\x01r\x01\ +\x05inner\x04\x04\0\x0dstorage-value\x03\0\x13\x01r\x01\x05inner\x04\x04\0\x0cst\ +orage-root\x03\0\x15\x01r\x01\x05inner\x04\x04\0\x11account-code-root\x03\0\x17\x01\ +r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04\ +\0\x07note-id\x03\0\x1b\x01r\x01\x05inner\x01\x04\0\x09note-type\x03\0\x1d\x03\x01\ +\x1bmiden:base/core-types@1.0.0\x05\0\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\ +\x01\x04\0\x04felt\x03\0\0\x01@\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\ +\x02\x03\x01!miden:cross-ctx-account/foo@1.0.0\x05\x02\x01B\x02\x01@\0\0z\x04\0\x09\ +heap-base\x01\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x03\x01B\x08\x01\ +@\x02\x01av\x01bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\ +\x01\x01@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\ +\0\x04\0\x09assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\ +\x04\x01B\x02\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0a\ +result-ptrz\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdli\ +b-crypto-hashes-blake3@1.0.0\x05\x05\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06\ +asset2v\x06asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove\ +-asset\x01\0\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/acco\ +unt@1.0.0\x05\x06\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0a\ +get-assets\x01\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x07\x01B\x02\x01@\x0a\ +\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0\ +v\x0arecipient1v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\ +\x01\x1amiden:core-import/tx@1.0.0\x05\x08\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-s\ +cript\x01\0\x04\x01\x1cmiden:base/note-script@1.0.0\x05\x09\x04\x01/miden:cross-\ +ctx-note/cross-ctx-note-world@1.0.0\x04\0\x0b\x1a\x01\0\x14cross-ctx-note-world\x03\ +\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.216.0\x10wit-\ +bindgen-rust\x060.31.0"; +#[inline(never)] +#[doc(hidden)] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/lib.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/lib.rs new file mode 100644 index 000000000..fcfcfac67 --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/lib.rs @@ -0,0 +1,37 @@ +// Do not link against libstd (i.e. anything defined in `std::`) +#![no_std] + +// However, we could still use some standard library types while +// remaining no-std compatible, if we uncommented the following lines: +// +// extern crate alloc; +// use alloc::vec::Vec; + +// Global allocator to use heap memory in no-std environment +#[global_allocator] +static ALLOC: miden::BumpAlloc = miden::BumpAlloc::new(); + +// Required for no-std crates +#[panic_handler] +fn my_panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +bindings::export!(MyNote with_types_in bindings); + +mod bindings; + +use bindings::{ + exports::miden::base::note_script::Guest, miden::cross_ctx_account::foo::process_felt, +}; +use miden::*; + +struct MyNote; + +impl Guest for MyNote { + fn note_script() { + let input = felt!(7); + let output = process_felt(input); + assert_eq(output, felt!(10)); + } +} diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/wit/cross-ctx-note.wit b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/wit/cross-ctx-note.wit new file mode 100644 index 000000000..31d43b7bd --- /dev/null +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/wit/cross-ctx-note.wit @@ -0,0 +1,8 @@ +package miden:cross-ctx-note@1.0.0; + +world cross-ctx-note-world { + include miden:core-import/all@1.0.0; + + import miden:cross-ctx-account/foo@1.0.0; + export miden:base/note-script@1.0.0; +} From e86c402acf53152d38964c760d7b20131f8edc92 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Wed, 27 Nov 2024 16:43:20 +0200 Subject: [PATCH 04/26] fix: skip the assembler registration for the already registered module --- codegen/masm/src/masm/program.rs | 2 +- frontend-wasm/src/component/translator.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/masm/src/masm/program.rs b/codegen/masm/src/masm/program.rs index 0af20494d..e1205ccf3 100644 --- a/codegen/masm/src/masm/program.rs +++ b/codegen/masm/src/masm/program.rs @@ -263,7 +263,7 @@ impl Program { // Assemble library for module in self.library.modules.iter() { - if lib_modules.contains(&module.id.to_string()) { + if lib_modules.contains(&module.id.as_str().to_string()) { log::warn!( "module '{}' is already registered with the assembler as library's module, \ skipping", diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index ec81c290f..70e12d909 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -362,7 +362,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { dbg!(name); // The inline export does no have an interface name let interface = interface.unwrap_or_default(); - dbg!(&interface); + // dbg!(&interface); let export_name = InterfaceFunctionIdent::from_full(interface, name.clone()); let export = self.build_export_lifted_function(func, ty, options)?; component_builder.add_export(export_name, export); From ce9f1e0f84246df3f704ea7c43964c82d6b81347 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Wed, 27 Nov 2024 16:47:08 +0200 Subject: [PATCH 05/26] feature: add custom dependencies to `Executor` resolver, Temporarily switch to `from_u32_unchecked` to use `bitcast` and avoid checks. --- frontend-wasm/src/intrinsics/felt.rs | 5 + midenc-debug/src/exec/executor.rs | 46 +++-- sdk/stdlib-sys/src/intrinsics/felt.rs | 16 +- sdk/stdlib-sys/src/stdlib/mem.rs | 7 +- .../expected/rust_sdk/cross_ctx_account.masm | 11 +- .../expected/rust_sdk/cross_ctx_account.wat | 16 +- .../expected/rust_sdk/cross_ctx_note.masm | 18 +- .../expected/rust_sdk/cross_ctx_note.wat | 20 +-- .../miden_sdk_account_test.hir | 24 +-- .../miden_sdk_account_test.wat | 157 +++++++++--------- .../src/rust_masm_tests/rust_sdk.rs | 40 ++++- .../rust-sdk/basic-wallet/src/bindings.rs | 82 +++++---- .../cross-ctx-account/src/bindings.rs | 58 ++++--- .../rust-sdk/cross-ctx-account/src/lib.rs | 2 +- .../rust-sdk/cross-ctx-note/src/bindings.rs | 57 ++++--- .../rust-sdk/p2id-note/src/bindings.rs | 56 +++++-- .../rust-sdk/wit-sdk/miden-core-import.wit | 3 +- 17 files changed, 371 insertions(+), 247 deletions(-) diff --git a/frontend-wasm/src/intrinsics/felt.rs b/frontend-wasm/src/intrinsics/felt.rs index 057a84dfc..9f6437549 100644 --- a/frontend-wasm/src/intrinsics/felt.rs +++ b/frontend-wasm/src/intrinsics/felt.rs @@ -20,6 +20,11 @@ pub(crate) fn convert_felt_intrinsics( let inst = builder.ins().cast(args[0], Felt, span); vec![inst] } + "from_u32_unchecked" => { + assert_eq!(args.len(), 1, "{} takes exactly one argument", func_id); + let inst = builder.ins().bitcast(args[0], Felt, span); + vec![inst] + } "as_u64" => { assert_eq!(args.len(), 1, "{} takes exactly one argument", func_id); // we're casting to i64 instead of u64 because Wasm doesn't have u64 diff --git a/midenc-debug/src/exec/executor.rs b/midenc-debug/src/exec/executor.rs index 03284efd5..01051a04e 100644 --- a/midenc-debug/src/exec/executor.rs +++ b/midenc-debug/src/exec/executor.rs @@ -9,7 +9,7 @@ use miden_assembly::Library as CompiledLibrary; use miden_core::{Program, StackInputs, Word}; use miden_package::{ Dependency, DependencyName, DependencyResolution, DependencyResolver, LocalResolution, - MemDependencyResolverByDigest, SystemLibraryId, + MastArtifact, MemDependencyResolverByDigest, SystemLibraryId, }; use miden_processor::{ AdviceInputs, ContextId, ExecutionError, Felt, MastForest, MemAdviceProvider, Process, @@ -35,17 +35,23 @@ pub struct Executor { stack: StackInputs, advice: AdviceInputs, libraries: Vec>, + dependency_resolver: MemDependencyResolverByDigest, } impl Executor { /// Construct an executor with the given arguments on the operand stack pub fn new(args: Vec) -> Self { + let mut resolver = MemDependencyResolverByDigest::default(); + resolver.add(*STDLIB.digest(), STDLIB.clone().into()); + resolver.add(*BASE.digest(), BASE.clone().into()); Self { stack: StackInputs::new(args).expect("invalid stack inputs"), advice: AdviceInputs::default(), libraries: Default::default(), + dependency_resolver: resolver, } } + /// Construct the executor with the given inputs and adds dependencies from the given package pub fn for_package( package: &miden_package::Package, args: Vec, @@ -57,25 +63,35 @@ impl Executor { package.name, DisplayHex::new(&package.digest().as_bytes()) ); - let mut exec = Self::new(args); + exec.with_dependencies(&package.manifest.dependencies)?; + log::debug!("executor created"); + Ok(exec) + } - let mut resolver = MemDependencyResolverByDigest::default(); - resolver.add(*STDLIB.digest(), STDLIB.clone().into()); - resolver.add(*BASE.digest(), BASE.clone().into()); + /// Adds dependencies to the executor + pub fn with_dependencies(&mut self, dependencies: &[Dependency]) -> Result<&mut Self, Report> { + use midenc_hir::formatter::DisplayHex; - for dep in &package.manifest.dependencies { - match resolver.resolve(dep) { + for dep in dependencies { + match self.dependency_resolver.resolve(dep) { Some(resolution) => { log::debug!("dependency {:?} resolved to {:?}", dep, resolution); + log::debug!("loading library from package dependency: {:?}", dep); match resolution { DependencyResolution::Local(LocalResolution::Library(lib)) => { let library = lib.as_ref(); - log::debug!("loading library from package dependency: {:?}", dep); - exec.with_mast_forest(lib.mast_forest().clone()); + self.with_mast_forest(lib.mast_forest().clone()); } - DependencyResolution::Local(LocalResolution::Package(_)) => { - todo!("local package dependencies are not yet supported in executor") + DependencyResolution::Local(LocalResolution::Package(pkg)) => { + if let MastArtifact::Library(lib) = &pkg.mast { + self.with_mast_forest(lib.mast_forest().clone()); + } else { + Err(Report::msg(format!( + "expected package {} to contain library", + pkg.name + )))?; + } } } } @@ -85,10 +101,10 @@ impl Executor { log::debug!("executor created"); - Ok(exec) + Ok(self) } - /// Set the contents of memory for the shadow stack frame of the entrypoint + /// Set the contents of memory for the shadow stack frame of the entrypint pub fn with_advice_inputs(&mut self, advice: AdviceInputs) -> &mut Self { self.advice.extend(advice); self @@ -290,6 +306,10 @@ impl Executor { let out = self.execute(program, session); out.parse_result().expect("invalid result") } + + pub fn dependency_resolver_mut(&mut self) -> &mut MemDependencyResolverByDigest { + &mut self.dependency_resolver + } } #[track_caller] diff --git a/sdk/stdlib-sys/src/intrinsics/felt.rs b/sdk/stdlib-sys/src/intrinsics/felt.rs index a1abd3330..3fba8e493 100644 --- a/sdk/stdlib-sys/src/intrinsics/felt.rs +++ b/sdk/stdlib-sys/src/intrinsics/felt.rs @@ -7,6 +7,9 @@ extern "C" { #[link_name = "from-u64-unchecked"] fn extern_from_u64_unchecked(value: u64) -> Felt; + #[link_name = "from-u32-unchecked"] + fn extern_from_u32_unchecked(value: u32) -> Felt; + #[link_name = "as_u64"] fn extern_as_u64(felt: Felt) -> u64; @@ -68,9 +71,11 @@ extern "C" { macro_rules! felt { // Trigger a compile-time error if the value is not a constant ($value:literal) => {{ - const VALUE: u64 = $value as u64; - assert!(VALUE <= Felt::M, "Invalid Felt value, must be >= 0 and <= 2^64 - 2^32 + 1"); - Felt::from_u64_unchecked(VALUE) + // const VALUE: u64 = $value as u64; + // assert!(VALUE <= Felt::M, "Invalid Felt value, must be >= 0 and <= 2^64 - 2^32 + 1"); + // Temporarily switch to `from_u32_unchecked` to use `bitcast` and avoid checks. + const VALUE: u32 = $value as u32; + Felt::from_u32_unchecked(VALUE) }}; } @@ -94,6 +99,11 @@ impl Felt { unsafe { extern_from_u64_unchecked(value) } } + #[inline(always)] + pub fn from_u32_unchecked(value: u32) -> Self { + unsafe { extern_from_u32_unchecked(value) } + } + #[inline(always)] pub fn new(value: u64) -> Result { if value > Self::M { diff --git a/sdk/stdlib-sys/src/stdlib/mem.rs b/sdk/stdlib-sys/src/stdlib/mem.rs index e3a794dcb..ed5c1b9a2 100644 --- a/sdk/stdlib-sys/src/stdlib/mem.rs +++ b/sdk/stdlib-sys/src/stdlib/mem.rs @@ -3,7 +3,10 @@ extern crate alloc; use alloc::vec::Vec; -use crate::intrinsics::{Felt, Word}; +use crate::{ + felt, + intrinsics::{Felt, Word}, +}; #[link(wasm_import_module = "miden:core-import/stdlib-mem@1.0.0")] extern "C" { @@ -96,7 +99,7 @@ pub fn pipe_double_words_to_memory(num_words: Felt) -> (Word, Vec) { let end_ptr = unsafe { write_ptr.add(num_words_in_felts) }; // Place for returned C, B, A, write_ptr let mut ret_area = ::core::mem::MaybeUninit::::uninit(); - let zero = Felt::from_u64_unchecked(0); + let zero = felt!(0); unsafe { extern_pipe_double_words_to_memory( zero, diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.masm b/tests/integration/expected/rust_sdk/cross_ctx_account.masm index 5217b54af..4992ec4da 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_account.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.masm @@ -409,16 +409,7 @@ end export."miden:cross-ctx-account/foo@1.0.0#process-felt" - exec."wit_bindgen_rt::run_ctors_once" - push.0.1 - dup.1 - dup.1 - push.4294967295.1 - exec.::std::math::u64::lt - assert - mul.4294967296 - add - add + exec."wit_bindgen_rt::run_ctors_once" push.3 add end diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.wat b/tests/integration/expected/rust_sdk/cross_ctx_account.wat index 7e0aac95b..af61b90be 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_account.wat +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.wat @@ -17,13 +17,13 @@ (instance (type (;0;) (func (param "a" float32) (param "b" float32) (result float32))) (export (;0;) "add" (func (type 0))) - (type (;1;) (func (param "a" u64) (result float32))) - (export (;1;) "from-u64-unchecked" (func (type 1))) + (type (;1;) (func (param "a" u32) (result float32))) + (export (;1;) "from-u32-unchecked" (func (type 1))) ) ) (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;2;) (type 2))) (core module (;0;) - (type (;0;) (func (param i64) (result f32))) + (type (;0;) (func (param i32) (result f32))) (type (;1;) (func (param f32 f32) (result f32))) (type (;2;) (func (result i32))) (type (;3;) (func)) @@ -31,7 +31,7 @@ (type (;5;) (func (param i32 i32 i32 i32) (result i32))) (type (;6;) (func (param f32) (result f32))) (type (;7;) (func (param i32 i32 i32) (result i32))) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;1;) (type 1))) (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;2;) (type 2))) (func $__wasm_call_ctors (;3;) (type 3)) @@ -66,8 +66,8 @@ (func $miden:cross-ctx-account/foo@1.0.0#process-felt (;7;) (type 6) (param f32) (result f32) call $wit_bindgen_rt::run_ctors_once local.get 0 - i64.const 1 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 3 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked call $miden_stdlib_sys::intrinsics::felt::extern_add ) (func $cabi_realloc_wit_bindgen_0_28_0 (;8;) (type 5) (param i32 i32 i32 i32) (result i32) @@ -206,11 +206,11 @@ ) (alias export 2 "add" (func (;0;))) (core func (;0;) (canon lower (func 0))) - (alias export 2 "from-u64-unchecked" (func (;1;))) + (alias export 2 "from-u32-unchecked" (func (;1;))) (core func (;1;) (canon lower (func 1))) (core instance (;0;) (export "add" (func 0)) - (export "from-u64-unchecked" (func 1)) + (export "from-u32-unchecked" (func 1)) ) (alias export 1 "heap-base" (func (;2;))) (core func (;2;) (canon lower (func 2))) diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.masm b/tests/integration/expected/rust_sdk/cross_ctx_note.masm index 6afb63166..df8870dff 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.masm @@ -411,23 +411,9 @@ end export."miden:base/note-script@1.0.0#note-script" exec."wit_bindgen_rt::run_ctors_once" - push.0.7 - dup.1 - dup.1 - push.4294967295.1 - exec.::std::math::u64::lt - assert - mul.4294967296 - add + push.7 exec.::miden:cross-ctx-account/foo@1.0.0::"process-felt" - push.0.10 - dup.1 - dup.1 - push.4294967295.1 - exec.::std::math::u64::lt - assert - mul.4294967296 - add + push.10 assert_eq end diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.wat b/tests/integration/expected/rust_sdk/cross_ctx_note.wat index d88055d4e..e51fd9554 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.wat +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.wat @@ -25,15 +25,15 @@ (import "miden:core-import/intrinsics-mem@1.0.0" (instance (;2;) (type 3))) (type (;4;) (instance - (type (;0;) (func (param "a" u64) (result float32))) - (export (;0;) "from-u64-unchecked" (func (type 0))) + (type (;0;) (func (param "a" u32) (result float32))) + (export (;0;) "from-u32-unchecked" (func (type 0))) (type (;1;) (func (param "a" float32) (param "b" float32))) (export (;1;) "assert-eq" (func (type 1))) ) ) (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;3;) (type 4))) (core module (;0;) - (type (;0;) (func (param i64) (result f32))) + (type (;0;) (func (param i32) (result f32))) (type (;1;) (func (param f32) (result f32))) (type (;2;) (func (param f32 f32))) (type (;3;) (func (result i32))) @@ -41,7 +41,7 @@ (type (;5;) (func (param i32 i32) (result i32))) (type (;6;) (func (param i32 i32 i32 i32) (result i32))) (type (;7;) (func (param i32 i32 i32) (result i32))) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) (import "miden:cross-ctx-account/foo@1.0.0" "process-felt" (func $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import (;1;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "assert-eq" (func $miden_stdlib_sys::intrinsics::felt::extern_assert_eq (;2;) (type 2))) (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;3;) (type 3))) @@ -76,11 +76,11 @@ ) (func $miden:base/note-script@1.0.0#note-script (;8;) (type 4) call $wit_bindgen_rt::run_ctors_once - i64.const 7 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 7 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked call $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import - i64.const 10 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 10 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked call $miden_stdlib_sys::intrinsics::felt::extern_assert_eq ) (func $cabi_realloc_wit_bindgen_0_28_0 (;9;) (type 6) (param i32 i32 i32 i32) (result i32) @@ -217,12 +217,12 @@ (elem (;0;) (i32.const 1) func $cross_ctx_note::bindings::__link_custom_section_describing_imports $cabi_realloc) (data $.rodata (;0;) (i32.const 1048576) "\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00") ) - (alias export 3 "from-u64-unchecked" (func (;0;))) + (alias export 3 "from-u32-unchecked" (func (;0;))) (core func (;0;) (canon lower (func 0))) (alias export 3 "assert-eq" (func (;1;))) (core func (;1;) (canon lower (func 1))) (core instance (;0;) - (export "from-u64-unchecked" (func 0)) + (export "from-u32-unchecked" (func 0)) (export "assert-eq" (func 1)) ) (alias export 1 "process-felt" (func (;2;))) 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 d1c17a1fe..64a41d2dc 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 @@ -43,8 +43,8 @@ (block 0 (let (v1 felt) (const.felt 0)) (let (v2 felt) (exec #miden_base_sys::bindings::account::get_id)) - (let (v3 i64) (const.i64 42)) - (let (v4 felt) (cast v3)) + (let (v3 i32) (const.i32 42)) + (let (v4 felt) (bitcast v3)) (let (v5 felt) (add.unchecked v4 v2)) (br (block 1 v5))) @@ -63,14 +63,14 @@ (let (v7 i32) (band v5 v6)) (let (v8 (ptr i32)) (global.symbol #__stack_pointer)) (store v8 v7) - (let (v9 i64) (const.i64 1)) - (let (v10 felt) (cast v9)) - (let (v11 i64) (const.i64 2)) - (let (v12 felt) (cast v11)) - (let (v13 i64) (const.i64 3)) - (let (v14 felt) (cast v13)) - (let (v15 i64) (const.i64 4)) - (let (v16 felt) (cast v15)) + (let (v9 i32) (const.i32 1)) + (let (v10 felt) (bitcast v9)) + (let (v11 i32) (const.i32 2)) + (let (v12 felt) (bitcast v11)) + (let (v13 i32) (const.i32 3)) + (let (v14 felt) (bitcast v13)) + (let (v15 i32) (const.i32 4)) + (let (v16 felt) (bitcast v15)) (let (v17 u32) (bitcast v7)) (let (v18 u32) (add.checked v17 12)) (let (v19 u32) (mod.unchecked v18 4)) @@ -1300,8 +1300,8 @@ (assertz 250 v18) (let (v19 (ptr i32)) (inttoptr v17)) (let (v20 i32) (load v19)) - (let (v21 i64) (const.i64 0)) - (let (v22 felt) (cast v21)) + (let (v21 i32) (const.i32 0)) + (let (v22 felt) (bitcast v21)) (let (v23 i32) (const.i32 4)) (let (v24 u32) (bitcast v23)) (let (v25 i32) (shl.wrapping v12 v24)) diff --git a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat index af033ceaa..5dbc9cf43 100644 --- a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat +++ b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat @@ -1,5 +1,5 @@ (module $miden_sdk_account_test.wasm - (type (;0;) (func (param i64) (result f32))) + (type (;0;) (func (param i32) (result f32))) (type (;1;) (func (param f32 f32) (result f32))) (type (;2;) (func (param f32) (result i64))) (type (;3;) (func (param f32 f32) (result i32))) @@ -7,26 +7,26 @@ (type (;5;) (func (param f32))) (type (;6;) (func (param f32) (result f32))) (type (;7;) (func (param f32 f32))) - (type (;8;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) - (type (;9;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) - (type (;10;) (func (param f32 f32 f32 f32 f32 f32 f32 f32))) - (type (;11;) (func (result i32))) - (type (;12;) (func (result f32))) - (type (;13;) (func (param f32 f32 f32 f32 i32))) - (type (;14;) (func (param i32) (result i32))) - (type (;15;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) (result f32))) - (type (;16;) (func (param f32 i32 i32))) - (type (;17;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 i32 i32 i32))) - (type (;18;) (func (param i32 i32 i32) (result i32))) - (type (;19;) (func (param i32 i32))) - (type (;20;) (func (param i32 f32))) - (type (;21;) (func (param i32) (result f32))) + (type (;8;) (func (param i64) (result f32))) + (type (;9;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (type (;10;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (type (;11;) (func (param f32 f32 f32 f32 f32 f32 f32 f32))) + (type (;12;) (func (result i32))) + (type (;13;) (func (result f32))) + (type (;14;) (func (param f32 f32 f32 f32 i32))) + (type (;15;) (func (param i32) (result i32))) + (type (;16;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) (result f32))) + (type (;17;) (func (param f32 i32 i32))) + (type (;18;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 f32 i32 i32 i32))) + (type (;19;) (func (param i32 i32 i32) (result i32))) + (type (;20;) (func (param i32 i32))) + (type (;21;) (func (param i32 f32))) (type (;22;) (func (param i32 f32 f32 i32) (result f32))) (type (;23;) (func (param i32 i32) (result i32))) (type (;24;) (func (param i32))) (type (;25;) (func (param i32 i32 i32))) (type (;26;) (func)) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;1;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "as_u64" (func $miden_stdlib_sys::intrinsics::felt::extern_as_u64 (;2;) (type 2))) (import "miden:core-import/intrinsics-felt@1.0.0" "gt" (func $miden_stdlib_sys::intrinsics::felt::extern_gt (;3;) (type 3))) @@ -44,19 +44,20 @@ (import "miden:core-import/intrinsics-felt@1.0.0" "mul" (func $miden_stdlib_sys::intrinsics::felt::extern_mul (;15;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "div" (func $miden_stdlib_sys::intrinsics::felt::extern_div (;16;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "assert-eq" (func $miden_stdlib_sys::intrinsics::felt::extern_assert_eq (;17;) (type 7))) - (import "miden:core-import/intrinsics-felt@1.0.0" "neg" (func $miden_stdlib_sys::intrinsics::felt::extern_neg (;18;) (type 6))) - (import "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" "hash-one-to-one" (func $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_1to1 (;19;) (type 8))) - (import "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" "hash-two-to-one" (func $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_2to1 (;20;) (type 9))) - (import "miden:core-import/stdlib-crypto-dsa-rpo-falcon@1.0.0" "rpo-falcon512-verify" (func $miden_stdlib_sys::stdlib::crypto::dsa::extern_rpo_falcon512_verify (;21;) (type 10))) - (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;22;) (type 11))) - (import "miden:core-import/account@1.0.0" "get-id" (func $miden_base_sys::bindings::account::extern_account_get_id (;23;) (type 12))) - (import "miden:core-import/account@1.0.0" "add-asset" (func $miden_base_sys::bindings::account::extern_account_add_asset (;24;) (type 13))) - (import "miden:core-import/account@1.0.0" "remove-asset" (func $miden_base_sys::bindings::account::extern_account_remove_asset (;25;) (type 13))) - (import "miden:core-import/note@1.0.0" "get-inputs" (func $miden_base_sys::bindings::note::extern_note_get_inputs (;26;) (type 14))) - (import "miden:core-import/tx@1.0.0" "create-note" (func $miden_base_sys::bindings::tx::extern_tx_create_note (;27;) (type 15))) - (import "miden:core-import/stdlib-mem@1.0.0" "pipe-words-to-memory" (func $miden_stdlib_sys::stdlib::mem::extern_pipe_words_to_memory (;28;) (type 16))) - (import "miden:core-import/stdlib-mem@1.0.0" "pipe-double-words-to-memory" (func $miden_stdlib_sys::stdlib::mem::extern_pipe_double_words_to_memory (;29;) (type 17))) - (func $core::alloc::global::GlobalAlloc::alloc_zeroed (;30;) (type 18) (param i32 i32 i32) (result i32) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u64-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked (;18;) (type 8))) + (import "miden:core-import/intrinsics-felt@1.0.0" "neg" (func $miden_stdlib_sys::intrinsics::felt::extern_neg (;19;) (type 6))) + (import "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" "hash-one-to-one" (func $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_1to1 (;20;) (type 9))) + (import "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" "hash-two-to-one" (func $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_2to1 (;21;) (type 10))) + (import "miden:core-import/stdlib-crypto-dsa-rpo-falcon@1.0.0" "rpo-falcon512-verify" (func $miden_stdlib_sys::stdlib::crypto::dsa::extern_rpo_falcon512_verify (;22;) (type 11))) + (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;23;) (type 12))) + (import "miden:core-import/account@1.0.0" "get-id" (func $miden_base_sys::bindings::account::extern_account_get_id (;24;) (type 13))) + (import "miden:core-import/account@1.0.0" "add-asset" (func $miden_base_sys::bindings::account::extern_account_add_asset (;25;) (type 14))) + (import "miden:core-import/account@1.0.0" "remove-asset" (func $miden_base_sys::bindings::account::extern_account_remove_asset (;26;) (type 14))) + (import "miden:core-import/note@1.0.0" "get-inputs" (func $miden_base_sys::bindings::note::extern_note_get_inputs (;27;) (type 15))) + (import "miden:core-import/tx@1.0.0" "create-note" (func $miden_base_sys::bindings::tx::extern_tx_create_note (;28;) (type 16))) + (import "miden:core-import/stdlib-mem@1.0.0" "pipe-words-to-memory" (func $miden_stdlib_sys::stdlib::mem::extern_pipe_words_to_memory (;29;) (type 17))) + (import "miden:core-import/stdlib-mem@1.0.0" "pipe-double-words-to-memory" (func $miden_stdlib_sys::stdlib::mem::extern_pipe_double_words_to_memory (;30;) (type 18))) + (func $core::alloc::global::GlobalAlloc::alloc_zeroed (;31;) (type 19) (param i32 i32 i32) (result i32) block ;; label = @1 local.get 0 local.get 1 @@ -72,16 +73,16 @@ end local.get 1 ) - (func $get_wallet_magic_number (;31;) (type 12) (result f32) + (func $get_wallet_magic_number (;32;) (type 13) (result f32) (local f32) call $miden_base_sys::bindings::account::get_id local.set 0 - i64.const 42 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 42 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked local.get 0 call $miden_stdlib_sys::intrinsics::felt::extern_add ) - (func $test_add_asset (;32;) (type 12) (result f32) + (func $test_add_asset (;33;) (type 13) (result f32) (local i32 i32 f32 f32 f32) global.get $__stack_pointer local.tee 0 @@ -91,18 +92,18 @@ i32.and local.tee 1 global.set $__stack_pointer - i64.const 1 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 1 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked local.set 2 - i64.const 2 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 2 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked local.set 3 - i64.const 3 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 3 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked local.set 4 local.get 1 - i64.const 4 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 4 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked f32.store offset=12 local.get 1 local.get 4 @@ -125,7 +126,7 @@ global.set $__stack_pointer local.get 2 ) - (func $test_felt_ops_smoke (;33;) (type 1) (param f32 f32) (result f32) + (func $test_felt_ops_smoke (;34;) (type 1) (param f32 f32) (result f32) (local i64) local.get 0 call $miden_stdlib_sys::intrinsics::felt::extern_as_u64 @@ -214,7 +215,7 @@ local.get 0 call $miden_stdlib_sys::intrinsics::felt::extern_neg ) - (func $note_script (;34;) (type 12) (result f32) + (func $note_script (;35;) (type 13) (result f32) (local i32 f32 i32 i32) global.get $__stack_pointer i32.const 16 @@ -263,7 +264,7 @@ br 0 (;@1;) end ) - (func $test_blake3_hash_1to1 (;35;) (type 19) (param i32 i32) + (func $test_blake3_hash_1to1 (;36;) (type 20) (param i32 i32) (local i32 i32) global.get $__stack_pointer local.tee 2 @@ -316,7 +317,7 @@ local.get 2 global.set $__stack_pointer ) - (func $test_blake3_hash_2to1 (;36;) (type 19) (param i32 i32) + (func $test_blake3_hash_2to1 (;37;) (type 20) (param i32 i32) local.get 1 i32.load align=1 local.get 1 @@ -352,7 +353,7 @@ local.get 0 call $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_2to1 ) - (func $test_rpo_falcon512_verify (;37;) (type 19) (param i32 i32) + (func $test_rpo_falcon512_verify (;38;) (type 20) (param i32 i32) local.get 0 f32.load local.get 0 @@ -371,17 +372,17 @@ f32.load offset=12 call $miden_stdlib_sys::stdlib::crypto::dsa::extern_rpo_falcon512_verify ) - (func $test_pipe_words_to_memory (;38;) (type 20) (param i32 f32) + (func $test_pipe_words_to_memory (;39;) (type 21) (param i32 f32) local.get 0 local.get 1 call $miden_stdlib_sys::stdlib::mem::pipe_words_to_memory ) - (func $test_pipe_double_words_to_memory (;39;) (type 20) (param i32 f32) + (func $test_pipe_double_words_to_memory (;40;) (type 21) (param i32 f32) local.get 0 local.get 1 call $miden_stdlib_sys::stdlib::mem::pipe_double_words_to_memory ) - (func $test_remove_asset (;40;) (type 21) (param i32) (result f32) + (func $test_remove_asset (;41;) (type 0) (param i32) (result f32) (local i32 i32 f32) global.get $__stack_pointer local.tee 1 @@ -401,26 +402,26 @@ global.set $__stack_pointer local.get 3 ) - (func $test_create_note (;41;) (type 22) (param i32 f32 f32 i32) (result f32) + (func $test_create_note (;42;) (type 22) (param i32 f32 f32 i32) (result f32) local.get 0 local.get 1 local.get 2 local.get 3 call $miden_base_sys::bindings::tx::create_note ) - (func $__rust_alloc (;42;) (type 23) (param i32 i32) (result i32) + (func $__rust_alloc (;43;) (type 23) (param i32 i32) (result i32) i32.const 1048576 local.get 1 local.get 0 call $::alloc ) - (func $__rust_alloc_zeroed (;43;) (type 23) (param i32 i32) (result i32) + (func $__rust_alloc_zeroed (;44;) (type 23) (param i32 i32) (result i32) i32.const 1048576 local.get 1 local.get 0 call $core::alloc::global::GlobalAlloc::alloc_zeroed ) - (func $::alloc (;44;) (type 18) (param i32 i32 i32) (result i32) + (func $::alloc (;45;) (type 19) (param i32 i32 i32) (result i32) (local i32 i32) block ;; label = @1 local.get 1 @@ -488,10 +489,10 @@ end unreachable ) - (func $miden_base_sys::bindings::account::get_id (;45;) (type 12) (result f32) + (func $miden_base_sys::bindings::account::get_id (;46;) (type 13) (result f32) call $miden_base_sys::bindings::account::extern_account_get_id ) - (func $miden_base_sys::bindings::account::add_asset (;46;) (type 19) (param i32 i32) + (func $miden_base_sys::bindings::account::add_asset (;47;) (type 20) (param i32 i32) local.get 1 f32.load local.get 1 @@ -503,7 +504,7 @@ local.get 0 call $miden_base_sys::bindings::account::extern_account_add_asset ) - (func $miden_base_sys::bindings::account::remove_asset (;47;) (type 19) (param i32 i32) + (func $miden_base_sys::bindings::account::remove_asset (;48;) (type 20) (param i32 i32) local.get 1 f32.load local.get 1 @@ -515,7 +516,7 @@ local.get 0 call $miden_base_sys::bindings::account::extern_account_remove_asset ) - (func $miden_base_sys::bindings::note::get_inputs (;48;) (type 24) (param i32) + (func $miden_base_sys::bindings::note::get_inputs (;49;) (type 24) (param i32) (local i32 i32 i32) global.get $__stack_pointer i32.const 16 @@ -562,7 +563,7 @@ i32.add global.set $__stack_pointer ) - (func $miden_base_sys::bindings::tx::create_note (;49;) (type 22) (param i32 f32 f32 i32) (result f32) + (func $miden_base_sys::bindings::tx::create_note (;50;) (type 22) (param i32 f32 f32 i32) (result f32) local.get 0 f32.load local.get 0 @@ -583,7 +584,7 @@ f32.load offset=12 call $miden_base_sys::bindings::tx::extern_tx_create_note ) - (func $alloc::vec::Vec::with_capacity (;50;) (type 19) (param i32 i32) + (func $alloc::vec::Vec::with_capacity (;51;) (type 20) (param i32 i32) (local i32 i32) global.get $__stack_pointer i32.const 16 @@ -628,7 +629,7 @@ i32.add global.set $__stack_pointer ) - (func $alloc::raw_vec::RawVec::try_allocate_in (;51;) (type 25) (param i32 i32 i32) + (func $alloc::raw_vec::RawVec::try_allocate_in (;52;) (type 25) (param i32 i32 i32) (local i32) block ;; label = @1 block ;; label = @2 @@ -702,7 +703,7 @@ local.get 1 i32.store ) - (func $miden_stdlib_sys::stdlib::mem::pipe_words_to_memory (;52;) (type 20) (param i32 f32) + (func $miden_stdlib_sys::stdlib::mem::pipe_words_to_memory (;53;) (type 21) (param i32 f32) (local i32 i32) global.get $__stack_pointer local.tee 2 @@ -767,7 +768,7 @@ local.get 2 global.set $__stack_pointer ) - (func $miden_stdlib_sys::stdlib::mem::pipe_double_words_to_memory (;53;) (type 20) (param i32 f32) + (func $miden_stdlib_sys::stdlib::mem::pipe_double_words_to_memory (;54;) (type 21) (param i32 f32) (local i32 i32 i32 i32) global.get $__stack_pointer local.tee 2 @@ -790,8 +791,8 @@ local.get 3 i32.load offset=24 local.set 5 - i64.const 0 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u64_unchecked + i32.const 0 + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked local.tee 1 local.get 1 local.get 1 @@ -861,68 +862,68 @@ local.get 2 global.set $__stack_pointer ) - (func $dummy (;54;) (type 26)) - (func $__wasm_call_dtors (;55;) (type 26) + (func $dummy (;55;) (type 26)) + (func $__wasm_call_dtors (;56;) (type 26) call $dummy call $dummy ) - (func $alloc::raw_vec::handle_error (;56;) (type 19) (param i32 i32) + (func $alloc::raw_vec::handle_error (;57;) (type 20) (param i32 i32) unreachable ) - (func $get_wallet_magic_number.command_export (;57;) (type 12) (result f32) + (func $get_wallet_magic_number.command_export (;58;) (type 13) (result f32) call $get_wallet_magic_number call $__wasm_call_dtors ) - (func $test_add_asset.command_export (;58;) (type 12) (result f32) + (func $test_add_asset.command_export (;59;) (type 13) (result f32) call $test_add_asset call $__wasm_call_dtors ) - (func $test_felt_ops_smoke.command_export (;59;) (type 1) (param f32 f32) (result f32) + (func $test_felt_ops_smoke.command_export (;60;) (type 1) (param f32 f32) (result f32) local.get 0 local.get 1 call $test_felt_ops_smoke call $__wasm_call_dtors ) - (func $note_script.command_export (;60;) (type 12) (result f32) + (func $note_script.command_export (;61;) (type 13) (result f32) call $note_script call $__wasm_call_dtors ) - (func $test_blake3_hash_1to1.command_export (;61;) (type 19) (param i32 i32) + (func $test_blake3_hash_1to1.command_export (;62;) (type 20) (param i32 i32) local.get 0 local.get 1 call $test_blake3_hash_1to1 call $__wasm_call_dtors ) - (func $test_blake3_hash_2to1.command_export (;62;) (type 19) (param i32 i32) + (func $test_blake3_hash_2to1.command_export (;63;) (type 20) (param i32 i32) local.get 0 local.get 1 call $test_blake3_hash_2to1 call $__wasm_call_dtors ) - (func $test_rpo_falcon512_verify.command_export (;63;) (type 19) (param i32 i32) + (func $test_rpo_falcon512_verify.command_export (;64;) (type 20) (param i32 i32) local.get 0 local.get 1 call $test_rpo_falcon512_verify call $__wasm_call_dtors ) - (func $test_pipe_words_to_memory.command_export (;64;) (type 20) (param i32 f32) + (func $test_pipe_words_to_memory.command_export (;65;) (type 21) (param i32 f32) local.get 0 local.get 1 call $test_pipe_words_to_memory call $__wasm_call_dtors ) - (func $test_pipe_double_words_to_memory.command_export (;65;) (type 20) (param i32 f32) + (func $test_pipe_double_words_to_memory.command_export (;66;) (type 21) (param i32 f32) local.get 0 local.get 1 call $test_pipe_double_words_to_memory call $__wasm_call_dtors ) - (func $test_remove_asset.command_export (;66;) (type 21) (param i32) (result f32) + (func $test_remove_asset.command_export (;67;) (type 0) (param i32) (result f32) local.get 0 call $test_remove_asset call $__wasm_call_dtors ) - (func $test_create_note.command_export (;67;) (type 22) (param i32 f32 f32 i32) (result f32) + (func $test_create_note.command_export (;68;) (type 22) (param i32 f32 f32 i32) (result f32) local.get 0 local.get 1 local.get 2 diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index f2ac1d6b8..a1d734fb4 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -1,11 +1,17 @@ -use std::{collections::BTreeMap, env, path::PathBuf}; +use std::{collections::BTreeMap, env, path::PathBuf, sync::Arc}; use expect_test::expect_file; use miden_core::crypto::hash::RpoDigest; +use miden_package::Package; +use midenc_debug::Executor; use midenc_frontend_wasm::WasmTranslationConfig; -use midenc_hir::{InterfaceFunctionIdent, InterfaceIdent, Symbol}; +use midenc_hir::{ + FunctionIdent, Ident, InterfaceFunctionIdent, InterfaceIdent, SourceSpan, Symbol, +}; -use crate::{cargo_proj::project, compiler_test::sdk_crate_path, CompilerTest}; +use crate::{ + cargo_proj::project, compiler_test::sdk_crate_path, CompilerTest, CompilerTestBuilder, +}; #[test] fn account() { @@ -166,7 +172,8 @@ fn rust_sdk_cross_ctx_note() { let _ = env_logger::builder().is_test(true).try_init(); let config = WasmTranslationConfig::default(); - let mut test = CompilerTest::rust_source_cargo_miden( + + let mut builder = CompilerTestBuilder::rust_source_cargo_miden( "../rust-apps-wasm/rust-sdk/cross-ctx-note", config, [ @@ -175,13 +182,34 @@ fn rust_sdk_cross_ctx_note() { "-l".into(), "base".into(), "--link-library".into(), - masp_path.into_os_string().into_string().unwrap().into(), + masp_path.clone().into_os_string().into_string().unwrap().into(), ], ); + builder.with_entrypoint(FunctionIdent { + // module: Ident::new(Symbol::intern("miden:base/note-script@1.0.0"), SourceSpan::default()), + module: Ident::new(Symbol::intern("cross_ctx_note"), SourceSpan::default()), + // function: Ident::new(Symbol::intern("note-script"), SourceSpan::default()), + function: Ident::new( + Symbol::intern("miden:base/note-script@1.0.0#note-script"), + SourceSpan::default(), + ), + }); + let mut test = builder.build(); let artifact_name = test.artifact_name().to_string(); test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); - // TODO: run it in the VM (outpit is checked via assert_eq! in the note code) + // Run it in the VM (output is checked via assert_eq in the note code) + let package = test.compiled_package(); + + let mut exec = Executor::new(vec![]); + let account_package = + Arc::new(Package::read_from_bytes(std::fs::read(masp_path).unwrap()).unwrap()); + + exec.dependency_resolver_mut() + .add(account_package.digest(), account_package.into()); + exec.with_dependencies(&package.manifest.dependencies).unwrap(); + + let trace = exec.execute(&package.unwrap_program(), &test.session); } diff --git a/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs index f51ea85fa..55d58f5ce 100644 --- a/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs @@ -62,6 +62,25 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] + pub fn from_u32_unchecked(a: u32) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u32-unchecked"] + fn wit_import(_: i32) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] pub fn assert_eq(a: f32, b: f32) { unsafe { #[cfg(target_arch = "wasm32")] @@ -592,8 +611,8 @@ pub(crate) use __export_basic_wallet_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:basic-wallet@1.0.0:basic-wallet-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1863] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xbe\x0d\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1894] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xdd\x0d\x01A\x02\x01\ A\x17\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -605,36 +624,37 @@ orage-root\x03\0\x15\x01r\x01\x05inner\x04\x04\0\x11account-code-root\x03\0\x17\ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04\ \0\x07note-id\x03\0\x1b\x01r\x01\x05inner\x01\x04\0\x09note-type\x03\0\x1d\x03\x01\ \x1bmiden:base/core-types@1.0.0\x05\0\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\0\ -\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x08\x01@\x02\x01av\x01\ +\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x0a\x01@\x02\x01av\x01\ bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01@\x01\ -\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\0\x04\0\x09\ -assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\ -\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\ -\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-ha\ -shes-blake3@1.0.0\x05\x03\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06\ -asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\ -\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\ -\x04\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\ -\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06\ -asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1\ -v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:c\ -ore-import/tx@1.0.0\x05\x06\x02\x03\0\0\x0acore-asset\x02\x03\0\0\x03tag\x02\x03\ -\0\0\x09recipient\x02\x03\0\0\x09note-type\x02\x03\0\0\x04felt\x01B\x0e\x02\x03\x02\ -\x01\x07\x04\0\x0acore-asset\x03\0\0\x02\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\ -\x03\x02\x01\x09\x04\0\x09recipient\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-\ -type\x03\0\x06\x02\x03\x02\x01\x0b\x04\0\x04felt\x03\0\x08\x01@\x01\x0acore-asse\ -t\x01\x01\0\x04\0\x0dreceive-asset\x01\x0a\x01@\x04\x0acore-asset\x01\x03tag\x03\ -\x09note-type\x07\x09recipient\x05\x01\0\x04\0\x0asend-asset\x01\x0b\x04\x01%mid\ -en:basic-wallet/basic-wallet@1.0.0\x05\x0c\x01B\x14\x02\x03\x02\x01\x07\x04\0\x0a\ -core-asset\x03\0\0\x02\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\ -\x04\0\x09recipient\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\ -\x03\x02\x01\x0b\x04\0\x04felt\x03\0\x08\x01@\x02\x01a\x09\x01b\x09\0\x09\x04\0\x14\ -test-felt-intrinsics\x01\x0a\x01p}\x01@\x01\x05input\x0b\0\x0b\x04\0\x0btest-std\ -lib\x01\x0c\x01p\x09\x01@\x01\x05input\x0d\0\x0d\x04\0\x11process-list-felt\x01\x0e\ -\x01@\x01\x05input\x01\0\x01\x04\0\x12process-core-asset\x01\x0f\x04\x01\x1cmide\ -n:basic-wallet/aux@1.0.0\x05\x0d\x04\x01+miden:basic-wallet/basic-wallet-world@1\ -.0.0\x04\0\x0b\x18\x01\0\x12basic-wallet-world\x03\0\0\0G\x09producers\x01\x0cpr\ -ocessed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x12from-u3\ +2-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01\ +'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\ +\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-on\ +e-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\ +\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\ +\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-i\ +d\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03\ +ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:cor\ +e-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06\ +asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0are\ +cipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\ +\x06\x02\x03\0\0\x0acore-asset\x02\x03\0\0\x03tag\x02\x03\0\0\x09recipient\x02\x03\ +\0\0\x09note-type\x02\x03\0\0\x04felt\x01B\x0e\x02\x03\x02\x01\x07\x04\0\x0acore\ +-asset\x03\0\0\x02\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\ +\0\x09recipient\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\ +\x02\x01\x0b\x04\0\x04felt\x03\0\x08\x01@\x01\x0acore-asset\x01\x01\0\x04\0\x0dr\ +eceive-asset\x01\x0a\x01@\x04\x0acore-asset\x01\x03tag\x03\x09note-type\x07\x09r\ +ecipient\x05\x01\0\x04\0\x0asend-asset\x01\x0b\x04\x01%miden:basic-wallet/basic-\ +wallet@1.0.0\x05\x0c\x01B\x14\x02\x03\x02\x01\x07\x04\0\x0acore-asset\x03\0\0\x02\ +\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09recipient\x03\ +\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\x02\x01\x0b\x04\0\ +\x04felt\x03\0\x08\x01@\x02\x01a\x09\x01b\x09\0\x09\x04\0\x14test-felt-intrinsic\ +s\x01\x0a\x01p}\x01@\x01\x05input\x0b\0\x0b\x04\0\x0btest-stdlib\x01\x0c\x01p\x09\ +\x01@\x01\x05input\x0d\0\x0d\x04\0\x11process-list-felt\x01\x0e\x01@\x01\x05inpu\ +t\x01\0\x01\x04\0\x12process-core-asset\x01\x0f\x04\x01\x1cmiden:basic-wallet/au\ +x@1.0.0\x05\x0d\x04\x01+miden:basic-wallet/basic-wallet-world@1.0.0\x04\0\x0b\x18\ +\x01\0\x12basic-wallet-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0d\ +wit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs index 112e7c543..3e329ec99 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs @@ -62,6 +62,25 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] + pub fn from_u32_unchecked(a: u32) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u32-unchecked"] + fn wit_import(_: i32) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] pub fn assert_eq(a: f32, b: f32) { unsafe { #[cfg(target_arch = "wasm32")] @@ -349,8 +368,8 @@ pub(crate) use __export_foo_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-account@1.0.0:foo-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1390] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xee\x09\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1421] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x8d\x0a\x01A\x02\x01\ A\x11\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -362,24 +381,25 @@ orage-root\x03\0\x15\x01r\x01\x05inner\x04\x04\0\x11account-code-root\x03\0\x17\ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04\ \0\x07note-id\x03\0\x1b\x01r\x01\x05inner\x01\x04\0\x09note-type\x03\0\x1d\x03\x01\ \x1bmiden:base/core-types@1.0.0\x05\0\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\0\ -\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x08\x01@\x02\x01av\x01\ +\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x0a\x01@\x02\x01av\x01\ bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01@\x01\ -\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\0\x04\0\x09\ -assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\ -\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\ -\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-ha\ -shes-blake3@1.0.0\x05\x03\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06\ -asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\ -\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\ -\x04\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\ -\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06\ -asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1\ -v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:c\ -ore-import/tx@1.0.0\x05\x06\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\x07\x04\ -\0\x04felt\x03\0\0\x01@\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\x02\x04\ -\x01!miden:cross-ctx-account/foo@1.0.0\x05\x08\x04\x01'miden:cross-ctx-account/f\ -oo-world@1.0.0\x04\0\x0b\x0f\x01\0\x09foo-world\x03\0\0\0G\x09producers\x01\x0cp\ -rocessed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x12from-u3\ +2-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01\ +'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\ +\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-on\ +e-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\ +\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\ +\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-i\ +d\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03\ +ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:cor\ +e-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06\ +asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0are\ +cipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\ +\x06\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\x07\x04\0\x04felt\x03\0\0\x01@\ +\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\x02\x04\x01!miden:cross-ctx-ac\ +count/foo@1.0.0\x05\x08\x04\x01'miden:cross-ctx-account/foo-world@1.0.0\x04\0\x0b\ +\x0f\x01\0\x09foo-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-c\ +omponent\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs index 6add6ea3e..18b6e311c 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/lib.rs @@ -31,6 +31,6 @@ impl foo::Guest for MyFoo { fn process_felt(input: Felt) -> Felt { // TODO: load increment from the global variable to test rodata initialization on fresh // context creation - input + felt!(1) + input + felt!(3) } } diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs index 479e29062..57655e6ea 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs @@ -62,6 +62,25 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] + pub fn from_u32_unchecked(a: u32) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u32-unchecked"] + fn wit_import(_: i32) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] pub fn assert_eq(a: f32, b: f32) { unsafe { #[cfg(target_arch = "wasm32")] @@ -374,8 +393,8 @@ pub(crate) use __export_cross_ctx_note_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-note@1.0.0:cross-ctx-note-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1466] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xaf\x0a\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1497] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xce\x0a\x01A\x02\x01\ A\x13\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -389,24 +408,24 @@ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04 \x1bmiden:base/core-types@1.0.0\x05\0\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\ \x01\x04\0\x04felt\x03\0\0\x01@\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\ \x02\x03\x01!miden:cross-ctx-account/foo@1.0.0\x05\x02\x01B\x02\x01@\0\0z\x04\0\x09\ -heap-base\x01\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x03\x01B\x08\x01\ +heap-base\x01\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x03\x01B\x0a\x01\ @\x02\x01av\x01bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\ -\x01\x01@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\ -\0\x04\0\x09assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\ -\x04\x01B\x02\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0a\ -result-ptrz\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdli\ -b-crypto-hashes-blake3@1.0.0\x05\x05\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06\ -asset2v\x06asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove\ --asset\x01\0\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/acco\ -unt@1.0.0\x05\x06\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0a\ -get-assets\x01\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x07\x01B\x02\x01@\x0a\ -\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0\ -v\x0arecipient1v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\ -\x01\x1amiden:core-import/tx@1.0.0\x05\x08\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-s\ -cript\x01\0\x04\x01\x1cmiden:base/note-script@1.0.0\x05\x09\x04\x01/miden:cross-\ -ctx-note/cross-ctx-note-world@1.0.0\x04\0\x0b\x1a\x01\0\x14cross-ctx-note-world\x03\ -\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.216.0\x10wit-\ -bindgen-rust\x060.31.0"; +\x01\x01@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\ +\0\x12from-u32-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\ +\x04\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x04\x01B\x02\x01@\x09\x02\ +a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0f\ +hash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.\ +0\x05\x05\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresul\ +t-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\ +\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x06\x01B\x03\x01\ +@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1c\ +miden:core-import/note@1.0.0\x05\x07\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06\ +asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipi\ +ent2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/\ +tx@1.0.0\x05\x08\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-script\x01\0\x04\x01\x1cmid\ +en:base/note-script@1.0.0\x05\x09\x04\x01/miden:cross-ctx-note/cross-ctx-note-wo\ +rld@1.0.0\x04\0\x0b\x1a\x01\0\x14cross-ctx-note-world\x03\0\0\0G\x09producers\x01\ +\x0cprocessed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/p2id-note/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/p2id-note/src/bindings.rs index d687c2cf8..1b4f82243 100644 --- a/tests/rust-apps-wasm/rust-sdk/p2id-note/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/p2id-note/src/bindings.rs @@ -299,6 +299,25 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] + pub fn from_u32_unchecked(a: u32) -> f32 { + unsafe { + #[cfg(target_arch = "wasm32")] + #[link( + wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" + )] + extern "C" { + #[link_name = "from-u32-unchecked"] + fn wit_import(_: i32) -> f32; + } + #[cfg(not(target_arch = "wasm32"))] + fn wit_import(_: i32) -> f32 { + unreachable!() + } + let ret = wit_import(_rt::as_i32(&a)); + ret + } + } + #[allow(unused_unsafe, clippy::all)] pub fn assert_eq(a: f32, b: f32) { unsafe { #[cfg(target_arch = "wasm32")] @@ -585,8 +604,8 @@ pub(crate) use __export_p2id_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:p2id@1.0.0:p2id-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1896] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xe7\x0d\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1927] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x86\x0e\x01A\x02\x01\ A\x19\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -612,23 +631,24 @@ g\x03\0\x02\x02\x03\x02\x01\x03\x04\0\x09recipient\x03\0\x04\x02\x03\x02\x01\x04 st-stdlib\x01\x0c\x01p\x09\x01@\x01\x05input\x0d\0\x0d\x04\0\x11process-list-fel\ t\x01\x0e\x01@\x01\x05input\x01\0\x01\x04\0\x12process-core-asset\x01\x0f\x03\x01\ \x1cmiden:basic-wallet/aux@1.0.0\x05\x07\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\ -\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x08\x01B\x08\x01@\x02\x01a\ +\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x08\x01B\x0a\x01@\x02\x01a\ v\x01bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01\ -@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x02\x01av\x01bv\x01\0\x04\ -\0\x09assert-eq\x01\x03\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x09\x01\ -B\x02\x01@\x09\x02a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult\ --ptrz\x01\0\x04\0\x0fhash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-cryp\ -to-hashes-blake3@1.0.0\x05\x0a\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2\ -v\x06asset3v\x0aresult-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\ -\x01\0\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.\ -0.0\x05\x0b\x01B\x03\x01@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-\ -assets\x01\0\x03\x01\x1cmiden:core-import/note@1.0.0\x05\x0c\x01B\x02\x01@\x0a\x06\ -asset0v\x06asset1v\x06asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0a\ -recipient1v\x0arecipient2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1a\ -miden:core-import/tx@1.0.0\x05\x0d\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-script\x01\ -\0\x04\x01\x1cmiden:base/note-script@1.0.0\x05\x0e\x04\x01\x1bmiden:p2id/p2id-wo\ -rld@1.0.0\x04\0\x0b\x10\x01\0\x0ap2id-world\x03\0\0\0G\x09producers\x01\x0cproce\ -ssed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x12fr\ +om-u32-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\ +\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x09\x01B\x02\x01@\x09\x02a0z\x02\ +a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash\ +-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\ +\x0a\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptr\ +z\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06\ +get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x0b\x01B\x03\x01@\x01\ +\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden\ +:core-import/note@1.0.0\x05\x0c\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset\ +2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\ +\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.\ +0.0\x05\x0d\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-script\x01\0\x04\x01\x1cmiden:ba\ +se/note-script@1.0.0\x05\x0e\x04\x01\x1bmiden:p2id/p2id-world@1.0.0\x04\0\x0b\x10\ +\x01\0\x0ap2id-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-comp\ +onent\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit b/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit index 386d8b294..dfb49747a 100644 --- a/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit +++ b/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit @@ -13,6 +13,7 @@ interface intrinsics-felt { add: func(a: f32, b: f32) -> f32; eq: func(a: f32, b: f32) -> bool; from-u64-unchecked: func(a: u64) -> f32; + from-u32-unchecked: func(a: u32) -> f32; assert-eq: func(a: f32, b: f32); } @@ -74,4 +75,4 @@ world all { import note; import tx; -} \ No newline at end of file +} From 2b71558005231b35b7a53f8a167919e0fe0a5e44 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 29 Nov 2024 16:18:36 +0200 Subject: [PATCH 06/26] fix: relax the module name validation in ConvertHirToMasm to support the Wasm CM naming --- codegen/masm/src/convert.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/codegen/masm/src/convert.rs b/codegen/masm/src/convert.rs index c54390a78..22352bd0c 100644 --- a/codegen/masm/src/convert.rs +++ b/codegen/masm/src/convert.rs @@ -1,4 +1,4 @@ -use miden_assembly::LibraryPath; +use miden_assembly::{ast, LibraryNamespace, LibraryPath, Span}; use midenc_hir::{ self as hir, pass::{AnalysisManager, ConversionPass, ConversionResult}, @@ -108,8 +108,15 @@ impl ConversionPass for ConvertHirToMasm { } else { ModuleKind::Library }; - let name = LibraryPath::new(&module.name).unwrap_or_else(|err| { - panic!("invalid module name '{}': {}", module.name.as_str(), err) + let name = LibraryPath::new(&module.name).unwrap_or_else(|_| { + // Fallback for Wasm CM naming `namespace:package/interface@version` + LibraryPath::new_from_components( + LibraryNamespace::Anon, + [ast::Ident::new_unchecked(Span::new( + module.name.span, + module.name.as_str().into(), + ))], + ) }); let mut masm_module = Box::new(masm::Module::new(name, kind)); From 6ebfeae5bf2402b46fd69f28d2011345f1b6331e Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 29 Nov 2024 16:21:09 +0200 Subject: [PATCH 07/26] feature: add `ComponentBuilder::load`, `with_exports` to modify `Component`. --- hir/src/component/mod.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index b3b85db1c..3a25c72ea 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -141,7 +141,7 @@ impl formatter::PrettyPrint for ComponentImport { } /// A component export -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ComponentExport { /// The module function that is being exported pub function: FunctionIdent, @@ -366,6 +366,17 @@ impl<'a> ComponentBuilder<'a> { } } + /// Create a new [ComponentBuilder] from a [Component]. + pub fn load(component: Component, diagnostics: &'a DiagnosticsHandler) -> Self { + Self { + modules: component.modules, + imports: component.imports, + exports: component.exports, + entry: None, + diagnostics, + } + } + /// Set the entrypoint for the [Component] being built. #[inline] pub fn with_entrypoint(mut self, id: FunctionIdent) -> Self { @@ -383,6 +394,15 @@ impl<'a> ComponentBuilder<'a> { self.add_module(module).map(|_| self) } + /// Replace the exports of the [Component] being built. + pub fn with_exports( + mut self, + exports: BTreeMap, + ) -> Self { + self.exports = exports; + self + } + /// Add `module` to the set of modules to link into the final [Component] /// /// Returns `Err` if a module with the same name already exists @@ -413,14 +433,22 @@ impl<'a> ComponentBuilder<'a> { } } + /// Add an import to the [Component] being built. Overwrites any existing import with the same + /// `function_id`. pub fn add_import(&mut self, function_id: FunctionIdent, import: ComponentImport) { self.imports.insert(function_id, import); } + /// Add an export to the [Component] being built. Overwrites any existing export with the same + /// `name`. pub fn add_export(&mut self, name: InterfaceFunctionIdent, export: ComponentExport) { self.exports.insert(name, export); } + pub fn exports(&self) -> &BTreeMap { + &self.exports + } + pub fn build(self) -> Component { assert!(!self.modules.is_empty(), "Cannot build a component with no modules"); Component { From 459f5aa1e241573c3d0303e8d8efdf158ba629ec Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 29 Nov 2024 16:22:30 +0200 Subject: [PATCH 08/26] feature: draft `LowerExportsCrossCtxStage` implementation with a lot of hardcoded shortcuts. --- .../src/stages/lower_cross_ctx/mod.rs | 134 +++++++++++++++++- .../expected/rust_sdk/cross_ctx_account.masm | 9 ++ 2 files changed, 136 insertions(+), 7 deletions(-) diff --git a/midenc-compile/src/stages/lower_cross_ctx/mod.rs b/midenc-compile/src/stages/lower_cross_ctx/mod.rs index 2e2278744..4d1f67dcb 100644 --- a/midenc-compile/src/stages/lower_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lower_cross_ctx/mod.rs @@ -1,15 +1,23 @@ //! Lowering the exports for cross-context calls. -use midenc_hir::pass::AnalysisManager; -use midenc_session::Session; +use std::collections::BTreeMap; + +use midenc_hir::{ + diagnostics::Severity, pass::AnalysisManager, types::Abi::Canonical, AbiParam, CallConv, + ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, Linkage, + Signature, SourceSpan, Type, +}; +use midenc_session::{DiagnosticsHandler, Session}; use super::LinkerInput; use crate::{stage::Stage, CompilerResult}; /// Generates lowering for exports for the cross-context calls according to the Miden ABI. /// -/// For every exported function load the arguments from the stack or the advice provider and put -/// the result on the stack/advice provider. +/// For each component export ensure a module for each interface that has a lowering +/// function, i.e. a function that takes parameters according to the cross-context Miden +/// ABI, lifts them to the Wasm CABI, calls the core Wasm module exported function, +/// lowers the results to the cross-context Miden ABI /// /// After this stage all exported functons are expected to be called using the Miden ABI for /// cross-context calls, i.e. using the stack and the advice provider for arguments and results. @@ -17,7 +25,9 @@ pub struct LowerExportsCrossCtxStage; // TODO: load the rodata into the memory in the lowering to ensure that the fresh context is // correctly initialized -// TODO: Don't lower the note script's entry point + +// TODO: swap `lift` and `lower` in the component import/export pretty-printing to sync with +// this stage's terminology (an export is lowered, an import is lifted) impl Stage for LowerExportsCrossCtxStage { type Input = LinkerInput; @@ -27,8 +37,118 @@ impl Stage for LowerExportsCrossCtxStage { &mut self, input: Self::Input, _analyses: &mut AnalysisManager, - _session: &Session, + session: &Session, ) -> CompilerResult { - Ok(input) + let component = if let LinkerInput::Hir(component) = input { + component + } else { + return Ok(input); + }; + + let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); + + let mut lowered_exports: BTreeMap = + BTreeMap::new(); + let exports = component_builder.exports().clone(); + for (id, export) in exports.into_iter() { + if let Canonical = export.function_ty.abi() { + // skip exports that are already lowered + lowered_exports.insert(id, export); + continue; + } + if let Some(entrypoint) = &session.options.entrypoint { + // skip the entrypoint + let export_core_func = format!( + "{}::{}", + export.function.module.as_str(), + export.function.function.as_str() + ); + if entrypoint == &export_core_func { + lowered_exports.insert(id, export); + continue; + } + } + let new_export = generate_lowering_function( + &mut component_builder, + id, + export, + &session.diagnostics, + )?; + lowered_exports.insert(id, new_export); + } + + let component_builder = component_builder.with_exports(lowered_exports); + + let component = component_builder.build(); + Ok(LinkerInput::Hir(component.into())) + } +} + +fn generate_lowering_function( + component_builder: &mut ComponentBuilder, + export_id: InterfaceFunctionIdent, + export: ComponentExport, + diagnostics: &DiagnosticsHandler, +) -> CompilerResult { + // So far we only hardcoded the lowering for the process-felt function + if export_id.interface.to_string() != "miden:cross-ctx-account/foo@1.0.0" + && export_id.function.as_str() != "process-felt" + { + return Ok(export); + } + // get or create the module for the interface + let module_id = export_id.interface.full_name; + let mut module_builder = component_builder.module(module_id); + // TODO: analyze the signature and speculate what cross-context Miden ABI signature we need to export. + // For now just assume passing <16 felts and returning 1 and copy the signature + let cc_export_sig = Signature { + params: vec![AbiParam::new(Type::Felt)], + results: vec![AbiParam::new(Type::Felt)], + // TODO: add CallConv::CrossCtx + cc: CallConv::SystemV, + linkage: Linkage::External, + }; + let mut builder = module_builder.function(export_id.function, cc_export_sig.clone())?; + let entry = builder.current_block(); + let params = builder.block_params(entry).to_vec(); + // TODO: lift the params from the cross-context Miden ABI to the Wasm CABI + + // TODO: put the core function signature in the export + let core_sig = Signature { + params: vec![AbiParam::new(Type::Felt)], + results: vec![AbiParam::new(Type::Felt)], + cc: CallConv::SystemV, + linkage: Linkage::Internal, + }; + let dfg = builder.data_flow_graph_mut(); + // import the Wasm core function + if dfg.get_import(&export.function).is_none() { + dfg.import_function(export.function.module, export.function.function, core_sig) + .map_err(|_e| { + let message = format!( + "Function(callee of the lowering) with name {} in module {} with signature \ + {cc_export_sig:?} is already imported (function call) with a different \ + signature", + export.function.function, export.function.module + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })?; } + // TODO: use the span from the callee + let call = builder.ins().exec(export.function, ¶ms, SourceSpan::UNKNOWN); + // dbg!(&sig); + // TODO: lower the result from the Wasm CABI to the cross-context Miden ABI + let result = builder.first_result(call); + builder.ins().ret(Some(result), SourceSpan::UNKNOWN); + let function_id = builder.build()?; + module_builder.build()?; + let component_export = ComponentExport { + function: function_id, + function_ty: FunctionType { + abi: Canonical, + ..export.function_ty + }, + ..export + }; + Ok(component_export) } diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.masm b/tests/integration/expected/rust_sdk/cross_ctx_account.masm index 4992ec4da..48e7cabf1 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_account.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.masm @@ -1,3 +1,12 @@ +# mod #anon::miden:cross-ctx-account/foo@1.0.0 + +use.cross_ctx_account + +export."process-felt" + exec.::cross_ctx_account::"miden:cross-ctx-account/foo@1.0.0#process-felt" +end + + # mod cross_ctx_account use.intrinsics::mem From 9e10242686a5f2a62c8b362b157ea4f488346875 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Fri, 29 Nov 2024 17:43:36 +0200 Subject: [PATCH 09/26] feature: draft `LiftImportsCrossCtxStage` scaffolding --- hir/src/component/mod.rs | 10 ++++ .../src/stages/lift_cross_ctx/mod.rs | 60 ++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index 3a25c72ea..2bda7b9c0 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -403,6 +403,12 @@ impl<'a> ComponentBuilder<'a> { self } + /// Replace the imports of the [Component] being built. + pub fn with_imports(mut self, imports: BTreeMap) -> Self { + self.imports = imports; + self + } + /// Add `module` to the set of modules to link into the final [Component] /// /// Returns `Err` if a module with the same name already exists @@ -445,6 +451,10 @@ impl<'a> ComponentBuilder<'a> { self.exports.insert(name, export); } + pub fn imports(&self) -> &BTreeMap { + &self.imports + } + pub fn exports(&self) -> &BTreeMap { &self.exports } diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs index cdefca9e6..074bbe6a5 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -1,16 +1,20 @@ //! Lifting the imports into the Miden ABI for the cross-context calls -use midenc_hir::pass::AnalysisManager; -use midenc_session::Session; +use std::collections::BTreeMap; + +use midenc_hir::{pass::AnalysisManager, ComponentBuilder, ComponentImport, FunctionIdent}; +use midenc_session::{DiagnosticsHandler, Session}; use super::LinkerInput; use crate::{stage::Stage, CompilerResult}; /// Generates lifting for imports for the cross-context calls according to the Miden ABI. /// -/// For every imported function call put the arguments on the stack or the advice provider and load -/// the result from the stack/advice provider into the memory according to the pointer after the -/// call. +/// For each component import ensure a module for each interface that has a lifting function i.e. a +/// function that takes the arguments according to the Wasm CABI, lowers them to the cross-context +/// Miden ABI, calls the imported function with the lowered arguments, takes the result +/// (cross-context Miden ABI), and lifts it to the Wasm CABI. +/// The calls to the component import is switched to the generated lifting function. pub struct LiftImportsCrossCtxStage; impl Stage for LiftImportsCrossCtxStage { @@ -21,8 +25,50 @@ impl Stage for LiftImportsCrossCtxStage { &mut self, input: Self::Input, _analyses: &mut AnalysisManager, - _session: &Session, + session: &Session, ) -> CompilerResult { - Ok(input) + let component = if let LinkerInput::Hir(component) = input { + component + } else { + return Ok(input); + }; + + let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); + + let mut lifted_imports: BTreeMap = BTreeMap::new(); + let imports = component_builder.imports().clone(); + for (id, import) in imports.into_iter() { + if let ComponentImport::MidenAbiImport(_) = import { + // skip imports that are already lifted + lifted_imports.insert(id, import); + continue; + } + let new_import = generate_lifting_function( + &mut component_builder, + id, + import, + &session.diagnostics, + )?; + lifted_imports.insert(id, new_import); + + // TODO: find all the calls to the component import and replace them with the generated lifting function + } + + let component_builder = component_builder.with_imports(lifted_imports); + + let component = component_builder.build(); + // dbg!(&component.imports()); + // dbg!(&component.modules().len()); + Ok(LinkerInput::Hir(component.into())) } } + +fn generate_lifting_function( + _component_builder: &mut ComponentBuilder<'_>, + _id: FunctionIdent, + import: ComponentImport, + _diagnostics: &DiagnosticsHandler, +) -> CompilerResult { + // TODO: implement the lifting function generation + Ok(import) +} From 4d45e2e4698a2139875ac6852171e8deb1951ae2 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Thu, 5 Dec 2024 17:44:34 +0200 Subject: [PATCH 10/26] feature: draft lifting function generation in `LiftImportsCrossCtxStage` --- Cargo.lock | 1 + frontend-wasm/src/component/translator.rs | 13 ++- hir/src/component/mod.rs | 4 +- midenc-compile/Cargo.toml | 1 + .../src/stages/lift_cross_ctx/mod.rs | 105 ++++++++++++++++-- .../src/stages/lower_cross_ctx/mod.rs | 22 ++-- .../expected/rust_sdk/cross_ctx_note.masm | 9 ++ tests/integration/src/compiler_test.rs | 2 +- .../src/rust_masm_tests/rust_sdk.rs | 4 +- 9 files changed, 133 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78d9a18a5..034b8df70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3241,6 +3241,7 @@ name = "midenc-compile" version = "0.0.7" dependencies = [ "clap", + "derive_more", "either", "intrusive-collections", "inventory", diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index 70e12d909..f547a8316 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -117,7 +117,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { } } for (name, export) in &wasm_translation.component.exports { - self.build_export(export, name, None, &mut component_builder)?; + self.build_export(export, name.clone(), None, &mut component_builder)?; } Ok(component_builder.build()) } @@ -353,13 +353,13 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { fn build_export( &self, export: &Export, - name: &String, + name: String, interface: Option, component_builder: &mut ComponentBuilder, ) -> WasmResult<()> { match export { Export::LiftedFunction { ty, func, options } => { - dbg!(name); + // dbg!(name); // The inline export does no have an interface name let interface = interface.unwrap_or_default(); // dbg!(&interface); @@ -372,7 +372,12 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { let interface = Some(name.clone()); // Flatten any(nested) interface instance exports into the IR `Component` exports for (export_name, export) in exports { - self.build_export(export, export_name, interface.clone(), component_builder)?; + self.build_export( + export, + export_name.clone(), + interface.clone(), + component_builder, + )?; } Ok(()) } diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index 2bda7b9c0..d1f9380b8 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -91,7 +91,7 @@ impl MidenAbiImport { } /// A component import -#[derive(Debug, Clone)] +#[derive(Debug, Clone, derive_more::From)] pub enum ComponentImport { /// A Wasm import that is following the Wasm Component Model Canonical ABI CanonAbiImport(CanonAbiImport), @@ -193,7 +193,7 @@ impl Component { // Temporary imterim solution until we have a proper way to name components let module_names = self.modules.keys().fold(String::new(), |acc, name| { if acc.is_empty() { - name.to_string() + name.as_str().to_string() } else { acc + "+" + name.as_str() } diff --git a/midenc-compile/Cargo.toml b/midenc-compile/Cargo.toml index 98e419cf2..fd0169050 100644 --- a/midenc-compile/Cargo.toml +++ b/midenc-compile/Cargo.toml @@ -29,3 +29,4 @@ midenc-hir-transform.workspace = true midenc-session.workspace = true thiserror.workspace = true wat.workspace = true +derive_more.workspace = true diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs index 074bbe6a5..8842c59bc 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -2,7 +2,11 @@ use std::collections::BTreeMap; -use midenc_hir::{pass::AnalysisManager, ComponentBuilder, ComponentImport, FunctionIdent}; +use midenc_hir::{ + diagnostics::Severity, pass::AnalysisManager, types::Abi, AbiParam, CallConv, CanonAbiImport, + ComponentBuilder, ComponentImport, FunctionIdent, FunctionType, InstBuilder, Linkage, + MidenAbiImport, Signature, SourceSpan, Symbol, Type, +}; use midenc_session::{DiagnosticsHandler, Session}; use super::LinkerInput; @@ -33,6 +37,14 @@ impl Stage for LiftImportsCrossCtxStage { return Ok(input); }; + // So far only hardcoded lift imports for the cross_ctx_note + if component.name().as_str() != "cross_ctx_note" { + return Ok(LinkerInput::Hir(component)); + } + + // dbg!(&component.imports()); + // dbg!(&component.modules().keys()); + let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); let mut lifted_imports: BTreeMap = BTreeMap::new(); @@ -43,13 +55,13 @@ impl Stage for LiftImportsCrossCtxStage { lifted_imports.insert(id, import); continue; } - let new_import = generate_lifting_function( + let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, id, - import, + import.unwrap_canon_abi_import(), &session.diagnostics, )?; - lifted_imports.insert(id, new_import); + lifted_imports.insert(lifting_func_id, new_import.into()); // TODO: find all the calls to the component import and replace them with the generated lifting function } @@ -57,18 +69,87 @@ impl Stage for LiftImportsCrossCtxStage { let component_builder = component_builder.with_imports(lifted_imports); let component = component_builder.build(); + // dbg!(&component.imports()); - // dbg!(&component.modules().len()); + // dbg!(&component.modules().keys()); + Ok(LinkerInput::Hir(component.into())) } } fn generate_lifting_function( - _component_builder: &mut ComponentBuilder<'_>, - _id: FunctionIdent, - import: ComponentImport, - _diagnostics: &DiagnosticsHandler, -) -> CompilerResult { - // TODO: implement the lifting function generation - Ok(import) + component_builder: &mut ComponentBuilder<'_>, + _core_import_function: FunctionIdent, + import: &CanonAbiImport, + diagnostics: &DiagnosticsHandler, +) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { + // get or create the module for the interface + let module_id = Symbol::intern(format!( + "lift-imports-{}", + import.interface_function.interface.full_name.as_str() + )); + dbg!(&module_id); + // TODO: prefix the module name with "lift-imports-"? The same for the lowering exports module. + let mut module_builder = component_builder.module(module_id); + // TODO: put the core function signature (as imported in the core module) in the component import + let import_core_sig = Signature { + params: vec![AbiParam::new(Type::Felt)], + results: vec![AbiParam::new(Type::Felt)], + cc: CallConv::SystemV, + linkage: Linkage::External, + }; + let mut builder = + module_builder.function(import.interface_function.function, import_core_sig.clone())?; + let entry = builder.current_block(); + let params = builder.block_params(entry).to_vec(); + + // TODO: analyze the signature and speculate what cross-context Miden ABI signature would + // export have. + // For now just assume passing <16 felts and returning 1 and copy the signature + let import_lowered_sig = Signature { + params: vec![AbiParam::new(Type::Felt)], + results: vec![AbiParam::new(Type::Felt)], + // TODO: add CallConv::CrossCtx + cc: CallConv::SystemV, + linkage: Linkage::External, + }; + let dfg = builder.data_flow_graph_mut(); + // import the Wasm CM interface function + let import_func_id = FunctionIdent { + module: import.interface_function.interface.full_name.into(), + function: import.interface_function.function.into(), + }; + if dfg.get_import(&import_func_id).is_none() { + dfg.import_function( + import_func_id.module, + import_func_id.function, + import_lowered_sig.clone(), + ) + .map_err(|_e| { + let message = format!( + "Lifting function with name {} in module {} with signature {import_lowered_sig:?} \ + is already imported (function call) with a different signature", + import_func_id.function, import_func_id.module + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })?; + } + // TODO: use the span from the caller + // TODO: lower the params from the Wasm CABI to the cross-context Miden ABI + let call = builder.ins().call(import_func_id, ¶ms, SourceSpan::UNKNOWN); + // dbg!(&sig); + // TODO: lift the result from the cross-context Miden ABI to Wasm CABI + let result = builder.first_result(call); + builder.ins().ret(Some(result), SourceSpan::UNKNOWN); + let function_id = builder.build()?; + module_builder.build()?; + let component_import = MidenAbiImport::new(FunctionType { + abi: Abi::Canonical, + params: import_lowered_sig.params.into_iter().map(|p| p.ty).collect(), + results: import_lowered_sig.results.into_iter().map(|r| r.ty).collect(), + }); + // dbg!(&component_import); + // dbg!(&function_id); + + Ok((component_import, function_id)) } diff --git a/midenc-compile/src/stages/lower_cross_ctx/mod.rs b/midenc-compile/src/stages/lower_cross_ctx/mod.rs index 4d1f67dcb..9a10a6e51 100644 --- a/midenc-compile/src/stages/lower_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lower_cross_ctx/mod.rs @@ -3,9 +3,11 @@ use std::collections::BTreeMap; use midenc_hir::{ - diagnostics::Severity, pass::AnalysisManager, types::Abi::Canonical, AbiParam, CallConv, - ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, Linkage, - Signature, SourceSpan, Type, + diagnostics::Severity, + pass::AnalysisManager, + types::Abi::{self, Canonical}, + AbiParam, CallConv, ComponentBuilder, ComponentExport, FunctionType, InstBuilder, + InterfaceFunctionIdent, Linkage, Signature, SourceSpan, Type, }; use midenc_session::{DiagnosticsHandler, Session}; @@ -45,6 +47,9 @@ impl Stage for LowerExportsCrossCtxStage { return Ok(input); }; + // dbg!(&component.exports()); + // dbg!(&component.modules().keys()); + let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); let mut lowered_exports: BTreeMap = @@ -80,6 +85,10 @@ impl Stage for LowerExportsCrossCtxStage { let component_builder = component_builder.with_exports(lowered_exports); let component = component_builder.build(); + + // dbg!(&component.exports()); + // dbg!(&component.modules().keys()); + Ok(LinkerInput::Hir(component.into())) } } @@ -126,9 +135,8 @@ fn generate_lowering_function( dfg.import_function(export.function.module, export.function.function, core_sig) .map_err(|_e| { let message = format!( - "Function(callee of the lowering) with name {} in module {} with signature \ - {cc_export_sig:?} is already imported (function call) with a different \ - signature", + "Lowering function with name {} in module {} with signature {cc_export_sig:?} \ + is already imported (function call) with a different signature", export.function.function, export.function.module ); diagnostics.diagnostic(Severity::Error).with_message(message).into_report() @@ -145,7 +153,7 @@ fn generate_lowering_function( let component_export = ComponentExport { function: function_id, function_ty: FunctionType { - abi: Canonical, + abi: Abi::Canonical, ..export.function_ty }, ..export diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.masm b/tests/integration/expected/rust_sdk/cross_ctx_note.masm index df8870dff..6f9bfb4e0 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.masm @@ -1,3 +1,12 @@ +# mod #anon::lift-imports-miden:cross-ctx-account/foo@1.0.0 + +use.miden:cross-ctx-account/foo@1.0.0 + +export."process-felt" + call.::miden:cross-ctx-account/foo@1.0.0::"process-felt" +end + + # mod cross_ctx_note use.intrinsics::mem diff --git a/tests/integration/src/compiler_test.rs b/tests/integration/src/compiler_test.rs index 3677228f0..a7a29bd43 100644 --- a/tests/integration/src/compiler_test.rs +++ b/tests/integration/src/compiler_test.rs @@ -445,7 +445,7 @@ impl CompilerTestBuilder { }, ) })); - dbg!(&inputs); + // dbg!(&inputs); CompilerTest { config: self.config, diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index a1d734fb4..2072f8234 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -163,11 +163,11 @@ fn rust_sdk_cross_ctx_note() { .iter() .map(|s| s.to_string()) .collect(); - dbg!(env::current_dir().unwrap().display()); + // dbg!(env::current_dir().unwrap().display()); let outputs = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm) .expect("Failed to compile the cross-ctx-account package for cross-ctx-note"); let masp_path: PathBuf = outputs.first().unwrap().clone(); - dbg!(&masp_path); + // dbg!(&masp_path); let _ = env_logger::builder().is_test(true).try_init(); From 302b7e7cbbd56c9881c0380d7b55135d4a808fda Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 10 Dec 2024 15:44:49 +0200 Subject: [PATCH 11/26] feature: rewrite the function calls from the imported function (Miden CCABI) to the lifting function (Wasm CABI). --- hir/src/component/mod.rs | 13 +- .../src/stages/lift_cross_ctx/mod.rs | 164 +++++++++++++++--- .../expected/rust_sdk/cross_ctx_note.masm | 3 +- 3 files changed, 155 insertions(+), 25 deletions(-) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index d1f9380b8..7b001231e 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -206,11 +206,12 @@ impl Component { &self.modules } + /// Consume this component and return its 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 + /// Drains the modules from this component and returns a mutable reference to them pub fn modules_mut(&mut self) -> &mut IndexMap> { &mut self.modules } @@ -459,6 +460,16 @@ impl<'a> ComponentBuilder<'a> { &self.exports } + /// Takes the modules from this component builder leaving it with empty modules list + pub fn take_modules(&mut self) -> impl Iterator)> + '_ { + self.modules.drain(..) + } + + /// Set the modules of this component + pub fn set_modules(&mut self, modules: IndexMap>) { + self.modules = modules; + } + pub fn build(self) -> Component { assert!(!self.modules.is_empty(), "Cannot build a component with no modules"); Component { diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs index 8842c59bc..841d314ae 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -1,11 +1,11 @@ //! Lifting the imports into the Miden ABI for the cross-context calls -use std::collections::BTreeMap; +use std::collections::{BTreeMap, VecDeque}; use midenc_hir::{ - diagnostics::Severity, pass::AnalysisManager, types::Abi, AbiParam, CallConv, CanonAbiImport, - ComponentBuilder, ComponentImport, FunctionIdent, FunctionType, InstBuilder, Linkage, - MidenAbiImport, Signature, SourceSpan, Symbol, Type, + diagnostics::Severity, pass::AnalysisManager, types::Abi, AbiParam, Block, Call, CallConv, + ComponentBuilder, ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, + Instruction, Linkage, MidenAbiImport, Signature, SourceSpan, Symbol, Type, UnsafeRef, }; use midenc_session::{DiagnosticsHandler, Session}; @@ -28,7 +28,7 @@ impl Stage for LiftImportsCrossCtxStage { fn run( &mut self, input: Self::Input, - _analyses: &mut AnalysisManager, + analyses: &mut AnalysisManager, session: &Session, ) -> CompilerResult { let component = if let LinkerInput::Hir(component) = input { @@ -55,15 +55,25 @@ impl Stage for LiftImportsCrossCtxStage { lifted_imports.insert(id, import); continue; } + let cabi_import = import.unwrap_canon_abi_import(); + let import_func_id = FunctionIdent { + module: cabi_import.interface_function.interface.full_name.into(), + function: cabi_import.interface_function.function.into(), + }; let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, - id, - import.unwrap_canon_abi_import(), + import_func_id, &session.diagnostics, )?; lifted_imports.insert(lifting_func_id, new_import.into()); - // TODO: find all the calls to the component import and replace them with the generated lifting function + call_lifting_function( + &mut component_builder, + lifting_func_id, + import_func_id, + analyses, + session, + )?; } let component_builder = component_builder.with_imports(lifted_imports); @@ -77,20 +87,18 @@ impl Stage for LiftImportsCrossCtxStage { } } +/// Generates the lifting function (cross-context Miden ABI -> Wasm CABI) for the given import function. fn generate_lifting_function( component_builder: &mut ComponentBuilder<'_>, - _core_import_function: FunctionIdent, - import: &CanonAbiImport, + import_func_id: FunctionIdent, diagnostics: &DiagnosticsHandler, ) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { // get or create the module for the interface - let module_id = Symbol::intern(format!( - "lift-imports-{}", - import.interface_function.interface.full_name.as_str() - )); - dbg!(&module_id); + let lifting_module_id = + Symbol::intern(format!("lift-imports-{}", import_func_id.module.as_str())); + dbg!(&lifting_module_id); // TODO: prefix the module name with "lift-imports-"? The same for the lowering exports module. - let mut module_builder = component_builder.module(module_id); + let mut module_builder = component_builder.module(lifting_module_id); // TODO: put the core function signature (as imported in the core module) in the component import let import_core_sig = Signature { params: vec![AbiParam::new(Type::Felt)], @@ -98,8 +106,7 @@ fn generate_lifting_function( cc: CallConv::SystemV, linkage: Linkage::External, }; - let mut builder = - module_builder.function(import.interface_function.function, import_core_sig.clone())?; + let mut builder = module_builder.function(import_func_id.function, import_core_sig.clone())?; let entry = builder.current_block(); let params = builder.block_params(entry).to_vec(); @@ -114,11 +121,6 @@ fn generate_lifting_function( linkage: Linkage::External, }; let dfg = builder.data_flow_graph_mut(); - // import the Wasm CM interface function - let import_func_id = FunctionIdent { - module: import.interface_function.interface.full_name.into(), - function: import.interface_function.function.into(), - }; if dfg.get_import(&import_func_id).is_none() { dfg.import_function( import_func_id.module, @@ -153,3 +155,119 @@ fn generate_lifting_function( Ok((component_import, function_id)) } + +/// Rewrites the calls to the function `from` to the function `to` in the given function. +/// Returns `true` if any call was rewritten. +fn rewrite_calls(function: &mut Function, from: FunctionIdent, to: FunctionIdent) -> bool { + let mut dirty = false; + let mut worklist = VecDeque::::default(); + for block in function.dfg.blocks.keys() { + worklist.push_back(block); + } + + for b in worklist { + let block = &mut function.dfg.blocks[b]; + // Take the list of instructions away from the block to simplify traversing the block + let mut insts = block.insts.take(); + // Take each instruction out of the list, top to bottom, modify it, then + // add it back to the instruction list of the block directly. This ensures + // we traverse the list and rewrite instructions in a single pass without + // any additional overhead + while let Some(inst) = insts.pop_front() { + let mut inst = unsafe { UnsafeRef::into_box(inst) }; + let instruction: &mut Instruction = inst.as_mut(); + match instruction { + Instruction::Call(Call { ref mut callee, .. }) => { + // Rewrite the call instruction + // rewrite_call(call, &mut function.dfg.value_lists, rewrites); + if callee == &from { + *callee = to; + dirty = true; + } + } + _op => (), + } + + block.insts.push_back(UnsafeRef::from_box(inst)); + } + } + dirty +} + +/// Replaces calls to the imported functions with calls to the lifting functions. +fn call_lifting_function( + component_builder: &mut ComponentBuilder<'_>, + lifting_func_id: FunctionIdent, + import_func_id: FunctionIdent, + analyses: &mut AnalysisManager, + session: &Session, +) -> Result<(), miden_assembly::Report> { + let mut modules = Vec::new(); + for (id, mut module) in component_builder.take_modules() { + if module.name == lifting_func_id.module { + // Skip the module with the lifting function + modules.push((id, module)); + continue; + } + // Removing a function via this cursor will move the cursor to + // the next function in the module. Once the end of the module + // is reached, the cursor will point to the null object, and + // `remove` will return `None`. + let mut cursor = module.cursor_mut(); + // let mut dirty = false; + while let Some(mut function) = cursor.remove() { + // // Apply rewrite + // if self.0.should_apply(&function, session) { + // dirty = true; + // self.0.apply(&mut function, analyses, session)?; + // analyses.invalidate::(&function.id); + // } + + // TODO: put the core function signature (as imported in the core module) in the component import + // as in the generate_lifting_function + let import_core_sig = Signature { + params: vec![AbiParam::new(Type::Felt)], + results: vec![AbiParam::new(Type::Felt)], + cc: CallConv::SystemV, + linkage: Linkage::External, + }; + + if rewrite_calls(&mut function, import_func_id, lifting_func_id) { + // Invalidate the analyses for the function since we've modified it + analyses.invalidate::(&function.id); + // Import the lifting function if it's not already imported + let dfg = &mut function.dfg; + if dfg.get_import(&lifting_func_id).is_none() { + dfg.import_function( + lifting_func_id.module, + lifting_func_id.function, + import_core_sig.clone(), + ) + .map_err(|_e| { + let message = format!( + "Lifting function with name {} in module {} with signature \ + {import_core_sig:?} is already imported (function call) with a \ + different signature", + import_func_id.function, import_func_id.module + ); + session + .diagnostics + .diagnostic(Severity::Error) + .with_message(message) + .into_report() + })?; + } + } + + // Add the function back to the module + // + // We add it before the current position of the cursor + // to ensure that we don't interfere with our traversal + // of the module top to bottom + cursor.insert_before(function); + } + modules.push((id, module)); + } + component_builder.set_modules(modules.into_iter().collect()); + Ok(()) +} diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.masm b/tests/integration/expected/rust_sdk/cross_ctx_note.masm index 6f9bfb4e0..3d2043a39 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.masm @@ -10,6 +10,7 @@ end # mod cross_ctx_note use.intrinsics::mem +use.lift-imports-miden:cross-ctx-account/foo@1.0.0 use.miden:cross-ctx-account/foo@1.0.0 proc."cross_ctx_note::bindings::__link_custom_section_describing_imports" @@ -421,7 +422,7 @@ end export."miden:base/note-script@1.0.0#note-script" exec."wit_bindgen_rt::run_ctors_once" push.7 - exec.::miden:cross-ctx-account/foo@1.0.0::"process-felt" + exec.::lift-imports-miden:cross-ctx-account/foo@1.0.0::"process-felt" push.10 assert_eq end From a170c8a06276d87aecb8249ce57d7654a97b9a68 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 10 Dec 2024 16:29:29 +0200 Subject: [PATCH 12/26] feature: store the imported function type in the component import --- frontend-wasm/src/component/build_ir.rs | 2 +- frontend-wasm/src/component/translator.rs | 24 ++++++++++--- hir/src/component/mod.rs | 19 ++++++---- .../src/stages/lift_cross_ctx/mod.rs | 35 +++++++------------ 4 files changed, 45 insertions(+), 35 deletions(-) diff --git a/frontend-wasm/src/component/build_ir.rs b/frontend-wasm/src/component/build_ir.rs index 24e9efb83..0190cd55b 100644 --- a/frontend-wasm/src/component/build_ir.rs +++ b/frontend-wasm/src/component/build_ir.rs @@ -21,7 +21,7 @@ pub fn translate_component( let component_types = component_types_builder.finish(); let parsed_modules = parsed_component.static_modules; let translator = ComponentTranslator::new(component_types, parsed_modules, config, session); - translator.translate(linearized_component_translation) + translator.translate(linearized_component_translation, session.diagnostics.as_ref()) } fn parse<'data>( diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index f547a8316..6d92c3568 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -4,7 +4,7 @@ use midenc_hir::{ MidenAbiImport, Symbol, }; use midenc_hir_type::Abi; -use midenc_session::Session; +use midenc_session::{DiagnosticsHandler, Session}; use rustc_hash::FxHashMap; use super::{ @@ -25,7 +25,7 @@ use crate::{ instance::ModuleArgument, module_env::ParsedModule, module_translation_state::ModuleTranslationState, - types::{EntityIndex, FuncIndex}, + types::{ir_func_type, EntityIndex, FuncIndex}, Module, }, unsupported_diag, WasmTranslationConfig, @@ -73,6 +73,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { pub fn translate( mut self, wasm_translation: LinearComponentTranslation, + diagnostics: &DiagnosticsHandler, ) -> WasmResult { let mut component_builder: midenc_hir::ComponentBuilder<'a> = midenc_hir::ComponentBuilder::new(&self.session.diagnostics); @@ -84,6 +85,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { instantiate_module, &mut component_builder, &wasm_translation, + diagnostics, )?; } GlobalInitializer::LowerImport { @@ -128,6 +130,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { instantiate_module: &InstantiateModule, component_builder: &mut ComponentBuilder<'_>, wasm_translation: &LinearComponentTranslation, + diagnostics: &DiagnosticsHandler, ) -> WasmResult<()> { match instantiate_module { InstantiateModule::Static(static_module_idx, args) => { @@ -163,6 +166,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { idx, &wasm_translation.component, component_builder, + diagnostics, )? { module_args.push(arg) } @@ -218,6 +222,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { idx: usize, wasm_component: &LinearComponent, component_builder: &mut ComponentBuilder<'_>, + diagnostics: &DiagnosticsHandler, ) -> WasmResult> { match trampoline { Trampoline::LowerImport { @@ -226,12 +231,18 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { options, } => { let module_import = module.imports.get(idx).expect("module import not found"); - let function_id = module.func_name(module_import.index.unwrap_func()).into(); + let func_index = module_import.index.unwrap_func(); + let function_id = module.func_name(func_index).into(); let function_id = FunctionIdent { module: module.name(), function: function_id, }; + let func_type = &module.functions[func_index]; + let module_types = self.component_types.module_types(); + let wasm_func_type = module_types[func_type.signature].clone(); + let low_func_ty = ir_func_type(&wasm_func_type, diagnostics)?; + // TODO: // Find process_list_felt instead empty module name and "0" function name! // Follow module_import.index through the shim modules/imports/exports? @@ -241,6 +252,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { match self.translate_import( runtime_import_idx, *lower_ty, + low_func_ty, options, wasm_component, )? { @@ -300,7 +312,8 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { fn translate_import( &self, runtime_import_index: RuntimeImportIndex, - signature: TypeFuncIndex, + high_func_ty: TypeFuncIndex, + low_func_ty: FunctionType, options: &CanonicalOptions, wasm_component: &LinearComponent, ) -> WasmResult> { @@ -338,11 +351,12 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { interface: InterfaceIdent::from_full_ident(&full_interface_name), function: Symbol::intern(import_func_name), }; - let lifted_func_ty = convert_lifted_func_ty(&signature, &self.component_types); + let lifted_func_ty = convert_lifted_func_ty(&high_func_ty, &self.component_types); let component_import = midenc_hir::ComponentImport::CanonAbiImport(CanonAbiImport::new( interface_function, lifted_func_ty, + low_func_ty, self.translate_canonical_options(options)?, )); Ok(Some(component_import)) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index 7b001231e..de2b7a3aa 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -52,7 +52,10 @@ pub struct CanonAbiImport { /// The interfact function name that is being imported pub interface_function: InterfaceFunctionIdent, /// The component(lifted) type of the imported function - function_ty: FunctionType, + high_func_ty: FunctionType, + /// The function type of the imported function in the module + /// (low-level from core Wasm) + low_func_ty: FunctionType, /// Any options associated with this import pub options: CanonicalOptions, } @@ -60,19 +63,21 @@ pub struct CanonAbiImport { impl CanonAbiImport { pub fn new( interface_function: InterfaceFunctionIdent, - function_ty: FunctionType, + high_func_ty: FunctionType, + low_func_ty: FunctionType, options: CanonicalOptions, ) -> Self { - assert_eq!(function_ty.abi, Abi::Wasm, "expected Abi::Wasm function type ABI"); + assert_eq!(high_func_ty.abi, Abi::Wasm, "expected Abi::Wasm function type ABI"); Self { interface_function, - function_ty, + high_func_ty, + low_func_ty, options, } } - pub fn function_ty(&self) -> &FunctionType { - &self.function_ty + pub fn low_func_ty(&self) -> &FunctionType { + &self.low_func_ty } } @@ -118,7 +123,7 @@ impl formatter::PrettyPrint for ComponentImport { fn render(&self) -> formatter::Document { use crate::formatter::*; let function_ty_str = match self { - ComponentImport::CanonAbiImport(import) => import.function_ty.to_string(), + ComponentImport::CanonAbiImport(import) => import.high_func_ty.to_string(), ComponentImport::MidenAbiImport(import) => import.function_ty.to_string(), }; let name = match self { diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs index 841d314ae..43d213e84 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -63,6 +63,7 @@ impl Stage for LiftImportsCrossCtxStage { let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, import_func_id, + cabi_import.low_func_ty().clone(), &session.diagnostics, )?; lifted_imports.insert(lifting_func_id, new_import.into()); @@ -71,6 +72,7 @@ impl Stage for LiftImportsCrossCtxStage { &mut component_builder, lifting_func_id, import_func_id, + cabi_import.low_func_ty().clone(), analyses, session, )?; @@ -91,18 +93,17 @@ impl Stage for LiftImportsCrossCtxStage { fn generate_lifting_function( component_builder: &mut ComponentBuilder<'_>, import_func_id: FunctionIdent, + import_func_ty: FunctionType, diagnostics: &DiagnosticsHandler, ) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { // get or create the module for the interface let lifting_module_id = Symbol::intern(format!("lift-imports-{}", import_func_id.module.as_str())); - dbg!(&lifting_module_id); - // TODO: prefix the module name with "lift-imports-"? The same for the lowering exports module. + // dbg!(&lifting_module_id); let mut module_builder = component_builder.module(lifting_module_id); - // TODO: put the core function signature (as imported in the core module) in the component import let import_core_sig = Signature { - params: vec![AbiParam::new(Type::Felt)], - results: vec![AbiParam::new(Type::Felt)], + params: import_func_ty.params.into_iter().map(AbiParam::new).collect(), + results: import_func_ty.results.into_iter().map(AbiParam::new).collect(), cc: CallConv::SystemV, linkage: Linkage::External, }; @@ -199,9 +200,16 @@ fn call_lifting_function( component_builder: &mut ComponentBuilder<'_>, lifting_func_id: FunctionIdent, import_func_id: FunctionIdent, + import_func_ty: FunctionType, analyses: &mut AnalysisManager, session: &Session, ) -> Result<(), miden_assembly::Report> { + let import_core_sig = Signature { + params: import_func_ty.params.into_iter().map(AbiParam::new).collect(), + results: import_func_ty.results.into_iter().map(AbiParam::new).collect(), + cc: CallConv::SystemV, + linkage: Linkage::External, + }; let mut modules = Vec::new(); for (id, mut module) in component_builder.take_modules() { if module.name == lifting_func_id.module { @@ -214,24 +222,7 @@ fn call_lifting_function( // is reached, the cursor will point to the null object, and // `remove` will return `None`. let mut cursor = module.cursor_mut(); - // let mut dirty = false; while let Some(mut function) = cursor.remove() { - // // Apply rewrite - // if self.0.should_apply(&function, session) { - // dirty = true; - // self.0.apply(&mut function, analyses, session)?; - // analyses.invalidate::(&function.id); - // } - - // TODO: put the core function signature (as imported in the core module) in the component import - // as in the generate_lifting_function - let import_core_sig = Signature { - params: vec![AbiParam::new(Type::Felt)], - results: vec![AbiParam::new(Type::Felt)], - cc: CallConv::SystemV, - linkage: Linkage::External, - }; - if rewrite_calls(&mut function, import_func_id, lifting_func_id) { // Invalidate the analyses for the function since we've modified it analyses.invalidate::(&function.id); From de6e333a838961935faaf4d464c2a8011fec65a2 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Wed, 11 Dec 2024 16:40:31 +0200 Subject: [PATCH 13/26] feature: on Miden CCABI lifting/lowering get import/export function signature from the `Component`, remove import function signature from `CanonAbiImport` --- frontend-wasm/src/component/translator.rs | 12 +---- hir/src/component/mod.rs | 32 +++++++++---- .../src/stages/lift_cross_ctx/mod.rs | 48 +++++++++++-------- .../src/stages/lower_cross_ctx/mod.rs | 34 +++++++------ 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index 6d92c3568..60b0b9871 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -25,7 +25,7 @@ use crate::{ instance::ModuleArgument, module_env::ParsedModule, module_translation_state::ModuleTranslationState, - types::{ir_func_type, EntityIndex, FuncIndex}, + types::{EntityIndex, FuncIndex}, Module, }, unsupported_diag, WasmTranslationConfig, @@ -222,7 +222,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { idx: usize, wasm_component: &LinearComponent, component_builder: &mut ComponentBuilder<'_>, - diagnostics: &DiagnosticsHandler, + _diagnostics: &DiagnosticsHandler, ) -> WasmResult> { match trampoline { Trampoline::LowerImport { @@ -238,11 +238,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { function: function_id, }; - let func_type = &module.functions[func_index]; - let module_types = self.component_types.module_types(); - let wasm_func_type = module_types[func_type.signature].clone(); - let low_func_ty = ir_func_type(&wasm_func_type, diagnostics)?; - // TODO: // Find process_list_felt instead empty module name and "0" function name! // Follow module_import.index through the shim modules/imports/exports? @@ -252,7 +247,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { match self.translate_import( runtime_import_idx, *lower_ty, - low_func_ty, options, wasm_component, )? { @@ -313,7 +307,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { &self, runtime_import_index: RuntimeImportIndex, high_func_ty: TypeFuncIndex, - low_func_ty: FunctionType, options: &CanonicalOptions, wasm_component: &LinearComponent, ) -> WasmResult> { @@ -356,7 +349,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { midenc_hir::ComponentImport::CanonAbiImport(CanonAbiImport::new( interface_function, lifted_func_ty, - low_func_ty, self.translate_canonical_options(options)?, )); Ok(Some(component_import)) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index de2b7a3aa..b77fcb20d 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -53,9 +53,6 @@ pub struct CanonAbiImport { pub interface_function: InterfaceFunctionIdent, /// The component(lifted) type of the imported function high_func_ty: FunctionType, - /// The function type of the imported function in the module - /// (low-level from core Wasm) - low_func_ty: FunctionType, /// Any options associated with this import pub options: CanonicalOptions, } @@ -64,21 +61,15 @@ impl CanonAbiImport { pub fn new( interface_function: InterfaceFunctionIdent, high_func_ty: FunctionType, - low_func_ty: FunctionType, options: CanonicalOptions, ) -> Self { assert_eq!(high_func_ty.abi, Abi::Wasm, "expected Abi::Wasm function type ABI"); Self { interface_function, high_func_ty, - low_func_ty, options, } } - - pub fn low_func_ty(&self) -> &FunctionType { - &self.low_func_ty - } } /// A Miden (sdklib, tx kernel) function import that is following the Miden ABI. @@ -465,6 +456,29 @@ impl<'a> ComponentBuilder<'a> { &self.exports } + /// Look up the signature of a function in this program by `id` + pub fn signature(&self, id: &FunctionIdent) -> Option<&Signature> { + let module = self.modules.get(&id.module)?; + module.function(id.function).map(|f| &f.signature) + } + + /// Look up the signature of an imported function by `id` + /// + /// NOTE: Due to the imports are stored on the function level this searches in **all** functions of + /// **all** modules of this component. + pub fn import_signature(&self, id: &FunctionIdent) -> Option<&Signature> { + for module in self.modules.values() { + for function in module.functions.iter() { + for import in function.imports() { + if &import.id == id { + return Some(&import.signature); + } + } + } + } + None + } + /// Takes the modules from this component builder leaving it with empty modules list pub fn take_modules(&mut self) -> impl Iterator)> + '_ { self.modules.drain(..) diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/lift_cross_ctx/mod.rs index 43d213e84..7b2a8d23c 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lift_cross_ctx/mod.rs @@ -49,10 +49,10 @@ impl Stage for LiftImportsCrossCtxStage { let mut lifted_imports: BTreeMap = BTreeMap::new(); let imports = component_builder.imports().clone(); - for (id, import) in imports.into_iter() { + for (core_import_func_id, import) in imports.into_iter() { if let ComponentImport::MidenAbiImport(_) = import { // skip imports that are already lifted - lifted_imports.insert(id, import); + lifted_imports.insert(core_import_func_id, import); continue; } let cabi_import = import.unwrap_canon_abi_import(); @@ -60,10 +60,27 @@ impl Stage for LiftImportsCrossCtxStage { module: cabi_import.interface_function.interface.full_name.into(), function: cabi_import.interface_function.function.into(), }; + + let import_func_sig = component_builder + .import_signature(&import_func_id) + .ok_or({ + let message = format!( + "Miden CCABI import lifting generation. Cannot find signature for Wasm \ + CABI imported function {}", + import_func_id + ); + session + .diagnostics + .diagnostic(Severity::Error) + .with_message(message) + .into_report() + })? + .clone(); + let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, import_func_id, - cabi_import.low_func_ty().clone(), + import_func_sig.clone(), &session.diagnostics, )?; lifted_imports.insert(lifting_func_id, new_import.into()); @@ -72,7 +89,7 @@ impl Stage for LiftImportsCrossCtxStage { &mut component_builder, lifting_func_id, import_func_id, - cabi_import.low_func_ty().clone(), + import_func_sig, analyses, session, )?; @@ -93,7 +110,7 @@ impl Stage for LiftImportsCrossCtxStage { fn generate_lifting_function( component_builder: &mut ComponentBuilder<'_>, import_func_id: FunctionIdent, - import_func_ty: FunctionType, + import_func_sig: Signature, diagnostics: &DiagnosticsHandler, ) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { // get or create the module for the interface @@ -101,13 +118,8 @@ fn generate_lifting_function( Symbol::intern(format!("lift-imports-{}", import_func_id.module.as_str())); // dbg!(&lifting_module_id); let mut module_builder = component_builder.module(lifting_module_id); - let import_core_sig = Signature { - params: import_func_ty.params.into_iter().map(AbiParam::new).collect(), - results: import_func_ty.results.into_iter().map(AbiParam::new).collect(), - cc: CallConv::SystemV, - linkage: Linkage::External, - }; - let mut builder = module_builder.function(import_func_id.function, import_core_sig.clone())?; + + let mut builder = module_builder.function(import_func_id.function, import_func_sig)?; let entry = builder.current_block(); let params = builder.block_params(entry).to_vec(); @@ -200,16 +212,10 @@ fn call_lifting_function( component_builder: &mut ComponentBuilder<'_>, lifting_func_id: FunctionIdent, import_func_id: FunctionIdent, - import_func_ty: FunctionType, + import_func_sig: Signature, analyses: &mut AnalysisManager, session: &Session, ) -> Result<(), miden_assembly::Report> { - let import_core_sig = Signature { - params: import_func_ty.params.into_iter().map(AbiParam::new).collect(), - results: import_func_ty.results.into_iter().map(AbiParam::new).collect(), - cc: CallConv::SystemV, - linkage: Linkage::External, - }; let mut modules = Vec::new(); for (id, mut module) in component_builder.take_modules() { if module.name == lifting_func_id.module { @@ -232,12 +238,12 @@ fn call_lifting_function( dfg.import_function( lifting_func_id.module, lifting_func_id.function, - import_core_sig.clone(), + import_func_sig.clone(), ) .map_err(|_e| { let message = format!( "Lifting function with name {} in module {} with signature \ - {import_core_sig:?} is already imported (function call) with a \ + {import_func_sig:?} is already imported (function call) with a \ different signature", import_func_id.function, import_func_id.module ); diff --git a/midenc-compile/src/stages/lower_cross_ctx/mod.rs b/midenc-compile/src/stages/lower_cross_ctx/mod.rs index 9a10a6e51..eff4508c5 100644 --- a/midenc-compile/src/stages/lower_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/lower_cross_ctx/mod.rs @@ -25,9 +25,6 @@ use crate::{stage::Stage, CompilerResult}; /// cross-context calls, i.e. using the stack and the advice provider for arguments and results. pub struct LowerExportsCrossCtxStage; -// TODO: load the rodata into the memory in the lowering to ensure that the fresh context is -// correctly initialized - // TODO: swap `lift` and `lower` in the component import/export pretty-printing to sync with // this stage's terminology (an export is lowered, an import is lifted) @@ -105,38 +102,45 @@ fn generate_lowering_function( { return Ok(export); } + + let export_func_sig = component_builder + .signature(&export.function) + .ok_or({ + let message = format!( + "Miden CCABI export lowering generation. Cannot find signature for exported \ + function {}", + export.function + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })? + .clone(); + // get or create the module for the interface let module_id = export_id.interface.full_name; let mut module_builder = component_builder.module(module_id); // TODO: analyze the signature and speculate what cross-context Miden ABI signature we need to export. // For now just assume passing <16 felts and returning 1 and copy the signature - let cc_export_sig = Signature { + let cross_ctx_export_sig = Signature { params: vec![AbiParam::new(Type::Felt)], results: vec![AbiParam::new(Type::Felt)], // TODO: add CallConv::CrossCtx cc: CallConv::SystemV, linkage: Linkage::External, }; - let mut builder = module_builder.function(export_id.function, cc_export_sig.clone())?; + let mut builder = module_builder.function(export_id.function, cross_ctx_export_sig.clone())?; let entry = builder.current_block(); let params = builder.block_params(entry).to_vec(); // TODO: lift the params from the cross-context Miden ABI to the Wasm CABI - // TODO: put the core function signature in the export - let core_sig = Signature { - params: vec![AbiParam::new(Type::Felt)], - results: vec![AbiParam::new(Type::Felt)], - cc: CallConv::SystemV, - linkage: Linkage::Internal, - }; let dfg = builder.data_flow_graph_mut(); // import the Wasm core function if dfg.get_import(&export.function).is_none() { - dfg.import_function(export.function.module, export.function.function, core_sig) + dfg.import_function(export.function.module, export.function.function, export_func_sig) .map_err(|_e| { let message = format!( - "Lowering function with name {} in module {} with signature {cc_export_sig:?} \ - is already imported (function call) with a different signature", + "Miden CCABI export lowering generation. Lowering function with name {} in \ + module {} with signature {cross_ctx_export_sig:?} is already imported \ + (function call) with a different signature", export.function.function, export.function.module ); diagnostics.diagnostic(Severity::Error).with_message(message).into_report() From 2be8e0a7400bb54b684bd1b149f747aaaae04f2c Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Thu, 12 Dec 2024 09:17:58 +0200 Subject: [PATCH 14/26] refactor: move `LiftImportsCrossCtxStage`, `LowerExportsCrossCtxStage` to the new `cross_ctx` module --- .../mod.rs => cross_ctx/lift_imports.rs} | 6 ++-- .../mod.rs => cross_ctx/lower_exports.rs} | 30 +++++++++++-------- midenc-compile/src/stages/cross_ctx/mod.rs | 2 ++ midenc-compile/src/stages/mod.rs | 6 ++-- 4 files changed, 24 insertions(+), 20 deletions(-) rename midenc-compile/src/stages/{lift_cross_ctx/mod.rs => cross_ctx/lift_imports.rs} (98%) rename midenc-compile/src/stages/{lower_cross_ctx/mod.rs => cross_ctx/lower_exports.rs} (87%) create mode 100644 midenc-compile/src/stages/cross_ctx/mod.rs diff --git a/midenc-compile/src/stages/lift_cross_ctx/mod.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs similarity index 98% rename from midenc-compile/src/stages/lift_cross_ctx/mod.rs rename to midenc-compile/src/stages/cross_ctx/lift_imports.rs index 7b2a8d23c..3c6898fd8 100644 --- a/midenc-compile/src/stages/lift_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -9,8 +9,7 @@ use midenc_hir::{ }; use midenc_session::{DiagnosticsHandler, Session}; -use super::LinkerInput; -use crate::{stage::Stage, CompilerResult}; +use crate::{stage::Stage, CompilerResult, LinkerInput}; /// Generates lifting for imports for the cross-context calls according to the Miden ABI. /// @@ -37,8 +36,9 @@ impl Stage for LiftImportsCrossCtxStage { return Ok(input); }; - // So far only hardcoded lift imports for the cross_ctx_note + // TODO: remove after handling the lifting for all imports! if component.name().as_str() != "cross_ctx_note" { + // So far only hardcoded lift imports for the cross_ctx_note return Ok(LinkerInput::Hir(component)); } diff --git a/midenc-compile/src/stages/lower_cross_ctx/mod.rs b/midenc-compile/src/stages/cross_ctx/lower_exports.rs similarity index 87% rename from midenc-compile/src/stages/lower_cross_ctx/mod.rs rename to midenc-compile/src/stages/cross_ctx/lower_exports.rs index eff4508c5..afd48054d 100644 --- a/midenc-compile/src/stages/lower_cross_ctx/mod.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_exports.rs @@ -11,8 +11,7 @@ use midenc_hir::{ }; use midenc_session::{DiagnosticsHandler, Session}; -use super::LinkerInput; -use crate::{stage::Stage, CompilerResult}; +use crate::{stage::Stage, CompilerResult, LinkerInput}; /// Generates lowering for exports for the cross-context calls according to the Miden ABI. /// @@ -96,10 +95,11 @@ fn generate_lowering_function( export: ComponentExport, diagnostics: &DiagnosticsHandler, ) -> CompilerResult { - // So far we only hardcoded the lowering for the process-felt function + // TODO: remove after handling the lowering for all exports! if export_id.interface.to_string() != "miden:cross-ctx-account/foo@1.0.0" && export_id.function.as_str() != "process-felt" { + // So far we only hardcoded the lowering for the process-felt function return Ok(export); } @@ -135,16 +135,20 @@ fn generate_lowering_function( let dfg = builder.data_flow_graph_mut(); // import the Wasm core function if dfg.get_import(&export.function).is_none() { - dfg.import_function(export.function.module, export.function.function, export_func_sig) - .map_err(|_e| { - let message = format!( - "Miden CCABI export lowering generation. Lowering function with name {} in \ - module {} with signature {cross_ctx_export_sig:?} is already imported \ - (function call) with a different signature", - export.function.function, export.function.module - ); - diagnostics.diagnostic(Severity::Error).with_message(message).into_report() - })?; + dfg.import_function( + export.function.module, + export.function.function, + export_func_sig.clone(), + ) + .map_err(|_e| { + let message = format!( + "Miden CCABI export lowering generation. Lowering function with name {} in module \ + {} with signature {export_func_sig:?} is already imported (function call) with a \ + different signature", + export.function.function, export.function.module + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })?; } // TODO: use the span from the callee let call = builder.ins().exec(export.function, ¶ms, SourceSpan::UNKNOWN); diff --git a/midenc-compile/src/stages/cross_ctx/mod.rs b/midenc-compile/src/stages/cross_ctx/mod.rs new file mode 100644 index 000000000..e29fc35ba --- /dev/null +++ b/midenc-compile/src/stages/cross_ctx/mod.rs @@ -0,0 +1,2 @@ +pub(super) mod lift_imports; +pub(super) mod lower_exports; diff --git a/midenc-compile/src/stages/mod.rs b/midenc-compile/src/stages/mod.rs index bb81c2d8c..b3a62607a 100644 --- a/midenc-compile/src/stages/mod.rs +++ b/midenc-compile/src/stages/mod.rs @@ -16,9 +16,8 @@ use crate::{CompilerResult, CompilerStopped}; mod assemble; mod codegen; -mod lift_cross_ctx; +mod cross_ctx; mod link; -mod lower_cross_ctx; mod parse; mod rewrite; mod sema; @@ -26,9 +25,8 @@ mod sema; pub use self::{ assemble::{Artifact, AssembleStage}, codegen::CodegenStage, - lift_cross_ctx::LiftImportsCrossCtxStage, + cross_ctx::{lift_imports::LiftImportsCrossCtxStage, lower_exports::LowerExportsCrossCtxStage}, link::{LinkerInput, LinkerOutput, LinkerStage}, - lower_cross_ctx::LowerExportsCrossCtxStage, parse::{ParseOutput, ParseStage}, rewrite::ApplyRewritesStage, sema::SemanticAnalysisStage, From 7ddee96c3383fe07b5b3b8e8a6538ccf9ff290b1 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Thu, 12 Dec 2024 17:08:38 +0200 Subject: [PATCH 15/26] feature: draft Wasm CM function type flattening, checks for scalar type values --- hir/src/component/mod.rs | 2 +- midenc-compile/src/stages/cross_ctx/flat.rs | 135 ++++++++++++++++++ .../src/stages/cross_ctx/lift_imports.rs | 36 +++-- .../src/stages/cross_ctx/lower_exports.rs | 34 +++-- midenc-compile/src/stages/cross_ctx/mod.rs | 3 + 5 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 midenc-compile/src/stages/cross_ctx/flat.rs diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index b77fcb20d..8e2100d55 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -52,7 +52,7 @@ pub struct CanonAbiImport { /// The interfact function name that is being imported pub interface_function: InterfaceFunctionIdent, /// The component(lifted) type of the imported function - high_func_ty: FunctionType, + pub high_func_ty: FunctionType, /// Any options associated with this import pub options: CanonicalOptions, } diff --git a/midenc-compile/src/stages/cross_ctx/flat.rs b/midenc-compile/src/stages/cross_ctx/flat.rs new file mode 100644 index 000000000..db6c427ea --- /dev/null +++ b/midenc-compile/src/stages/cross_ctx/flat.rs @@ -0,0 +1,135 @@ +//! Convertion between the Wasm CM types and the Miden cross-context ABI types. +//! +//! See https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening +//! and https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md +//! for the Wasm CM <-> core Wasm types conversion rules. + +use midenc_hir::{ + types::Abi, AbiParam, ArgumentPurpose, CallConv, FunctionType, Linkage, Signature, StructType, + Type, +}; + +/// Lowering the import or lifting the export function +pub enum FlatteningDirection { + Lift, + Lower, +} + +/// Flattens the given type into a list of ABI parameters. +pub fn flatten_type(ty: &Type) -> Vec { + // see https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening + match ty { + Type::Unknown => todo!(), + Type::Unit => todo!(), + Type::Never => todo!(), + Type::I1 => todo!(), + Type::I8 => todo!(), + Type::U8 => todo!(), + Type::I16 => todo!(), + Type::U16 => todo!(), + Type::I32 => todo!(), + Type::U32 => todo!(), + Type::I64 => todo!(), + Type::U64 => todo!(), + Type::I128 => todo!(), + Type::U128 => todo!(), + Type::U256 => todo!(), + Type::F64 => todo!(), + Type::Felt => vec![AbiParam::new(Type::Felt)], + Type::Ptr(_) => todo!(), + Type::NativePtr(..) => todo!(), + Type::Struct(struct_ty) => { + struct_ty.fields().iter().flat_map(|field| flatten_type(&field.ty)).collect() + } + Type::Array(..) => todo!(), + Type::List(_) => todo!(), + } +} + +/// Flattens the given list of types into a list of ABI parameters. +pub fn flatten_types(tys: &[Type]) -> Vec { + tys.iter().flat_map(flatten_type).collect() +} + +/// Flattens the given Wasm CM level function type +pub fn flatten_function_type(func_ty: &FunctionType, dir: FlatteningDirection) -> Signature { + // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening + // + // For a variety of practical reasons, we need to limit the total number of flattened + // parameters and results, falling back to storing everything in linear memory. The number of + // flattened results is currently limited to 1 due to various parts of the toolchain (notably + // the C ABI) not yet being able to express multi-value returns. Hopefully this limitation is + // temporary and can be lifted before the Component Model is fully standardized. + assert_eq!(func_ty.abi, Abi::Wasm, "expected Wasm CM type"); + const MAX_FLAT_PARAMS: usize = 16; + const MAX_FLAT_RESULTS: usize = 1; + let mut flat_params = flatten_types(&func_ty.params); + let mut flat_results = flatten_types(&func_ty.results); + if flat_params.len() > MAX_FLAT_PARAMS { + // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening + // + // When there are too many flat values, in general, a single `i32` pointer can be passed instead + // (pointing to a tuple in linear memory). When lowering into linear memory, this requires the + // Canonical ABI to call `realloc` to allocate space to put the tuple. + let tuple = Type::Struct(StructType::new(func_ty.params.clone())); + flat_params = vec![AbiParam::sret(Type::Ptr(tuple.into()))]; + } + if flat_results.len() > MAX_FLAT_RESULTS { + // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening + // + // As an optimization, when lowering the return value of an imported function (via `canon + // lower`), the caller can have already allocated space for the return value (e.g., + // efficiently on the stack), passing in an `i32` pointer as an parameter instead of + // returning an `i32` as a return value. + assert_eq!(func_ty.results.len(), 1, "expected a single result"); + let result = func_ty.results.first().expect("unexpected empty results").clone(); + match dir { + FlatteningDirection::Lift => { + flat_results = vec![AbiParam::sret(Type::Ptr(result.into()))]; + } + FlatteningDirection::Lower => { + flat_params.push(AbiParam::sret(Type::Ptr(result.into()))); + flat_results = vec![]; + } + } + } + Signature { + params: flat_params, + results: flat_results, + // TODO: add and use CallConv::CrossCtx here + cc: CallConv::SystemV, + linkage: Linkage::External, + } +} + +/// Checks if the given function signature needs to be transformed, i.e., if it contains a pointer +pub fn needs_transformation(sig: &Signature) -> bool { + sig.params().iter().any(|param| param.purpose == ArgumentPurpose::StructReturn) + || sig + .results() + .iter() + .any(|result| result.purpose == ArgumentPurpose::StructReturn) +} + +/// Asserts that the given core Wasm signature is equivalent to the given flattened signature +/// This checks that we flattened the Wasm CM function type correctly. +pub fn assert_core_wasm_signature_equivalence( + wasm_core_sig: &Signature, + flattened_sig: &Signature, +) { + assert_eq!( + wasm_core_sig.params().len(), + flattened_sig.params().len(), + "expected the same number of params" + ); + assert_eq!( + wasm_core_sig.results().len(), + flattened_sig.results().len(), + "expected the same number of results" + ); + for (wasm_core_param, flattened_param) in + wasm_core_sig.params().iter().zip(flattened_sig.params()) + { + assert_eq!(wasm_core_param.ty, flattened_param.ty, "expected the same param type"); + } +} diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs index 3c6898fd8..dbe210bf4 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -3,12 +3,16 @@ use std::collections::{BTreeMap, VecDeque}; use midenc_hir::{ - diagnostics::Severity, pass::AnalysisManager, types::Abi, AbiParam, Block, Call, CallConv, - ComponentBuilder, ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, - Instruction, Linkage, MidenAbiImport, Signature, SourceSpan, Symbol, Type, UnsafeRef, + diagnostics::Severity, pass::AnalysisManager, types::Abi, Block, Call, ComponentBuilder, + ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, Instruction, + MidenAbiImport, Signature, SourceSpan, Symbol, UnsafeRef, }; use midenc_session::{DiagnosticsHandler, Session}; +use super::flat::{ + assert_core_wasm_signature_equivalence, flatten_function_type, needs_transformation, + FlatteningDirection, +}; use crate::{stage::Stage, CompilerResult, LinkerInput}; /// Generates lifting for imports for the cross-context calls according to the Miden ABI. @@ -79,6 +83,7 @@ impl Stage for LiftImportsCrossCtxStage { let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, + &cabi_import.high_func_ty, import_func_id, import_func_sig.clone(), &session.diagnostics, @@ -109,6 +114,7 @@ impl Stage for LiftImportsCrossCtxStage { /// Generates the lifting function (cross-context Miden ABI -> Wasm CABI) for the given import function. fn generate_lifting_function( component_builder: &mut ComponentBuilder<'_>, + high_func_ty: &FunctionType, import_func_id: FunctionIdent, import_func_sig: Signature, diagnostics: &DiagnosticsHandler, @@ -119,20 +125,22 @@ fn generate_lifting_function( // dbg!(&lifting_module_id); let mut module_builder = component_builder.module(lifting_module_id); + let import_lowered_sig = flatten_function_type(high_func_ty, FlatteningDirection::Lower); + + if needs_transformation(&import_lowered_sig) { + let message = format!( + "Miden CCABI export lowering generation. Signature for exported function {} requires \ + lowering. This is not supported yet.", + import_func_id + ); + return Err(diagnostics.diagnostic(Severity::Error).with_message(message).into_report()); + } + assert_core_wasm_signature_equivalence(&import_func_sig, &import_lowered_sig); + let mut builder = module_builder.function(import_func_id.function, import_func_sig)?; let entry = builder.current_block(); let params = builder.block_params(entry).to_vec(); - // TODO: analyze the signature and speculate what cross-context Miden ABI signature would - // export have. - // For now just assume passing <16 felts and returning 1 and copy the signature - let import_lowered_sig = Signature { - params: vec![AbiParam::new(Type::Felt)], - results: vec![AbiParam::new(Type::Felt)], - // TODO: add CallConv::CrossCtx - cc: CallConv::SystemV, - linkage: Linkage::External, - }; let dfg = builder.data_flow_graph_mut(); if dfg.get_import(&import_func_id).is_none() { dfg.import_function( @@ -150,10 +158,8 @@ fn generate_lifting_function( })?; } // TODO: use the span from the caller - // TODO: lower the params from the Wasm CABI to the cross-context Miden ABI let call = builder.ins().call(import_func_id, ¶ms, SourceSpan::UNKNOWN); // dbg!(&sig); - // TODO: lift the result from the cross-context Miden ABI to Wasm CABI let result = builder.first_result(call); builder.ins().ret(Some(result), SourceSpan::UNKNOWN); let function_id = builder.build()?; diff --git a/midenc-compile/src/stages/cross_ctx/lower_exports.rs b/midenc-compile/src/stages/cross_ctx/lower_exports.rs index afd48054d..372821689 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_exports.rs @@ -6,11 +6,15 @@ use midenc_hir::{ diagnostics::Severity, pass::AnalysisManager, types::Abi::{self, Canonical}, - AbiParam, CallConv, ComponentBuilder, ComponentExport, FunctionType, InstBuilder, - InterfaceFunctionIdent, Linkage, Signature, SourceSpan, Type, + ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, + SourceSpan, }; use midenc_session::{DiagnosticsHandler, Session}; +use super::flat::{ + assert_core_wasm_signature_equivalence, flatten_function_type, needs_transformation, + FlatteningDirection, +}; use crate::{stage::Stage, CompilerResult, LinkerInput}; /// Generates lowering for exports for the cross-context calls according to the Miden ABI. @@ -24,7 +28,8 @@ use crate::{stage::Stage, CompilerResult, LinkerInput}; /// cross-context calls, i.e. using the stack and the advice provider for arguments and results. pub struct LowerExportsCrossCtxStage; -// TODO: swap `lift` and `lower` in the component import/export pretty-printing to sync with +// TODO: NO! Reverse - rename these stages to be inline with WASM CM!!! +// swap `lift` and `lower` in the component import/export pretty-printing to sync with // this stage's terminology (an export is lowered, an import is lifted) impl Stage for LowerExportsCrossCtxStage { @@ -118,19 +123,21 @@ fn generate_lowering_function( // get or create the module for the interface let module_id = export_id.interface.full_name; let mut module_builder = component_builder.module(module_id); - // TODO: analyze the signature and speculate what cross-context Miden ABI signature we need to export. - // For now just assume passing <16 felts and returning 1 and copy the signature - let cross_ctx_export_sig = Signature { - params: vec![AbiParam::new(Type::Felt)], - results: vec![AbiParam::new(Type::Felt)], - // TODO: add CallConv::CrossCtx - cc: CallConv::SystemV, - linkage: Linkage::External, - }; + let cross_ctx_export_sig = + flatten_function_type(&export.function_ty, FlatteningDirection::Lift); + if needs_transformation(&cross_ctx_export_sig) { + let message = format!( + "Miden CCABI export lowering generation. Signature for exported function {} requires \ + lowering. This is not yet supported", + export.function + ); + return Err(diagnostics.diagnostic(Severity::Error).with_message(message).into_report()); + } + assert_core_wasm_signature_equivalence(&export_func_sig, &cross_ctx_export_sig); + let mut builder = module_builder.function(export_id.function, cross_ctx_export_sig.clone())?; let entry = builder.current_block(); let params = builder.block_params(entry).to_vec(); - // TODO: lift the params from the cross-context Miden ABI to the Wasm CABI let dfg = builder.data_flow_graph_mut(); // import the Wasm core function @@ -153,7 +160,6 @@ fn generate_lowering_function( // TODO: use the span from the callee let call = builder.ins().exec(export.function, ¶ms, SourceSpan::UNKNOWN); // dbg!(&sig); - // TODO: lower the result from the Wasm CABI to the cross-context Miden ABI let result = builder.first_result(call); builder.ins().ret(Some(result), SourceSpan::UNKNOWN); let function_id = builder.build()?; diff --git a/midenc-compile/src/stages/cross_ctx/mod.rs b/midenc-compile/src/stages/cross_ctx/mod.rs index e29fc35ba..b61c7eb5f 100644 --- a/midenc-compile/src/stages/cross_ctx/mod.rs +++ b/midenc-compile/src/stages/cross_ctx/mod.rs @@ -1,2 +1,5 @@ +//! Translation between Wasm CM CABI and Miden cross-context ABI (Miden CCABI). + +mod flat; pub(super) mod lift_imports; pub(super) mod lower_exports; From eacba1d076cacd16d303f23dd73fbf9dec158ba5 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Thu, 12 Dec 2024 17:11:16 +0200 Subject: [PATCH 16/26] refactor: rename `CanonAbiImport::interface_function_ty` --- hir/src/component/mod.rs | 10 +++++----- midenc-compile/src/stages/cross_ctx/lift_imports.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hir/src/component/mod.rs b/hir/src/component/mod.rs index 8e2100d55..34522573f 100644 --- a/hir/src/component/mod.rs +++ b/hir/src/component/mod.rs @@ -49,10 +49,10 @@ impl formatter::PrettyPrint for CanonicalOptions { /// the Wasm Component Model Canonical ABI. #[derive(Debug, Clone)] pub struct CanonAbiImport { - /// The interfact function name that is being imported + /// The interface function name that is being imported (Wasm CM level) pub interface_function: InterfaceFunctionIdent, - /// The component(lifted) type of the imported function - pub high_func_ty: FunctionType, + /// The interface function type (Wasm CM level) + pub interface_function_ty: FunctionType, /// Any options associated with this import pub options: CanonicalOptions, } @@ -66,7 +66,7 @@ impl CanonAbiImport { assert_eq!(high_func_ty.abi, Abi::Wasm, "expected Abi::Wasm function type ABI"); Self { interface_function, - high_func_ty, + interface_function_ty: high_func_ty, options, } } @@ -114,7 +114,7 @@ impl formatter::PrettyPrint for ComponentImport { fn render(&self) -> formatter::Document { use crate::formatter::*; let function_ty_str = match self { - ComponentImport::CanonAbiImport(import) => import.high_func_ty.to_string(), + ComponentImport::CanonAbiImport(import) => import.interface_function_ty.to_string(), ComponentImport::MidenAbiImport(import) => import.function_ty.to_string(), }; let name = match self { diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs index dbe210bf4..a61c80eff 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -83,7 +83,7 @@ impl Stage for LiftImportsCrossCtxStage { let (new_import, lifting_func_id) = generate_lifting_function( &mut component_builder, - &cabi_import.high_func_ty, + &cabi_import.interface_function_ty, import_func_id, import_func_sig.clone(), &session.diagnostics, From 8c34a20ddb8d107d9c2636b20fb66f93e5d664d1 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Thu, 12 Dec 2024 17:46:56 +0200 Subject: [PATCH 17/26] chore: remove the hard-coded `cross-ctx*` checks in Miden CCABI lifting/lowering --- .../src/stages/cross_ctx/lift_imports.rs | 6 ---- .../src/stages/cross_ctx/lower_exports.rs | 8 ----- tests/integration/src/compiler_test.rs | 12 +++---- .../src/rust_masm_tests/rust_sdk.rs | 33 +++++++++++-------- 4 files changed, 25 insertions(+), 34 deletions(-) diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs index a61c80eff..af8d027ce 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -40,12 +40,6 @@ impl Stage for LiftImportsCrossCtxStage { return Ok(input); }; - // TODO: remove after handling the lifting for all imports! - if component.name().as_str() != "cross_ctx_note" { - // So far only hardcoded lift imports for the cross_ctx_note - return Ok(LinkerInput::Hir(component)); - } - // dbg!(&component.imports()); // dbg!(&component.modules().keys()); diff --git a/midenc-compile/src/stages/cross_ctx/lower_exports.rs b/midenc-compile/src/stages/cross_ctx/lower_exports.rs index 372821689..5307180cd 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_exports.rs @@ -100,14 +100,6 @@ fn generate_lowering_function( export: ComponentExport, diagnostics: &DiagnosticsHandler, ) -> CompilerResult { - // TODO: remove after handling the lowering for all exports! - if export_id.interface.to_string() != "miden:cross-ctx-account/foo@1.0.0" - && export_id.function.as_str() != "process-felt" - { - // So far we only hardcoded the lowering for the process-felt function - return Ok(export); - } - let export_func_sig = component_builder .signature(&export.function) .ok_or({ diff --git a/tests/integration/src/compiler_test.rs b/tests/integration/src/compiler_test.rs index a7a29bd43..3ed91aa43 100644 --- a/tests/integration/src/compiler_test.rs +++ b/tests/integration/src/compiler_test.rs @@ -1090,7 +1090,7 @@ impl CompilerTest { /// Get the compiled IR MASM program pub fn ir_masm_program(&mut self) -> Arc { if self.ir_masm_program.is_none() { - self.compile_wasm_to_masm_program(); + self.compile_wasm_to_masm_program().unwrap(); } match self.ir_masm_program.as_ref().unwrap().as_ref() { Ok(prog) => prog.clone(), @@ -1101,7 +1101,7 @@ impl CompilerTest { /// Get the compiled [miden_package::Package] pub fn compiled_package(&mut self) -> Arc { if self.package.is_none() { - self.compile_wasm_to_masm_program(); + self.compile_wasm_to_masm_program().unwrap(); } match self.package.as_ref().unwrap().as_ref() { Ok(prog) => prog.clone(), @@ -1112,7 +1112,7 @@ impl CompilerTest { /// Get the MASM source code pub fn masm_src(&mut self) -> String { if self.masm_src.is_none() { - self.compile_wasm_to_masm_program(); + self.compile_wasm_to_masm_program().unwrap(); } self.masm_src.clone().unwrap() } @@ -1126,7 +1126,7 @@ impl CompilerTest { } } - pub(crate) fn compile_wasm_to_masm_program(&mut self) { + pub(crate) fn compile_wasm_to_masm_program(&mut self) -> Result<(), String> { use midenc_codegen_masm::MasmArtifact; use midenc_compile::compile_to_memory_with_pre_assembly_stage; use midenc_hir::pass::AnalysisManager; @@ -1148,13 +1148,13 @@ impl CompilerTest { }; let package = compile_to_memory_with_pre_assembly_stage(self.session.clone(), &mut stage as _) - .map_err(format_report) - .unwrap_or_else(|err| panic!("{err}")) + .map_err(format_report)? .unwrap_mast(); assert!(src.is_some(), "failed to pretty print masm artifact"); self.masm_src = src; self.ir_masm_program = masm_program.map(Ok); self.package = Some(Ok(Arc::new(package))); + Ok(()) } } diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index 2072f8234..ee8836028 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -46,22 +46,27 @@ fn rust_sdk_basic_wallet() { let artifact_name = test.artifact_name().to_string(); test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); - test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); - let package = test.compiled_package(); - let lib = package.unwrap_library(); - let expected_module = "#anon::miden:basic-wallet/basic-wallet@1.0.0"; - let expected_function = "receive-asset"; - let exports = lib - .exports() - .filter(|e| !e.module.to_string().starts_with("intrinsics")) - .map(|e| format!("{}::{}", e.module, e.name.as_str())) - .collect::>(); - dbg!(&exports); - assert!(lib.exports().any(|export| { - export.module.to_string() == expected_module && export.name.as_str() == expected_function - })); + assert!( + test.compile_wasm_to_masm_program().is_err(), + "expected to fail until the lifting/lowering of the heap-allocated data is supported" + ); + // test.expect_masm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.masm")]); + // let package = test.compiled_package(); + // let lib = package.unwrap_library(); + // let expected_module = "#anon::miden:basic-wallet/basic-wallet@1.0.0"; + // let expected_function = "receive-asset"; + // let exports = lib + // .exports() + // .filter(|e| !e.module.to_string().starts_with("intrinsics")) + // .map(|e| format!("{}::{}", e.module, e.name.as_str())) + // .collect::>(); + // dbg!(&exports); + // assert!(lib.exports().any(|export| { + // export.module.to_string() == expected_module && export.name.as_str() == expected_function + // })); } +#[ignore = "until lifting/lowering of the heap-allocated data is supported"] #[test] fn rust_sdk_p2id_note_script() { // Build basic-wallet package From de4f8f751f321bc43c3ad0d3a1d92ac3b617547e Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 16 Dec 2024 11:54:13 +0200 Subject: [PATCH 18/26] feature: implement CanonABI type flattening for app relevant `Type` variants --- frontend-wasm/src/component/translator.rs | 8 -- midenc-compile/src/stages/cross_ctx/flat.rs | 115 ++++++++++++------ .../src/stages/cross_ctx/lift_imports.rs | 10 +- .../src/stages/cross_ctx/lower_exports.rs | 9 +- 4 files changed, 95 insertions(+), 47 deletions(-) diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index 60b0b9871..1fb497c40 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -189,10 +189,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { )?; // Skip the shim and fixups core modules, they are a workaround for // specify the core instance memory and reallod function for the lowering - - // TODO: - // Imported function from the shim has empty module name and "0" as a if name. - if ir_module.name.as_str() != "wit-component:shim" && ir_module.name.as_str() != "wit-component:fixups" { @@ -238,10 +234,6 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> { function: function_id, }; - // TODO: - // Find process_list_felt instead empty module name and "0" function name! - // Follow module_import.index through the shim modules/imports/exports? - let runtime_import_idx = self.lower_imports[index]; // dbg!(&module_import); match self.translate_import( diff --git a/midenc-compile/src/stages/cross_ctx/flat.rs b/midenc-compile/src/stages/cross_ctx/flat.rs index db6c427ea..6f629c962 100644 --- a/midenc-compile/src/stages/cross_ctx/flat.rs +++ b/midenc-compile/src/stages/cross_ctx/flat.rs @@ -5,8 +5,8 @@ //! for the Wasm CM <-> core Wasm types conversion rules. use midenc_hir::{ - types::Abi, AbiParam, ArgumentPurpose, CallConv, FunctionType, Linkage, Signature, StructType, - Type, + types::Abi, AbiParam, ArgumentExtension, ArgumentPurpose, CallConv, FunctionType, Linkage, + Signature, StructType, Type, }; /// Lowering the import or lifting the export function @@ -15,44 +15,85 @@ pub enum FlatteningDirection { Lower, } -/// Flattens the given type into a list of ABI parameters. -pub fn flatten_type(ty: &Type) -> Vec { +/// Flattens the given CanonABI type into a list of ABI parameters. +pub fn flatten_type(ty: &Type) -> Result, String> { // see https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening - match ty { - Type::Unknown => todo!(), - Type::Unit => todo!(), - Type::Never => todo!(), - Type::I1 => todo!(), - Type::I8 => todo!(), - Type::U8 => todo!(), - Type::I16 => todo!(), - Type::U16 => todo!(), - Type::I32 => todo!(), - Type::U32 => todo!(), - Type::I64 => todo!(), - Type::U64 => todo!(), - Type::I128 => todo!(), - Type::U128 => todo!(), - Type::U256 => todo!(), - Type::F64 => todo!(), + Ok(match ty { + Type::Unit => vec![], + Type::I1 => vec![AbiParam { + ty: Type::I32, + purpose: ArgumentPurpose::Default, + extension: ArgumentExtension::Zext, + }], + Type::I8 => vec![AbiParam { + ty: Type::I32, + purpose: ArgumentPurpose::Default, + extension: ArgumentExtension::Sext, + }], + Type::U8 => vec![AbiParam { + ty: Type::I32, + purpose: ArgumentPurpose::Default, + extension: ArgumentExtension::Zext, + }], + Type::I16 => vec![AbiParam { + ty: Type::I32, + purpose: ArgumentPurpose::Default, + extension: ArgumentExtension::Sext, + }], + Type::U16 => vec![AbiParam { + ty: Type::I32, + purpose: ArgumentPurpose::Default, + extension: ArgumentExtension::Zext, + }], + Type::I32 => vec![AbiParam::new(Type::I32)], + Type::U32 => vec![AbiParam::new(Type::I32)], + Type::I64 => vec![AbiParam::new(Type::I64)], + Type::U64 => vec![AbiParam::new(Type::I64)], + Type::I128 | Type::U128 | Type::U256 => { + panic!("CanonABI type flattening: not yet implemented {}", ty) + } + Type::F64 => { + let message = "CanonABI type flattening: unexpected f64 type".to_string(); + return Err(message); + } Type::Felt => vec![AbiParam::new(Type::Felt)], - Type::Ptr(_) => todo!(), - Type::NativePtr(..) => todo!(), - Type::Struct(struct_ty) => { - struct_ty.fields().iter().flat_map(|field| flatten_type(&field.ty)).collect() + Type::Struct(struct_ty) => struct_ty + .fields() + .iter() + .map(|field| flatten_type(&field.ty)) + .collect::>, String>>()? + .into_iter() + .flatten() + .collect(), + Type::Array(elem_ty, len) => vec![AbiParam::new(*elem_ty.clone()); *len], + Type::List(elem_ty) => vec![ + // pointer to the list element type + AbiParam::sret(*elem_ty.clone()), + // length of the list + AbiParam::new(Type::I32), + ], + Type::Unknown | Type::Never | Type::Ptr(_) | Type::NativePtr(..) => { + panic!("CanonABI type flattening: unexpected {} type", ty) } - Type::Array(..) => todo!(), - Type::List(_) => todo!(), - } + }) } -/// Flattens the given list of types into a list of ABI parameters. -pub fn flatten_types(tys: &[Type]) -> Vec { - tys.iter().flat_map(flatten_type).collect() +/// Flattens the given list of CanonABI types into a list of ABI parameters. +pub fn flatten_types(tys: &[Type]) -> Result, String> { + Ok(tys + .iter() + .map(flatten_type) + .collect::>, String>>()? + .into_iter() + .flatten() + .collect()) } -/// Flattens the given Wasm CM level function type -pub fn flatten_function_type(func_ty: &FunctionType, dir: FlatteningDirection) -> Signature { +/// Flattens the given CanonABI function type +pub fn flatten_function_type( + func_ty: &FunctionType, + dir: FlatteningDirection, +) -> Result { // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening // // For a variety of practical reasons, we need to limit the total number of flattened @@ -63,8 +104,8 @@ pub fn flatten_function_type(func_ty: &FunctionType, dir: FlatteningDirection) - assert_eq!(func_ty.abi, Abi::Wasm, "expected Wasm CM type"); const MAX_FLAT_PARAMS: usize = 16; const MAX_FLAT_RESULTS: usize = 1; - let mut flat_params = flatten_types(&func_ty.params); - let mut flat_results = flatten_types(&func_ty.results); + let mut flat_params = flatten_types(&func_ty.params)?; + let mut flat_results = flatten_types(&func_ty.results)?; if flat_params.len() > MAX_FLAT_PARAMS { // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening // @@ -93,13 +134,13 @@ pub fn flatten_function_type(func_ty: &FunctionType, dir: FlatteningDirection) - } } } - Signature { + Ok(Signature { params: flat_params, results: flat_results, // TODO: add and use CallConv::CrossCtx here cc: CallConv::SystemV, linkage: Linkage::External, - } + }) } /// Checks if the given function signature needs to be transformed, i.e., if it contains a pointer diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs index af8d027ce..da0c31a3a 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -119,7 +119,15 @@ fn generate_lifting_function( // dbg!(&lifting_module_id); let mut module_builder = component_builder.module(lifting_module_id); - let import_lowered_sig = flatten_function_type(high_func_ty, FlatteningDirection::Lower); + let import_lowered_sig = flatten_function_type(high_func_ty, FlatteningDirection::Lower) + .map_err(|e| { + let message = format!( + "Miden CCABI import lifting generation. Signature for imported function {} \ + requires flattening. Error: {}", + import_func_id.function, e + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })?; if needs_transformation(&import_lowered_sig) { let message = format!( diff --git a/midenc-compile/src/stages/cross_ctx/lower_exports.rs b/midenc-compile/src/stages/cross_ctx/lower_exports.rs index 5307180cd..917316f0f 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_exports.rs @@ -116,7 +116,14 @@ fn generate_lowering_function( let module_id = export_id.interface.full_name; let mut module_builder = component_builder.module(module_id); let cross_ctx_export_sig = - flatten_function_type(&export.function_ty, FlatteningDirection::Lift); + flatten_function_type(&export.function_ty, FlatteningDirection::Lift).map_err(|e| { + let message = format!( + "Miden CCABI export lowering generation. Signature for exported function {} \ + requires flattening. Error: {}", + export.function, e + ); + diagnostics.diagnostic(Severity::Error).with_message(message).into_report() + })?; if needs_transformation(&cross_ctx_export_sig) { let message = format!( "Miden CCABI export lowering generation. Signature for exported function {} requires \ From 24925c466cf57605a9ebcd524ee6e3f82ee9fcb6 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 16 Dec 2024 12:16:22 +0200 Subject: [PATCH 19/26] feature: add `CallConv::CrossCtx` calling convention for cross-context `call`-able functions --- hir/src/asm/builder.rs | 2 +- hir/src/function.rs | 8 ++++++++ midenc-compile/src/stages/cross_ctx/flat.rs | 3 +-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/hir/src/asm/builder.rs b/hir/src/asm/builder.rs index 103d9c131..e65061ab8 100644 --- a/hir/src/asm/builder.rs +++ b/hir/src/asm/builder.rs @@ -2211,7 +2211,7 @@ fn execute_call( } match import.signature.cc { // For now, we're treating all calling conventions the same as SystemV - CallConv::Fast | CallConv::SystemV | CallConv::Kernel => { + CallConv::Fast | CallConv::SystemV | CallConv::Kernel | CallConv::CrossCtx => { // Visit the argument list in reverse (so that the top of the stack on entry // is the first argument), and allocate elements based on the argument types. let mut elements_needed = 0; diff --git a/hir/src/function.rs b/hir/src/function.rs index 5dbcc76e1..e0ca4e9b6 100644 --- a/hir/src/function.rs +++ b/hir/src/function.rs @@ -62,6 +62,13 @@ pub enum CallConv { /// /// In all other respects, this calling convention is the same as `SystemV` Kernel, + /// A function with this calling convention is expected to be called using the `call` + /// instruction. Since execution moves to a different contexe he callee does not have access to + /// caller's memory, so arguments and results are passed through the stack or through the + /// advice provider. + /// + /// see https://0xpolygonmiden.github.io/miden-vm/user_docs/assembly/execution_contexts.html + CrossCtx, } impl fmt::Display for CallConv { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -70,6 +77,7 @@ impl fmt::Display for CallConv { Self::SystemV => f.write_str("C"), Self::Wasm => f.write_str("wasm"), Self::Kernel => f.write_str("kernel"), + Self::CrossCtx => f.write_str("cctx"), } } } diff --git a/midenc-compile/src/stages/cross_ctx/flat.rs b/midenc-compile/src/stages/cross_ctx/flat.rs index 6f629c962..7e640f2bd 100644 --- a/midenc-compile/src/stages/cross_ctx/flat.rs +++ b/midenc-compile/src/stages/cross_ctx/flat.rs @@ -137,8 +137,7 @@ pub fn flatten_function_type( Ok(Signature { params: flat_params, results: flat_results, - // TODO: add and use CallConv::CrossCtx here - cc: CallConv::SystemV, + cc: CallConv::CrossCtx, linkage: Linkage::External, }) } From 413b4ac2cef5cc9a381918d786809a1bab208c5a Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 16 Dec 2024 12:24:45 +0200 Subject: [PATCH 20/26] fix: use import/export core function's span for the generated lifting/lowering functions. --- midenc-compile/src/stages/cross_ctx/lift_imports.rs | 8 +++++--- midenc-compile/src/stages/cross_ctx/lower_exports.rs | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lift_imports.rs index da0c31a3a..ad9536f43 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_imports.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, VecDeque}; +use miden_assembly::Spanned; use midenc_hir::{ diagnostics::Severity, pass::AnalysisManager, types::Abi, Block, Call, ComponentBuilder, ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, Instruction, @@ -80,6 +81,7 @@ impl Stage for LiftImportsCrossCtxStage { &cabi_import.interface_function_ty, import_func_id, import_func_sig.clone(), + core_import_func_id.function.span(), &session.diagnostics, )?; lifted_imports.insert(lifting_func_id, new_import.into()); @@ -111,6 +113,7 @@ fn generate_lifting_function( high_func_ty: &FunctionType, import_func_id: FunctionIdent, import_func_sig: Signature, + span: SourceSpan, diagnostics: &DiagnosticsHandler, ) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { // get or create the module for the interface @@ -159,11 +162,10 @@ fn generate_lifting_function( diagnostics.diagnostic(Severity::Error).with_message(message).into_report() })?; } - // TODO: use the span from the caller - let call = builder.ins().call(import_func_id, ¶ms, SourceSpan::UNKNOWN); + let call = builder.ins().call(import_func_id, ¶ms, span); // dbg!(&sig); let result = builder.first_result(call); - builder.ins().ret(Some(result), SourceSpan::UNKNOWN); + builder.ins().ret(Some(result), span); let function_id = builder.build()?; module_builder.build()?; let component_import = MidenAbiImport::new(FunctionType { diff --git a/midenc-compile/src/stages/cross_ctx/lower_exports.rs b/midenc-compile/src/stages/cross_ctx/lower_exports.rs index 917316f0f..da7768900 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_exports.rs @@ -2,12 +2,12 @@ use std::collections::BTreeMap; +use miden_assembly::Spanned; use midenc_hir::{ diagnostics::Severity, pass::AnalysisManager, types::Abi::{self, Canonical}, ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, - SourceSpan, }; use midenc_session::{DiagnosticsHandler, Session}; @@ -156,11 +156,11 @@ fn generate_lowering_function( diagnostics.diagnostic(Severity::Error).with_message(message).into_report() })?; } - // TODO: use the span from the callee - let call = builder.ins().exec(export.function, ¶ms, SourceSpan::UNKNOWN); + let span = export.function.function.span(); + let call = builder.ins().exec(export.function, ¶ms, span); // dbg!(&sig); let result = builder.first_result(call); - builder.ins().ret(Some(result), SourceSpan::UNKNOWN); + builder.ins().ret(Some(result), span); let function_id = builder.build()?; module_builder.build()?; let component_export = ComponentExport { From f7f3b74a4b8ef477ce9950dcd2ac07c294987e66 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 16 Dec 2024 12:39:03 +0200 Subject: [PATCH 21/26] refactor: rename `LowerExportsCrossCtxStage` -> `LiftExportsCrossCtxStage` and `LiftImportsCrossCtxStage` -> `LowerImportsCrossCtxStage` to be in sync with Wasm CM terminology (`canon lift` for component exports and `canon lower` for component imports) --- midenc-compile/src/lib.rs | 8 +- .../{lower_exports.rs => lift_exports.rs} | 45 +++++------ .../{lift_imports.rs => lower_imports.rs} | 75 ++++++++++--------- midenc-compile/src/stages/cross_ctx/mod.rs | 4 +- midenc-compile/src/stages/mod.rs | 2 +- .../expected/rust_sdk/cross_ctx_note.masm | 6 +- 6 files changed, 68 insertions(+), 72 deletions(-) rename midenc-compile/src/stages/cross_ctx/{lower_exports.rs => lift_exports.rs} (77%) rename midenc-compile/src/stages/cross_ctx/{lift_imports.rs => lower_imports.rs} (81%) diff --git a/midenc-compile/src/lib.rs b/midenc-compile/src/lib.rs index 474b28125..e49e2b02e 100644 --- a/midenc-compile/src/lib.rs +++ b/midenc-compile/src/lib.rs @@ -84,8 +84,8 @@ where }; let mut stages = ParseStage .next(SemanticAnalysisStage) - .next(LowerExportsCrossCtxStage) - .next(LiftImportsCrossCtxStage) + .next(LiftExportsCrossCtxStage) + .next(LowerImportsCrossCtxStage) .next_optional(ApplyRewritesStage) .collect(LinkerStage) .next(CodegenStage) @@ -110,8 +110,8 @@ fn compile_inputs( ) -> CompilerResult { let mut stages = ParseStage .next(SemanticAnalysisStage) - .next(LowerExportsCrossCtxStage) - .next(LiftImportsCrossCtxStage) + .next(LiftExportsCrossCtxStage) + .next(LowerImportsCrossCtxStage) .next_optional(ApplyRewritesStage) .collect(LinkerStage) .next(CodegenStage) diff --git a/midenc-compile/src/stages/cross_ctx/lower_exports.rs b/midenc-compile/src/stages/cross_ctx/lift_exports.rs similarity index 77% rename from midenc-compile/src/stages/cross_ctx/lower_exports.rs rename to midenc-compile/src/stages/cross_ctx/lift_exports.rs index da7768900..feacaeced 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_exports.rs @@ -1,4 +1,4 @@ -//! Lowering the exports for cross-context calls. +//! lifting the exports for cross-context calls. use std::collections::BTreeMap; @@ -17,22 +17,18 @@ use super::flat::{ }; use crate::{stage::Stage, CompilerResult, LinkerInput}; -/// Generates lowering for exports for the cross-context calls according to the Miden ABI. +/// Generates lifting for exports for the cross-context calls according to the Miden ABI. /// -/// For each component export ensure a module for each interface that has a lowering +/// For each component export ensure a module for each interface that has a lifting /// function, i.e. a function that takes parameters according to the cross-context Miden -/// ABI, lifts them to the Wasm CABI, calls the core Wasm module exported function, -/// lowers the results to the cross-context Miden ABI +/// ABI, converts them to the Wasm CABI, calls the core Wasm module exported function, +/// converts the results to the cross-context Miden ABI /// /// After this stage all exported functons are expected to be called using the Miden ABI for /// cross-context calls, i.e. using the stack and the advice provider for arguments and results. -pub struct LowerExportsCrossCtxStage; +pub struct LiftExportsCrossCtxStage; -// TODO: NO! Reverse - rename these stages to be inline with WASM CM!!! -// swap `lift` and `lower` in the component import/export pretty-printing to sync with -// this stage's terminology (an export is lowered, an import is lifted) - -impl Stage for LowerExportsCrossCtxStage { +impl Stage for LiftExportsCrossCtxStage { type Input = LinkerInput; type Output = LinkerInput; @@ -53,13 +49,12 @@ impl Stage for LowerExportsCrossCtxStage { let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); - let mut lowered_exports: BTreeMap = - BTreeMap::new(); + let mut lifted_exports: BTreeMap = BTreeMap::new(); let exports = component_builder.exports().clone(); for (id, export) in exports.into_iter() { if let Canonical = export.function_ty.abi() { - // skip exports that are already lowered - lowered_exports.insert(id, export); + // skip exports that are already lifted + lifted_exports.insert(id, export); continue; } if let Some(entrypoint) = &session.options.entrypoint { @@ -70,20 +65,20 @@ impl Stage for LowerExportsCrossCtxStage { export.function.function.as_str() ); if entrypoint == &export_core_func { - lowered_exports.insert(id, export); + lifted_exports.insert(id, export); continue; } } - let new_export = generate_lowering_function( + let new_export = generate_lifting_function( &mut component_builder, id, export, &session.diagnostics, )?; - lowered_exports.insert(id, new_export); + lifted_exports.insert(id, new_export); } - let component_builder = component_builder.with_exports(lowered_exports); + let component_builder = component_builder.with_exports(lifted_exports); let component = component_builder.build(); @@ -94,7 +89,7 @@ impl Stage for LowerExportsCrossCtxStage { } } -fn generate_lowering_function( +fn generate_lifting_function( component_builder: &mut ComponentBuilder, export_id: InterfaceFunctionIdent, export: ComponentExport, @@ -104,7 +99,7 @@ fn generate_lowering_function( .signature(&export.function) .ok_or({ let message = format!( - "Miden CCABI export lowering generation. Cannot find signature for exported \ + "Miden CCABI export lifting generation. Cannot find signature for exported \ function {}", export.function ); @@ -118,7 +113,7 @@ fn generate_lowering_function( let cross_ctx_export_sig = flatten_function_type(&export.function_ty, FlatteningDirection::Lift).map_err(|e| { let message = format!( - "Miden CCABI export lowering generation. Signature for exported function {} \ + "Miden CCABI export lifting generation. Signature for exported function {} \ requires flattening. Error: {}", export.function, e ); @@ -126,8 +121,8 @@ fn generate_lowering_function( })?; if needs_transformation(&cross_ctx_export_sig) { let message = format!( - "Miden CCABI export lowering generation. Signature for exported function {} requires \ - lowering. This is not yet supported", + "Miden CCABI export lifting generation. Signature for exported function {} requires \ + lifting. This is not yet supported", export.function ); return Err(diagnostics.diagnostic(Severity::Error).with_message(message).into_report()); @@ -148,7 +143,7 @@ fn generate_lowering_function( ) .map_err(|_e| { let message = format!( - "Miden CCABI export lowering generation. Lowering function with name {} in module \ + "Miden CCABI export lifting generation. lifting function with name {} in module \ {} with signature {export_func_sig:?} is already imported (function call) with a \ different signature", export.function.function, export.function.module diff --git a/midenc-compile/src/stages/cross_ctx/lift_imports.rs b/midenc-compile/src/stages/cross_ctx/lower_imports.rs similarity index 81% rename from midenc-compile/src/stages/cross_ctx/lift_imports.rs rename to midenc-compile/src/stages/cross_ctx/lower_imports.rs index ad9536f43..2a0973a07 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_imports.rs @@ -1,4 +1,4 @@ -//! Lifting the imports into the Miden ABI for the cross-context calls +//! lowering the imports into the Miden ABI for the cross-context calls use std::collections::{BTreeMap, VecDeque}; @@ -16,16 +16,16 @@ use super::flat::{ }; use crate::{stage::Stage, CompilerResult, LinkerInput}; -/// Generates lifting for imports for the cross-context calls according to the Miden ABI. +/// Generates lowering for imports for the cross-context calls according to the Miden ABI. /// -/// For each component import ensure a module for each interface that has a lifting function i.e. a -/// function that takes the arguments according to the Wasm CABI, lowers them to the cross-context +/// For each component import ensure a module for each interface that has a lowering function i.e. a +/// function that takes the arguments according to the Wasm CABI, converts them to the cross-context /// Miden ABI, calls the imported function with the lowered arguments, takes the result -/// (cross-context Miden ABI), and lifts it to the Wasm CABI. -/// The calls to the component import is switched to the generated lifting function. -pub struct LiftImportsCrossCtxStage; +/// (cross-context Miden ABI), and converts it to the Wasm CABI. +/// The calls to the component import is switched to the generated lowering function. +pub struct LowerImportsCrossCtxStage; -impl Stage for LiftImportsCrossCtxStage { +impl Stage for LowerImportsCrossCtxStage { type Input = LinkerInput; type Output = LinkerInput; @@ -46,12 +46,12 @@ impl Stage for LiftImportsCrossCtxStage { let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics); - let mut lifted_imports: BTreeMap = BTreeMap::new(); + let mut lowered_imports: BTreeMap = BTreeMap::new(); let imports = component_builder.imports().clone(); for (core_import_func_id, import) in imports.into_iter() { if let ComponentImport::MidenAbiImport(_) = import { - // skip imports that are already lifted - lifted_imports.insert(core_import_func_id, import); + // skip imports that are already lowered + lowered_imports.insert(core_import_func_id, import); continue; } let cabi_import = import.unwrap_canon_abi_import(); @@ -64,7 +64,7 @@ impl Stage for LiftImportsCrossCtxStage { .import_signature(&import_func_id) .ok_or({ let message = format!( - "Miden CCABI import lifting generation. Cannot find signature for Wasm \ + "Miden CCABI import lowering generation. Cannot find signature for Wasm \ CABI imported function {}", import_func_id ); @@ -76,7 +76,7 @@ impl Stage for LiftImportsCrossCtxStage { })? .clone(); - let (new_import, lifting_func_id) = generate_lifting_function( + let (new_import, lowering_func_id) = generate_lowering_function( &mut component_builder, &cabi_import.interface_function_ty, import_func_id, @@ -84,11 +84,11 @@ impl Stage for LiftImportsCrossCtxStage { core_import_func_id.function.span(), &session.diagnostics, )?; - lifted_imports.insert(lifting_func_id, new_import.into()); + lowered_imports.insert(lowering_func_id, new_import.into()); - call_lifting_function( + call_lowering_function( &mut component_builder, - lifting_func_id, + lowering_func_id, import_func_id, import_func_sig, analyses, @@ -96,7 +96,7 @@ impl Stage for LiftImportsCrossCtxStage { )?; } - let component_builder = component_builder.with_imports(lifted_imports); + let component_builder = component_builder.with_imports(lowered_imports); let component = component_builder.build(); @@ -107,8 +107,8 @@ impl Stage for LiftImportsCrossCtxStage { } } -/// Generates the lifting function (cross-context Miden ABI -> Wasm CABI) for the given import function. -fn generate_lifting_function( +/// Generates the lowering function (cross-context Miden ABI -> Wasm CABI) for the given import function. +fn generate_lowering_function( component_builder: &mut ComponentBuilder<'_>, high_func_ty: &FunctionType, import_func_id: FunctionIdent, @@ -117,15 +117,15 @@ fn generate_lifting_function( diagnostics: &DiagnosticsHandler, ) -> CompilerResult<(MidenAbiImport, FunctionIdent)> { // get or create the module for the interface - let lifting_module_id = - Symbol::intern(format!("lift-imports-{}", import_func_id.module.as_str())); - // dbg!(&lifting_module_id); - let mut module_builder = component_builder.module(lifting_module_id); + let lowering_module_id = + Symbol::intern(format!("lower-imports-{}", import_func_id.module.as_str())); + // dbg!(&lowering_module_id); + let mut module_builder = component_builder.module(lowering_module_id); let import_lowered_sig = flatten_function_type(high_func_ty, FlatteningDirection::Lower) .map_err(|e| { let message = format!( - "Miden CCABI import lifting generation. Signature for imported function {} \ + "Miden CCABI import lowering generation. Signature for imported function {} \ requires flattening. Error: {}", import_func_id.function, e ); @@ -155,8 +155,9 @@ fn generate_lifting_function( ) .map_err(|_e| { let message = format!( - "Lifting function with name {} in module {} with signature {import_lowered_sig:?} \ - is already imported (function call) with a different signature", + "lowering function with name {} in module {} with signature \ + {import_lowered_sig:?} is already imported (function call) with a different \ + signature", import_func_id.function, import_func_id.module ); diagnostics.diagnostic(Severity::Error).with_message(message).into_report() @@ -217,10 +218,10 @@ fn rewrite_calls(function: &mut Function, from: FunctionIdent, to: FunctionIdent dirty } -/// Replaces calls to the imported functions with calls to the lifting functions. -fn call_lifting_function( +/// Replaces calls to the imported functions with calls to the lowering functions. +fn call_lowering_function( component_builder: &mut ComponentBuilder<'_>, - lifting_func_id: FunctionIdent, + lowering_func_id: FunctionIdent, import_func_id: FunctionIdent, import_func_sig: Signature, analyses: &mut AnalysisManager, @@ -228,8 +229,8 @@ fn call_lifting_function( ) -> Result<(), miden_assembly::Report> { let mut modules = Vec::new(); for (id, mut module) in component_builder.take_modules() { - if module.name == lifting_func_id.module { - // Skip the module with the lifting function + if module.name == lowering_func_id.module { + // Skip the module with the lowering function modules.push((id, module)); continue; } @@ -239,20 +240,20 @@ fn call_lifting_function( // `remove` will return `None`. let mut cursor = module.cursor_mut(); while let Some(mut function) = cursor.remove() { - if rewrite_calls(&mut function, import_func_id, lifting_func_id) { + if rewrite_calls(&mut function, import_func_id, lowering_func_id) { // Invalidate the analyses for the function since we've modified it analyses.invalidate::(&function.id); - // Import the lifting function if it's not already imported + // Import the lowering function if it's not already imported let dfg = &mut function.dfg; - if dfg.get_import(&lifting_func_id).is_none() { + if dfg.get_import(&lowering_func_id).is_none() { dfg.import_function( - lifting_func_id.module, - lifting_func_id.function, + lowering_func_id.module, + lowering_func_id.function, import_func_sig.clone(), ) .map_err(|_e| { let message = format!( - "Lifting function with name {} in module {} with signature \ + "lowering function with name {} in module {} with signature \ {import_func_sig:?} is already imported (function call) with a \ different signature", import_func_id.function, import_func_id.module diff --git a/midenc-compile/src/stages/cross_ctx/mod.rs b/midenc-compile/src/stages/cross_ctx/mod.rs index b61c7eb5f..c9043b50b 100644 --- a/midenc-compile/src/stages/cross_ctx/mod.rs +++ b/midenc-compile/src/stages/cross_ctx/mod.rs @@ -1,5 +1,5 @@ //! Translation between Wasm CM CABI and Miden cross-context ABI (Miden CCABI). mod flat; -pub(super) mod lift_imports; -pub(super) mod lower_exports; +pub(super) mod lift_exports; +pub(super) mod lower_imports; diff --git a/midenc-compile/src/stages/mod.rs b/midenc-compile/src/stages/mod.rs index b3a62607a..eb819b0be 100644 --- a/midenc-compile/src/stages/mod.rs +++ b/midenc-compile/src/stages/mod.rs @@ -25,7 +25,7 @@ mod sema; pub use self::{ assemble::{Artifact, AssembleStage}, codegen::CodegenStage, - cross_ctx::{lift_imports::LiftImportsCrossCtxStage, lower_exports::LowerExportsCrossCtxStage}, + cross_ctx::{lift_exports::LiftExportsCrossCtxStage, lower_imports::LowerImportsCrossCtxStage}, link::{LinkerInput, LinkerOutput, LinkerStage}, parse::{ParseOutput, ParseStage}, rewrite::ApplyRewritesStage, diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.masm b/tests/integration/expected/rust_sdk/cross_ctx_note.masm index 3d2043a39..df1250200 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.masm +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.masm @@ -1,4 +1,4 @@ -# mod #anon::lift-imports-miden:cross-ctx-account/foo@1.0.0 +# mod #anon::lower-imports-miden:cross-ctx-account/foo@1.0.0 use.miden:cross-ctx-account/foo@1.0.0 @@ -10,7 +10,7 @@ end # mod cross_ctx_note use.intrinsics::mem -use.lift-imports-miden:cross-ctx-account/foo@1.0.0 +use.lower-imports-miden:cross-ctx-account/foo@1.0.0 use.miden:cross-ctx-account/foo@1.0.0 proc."cross_ctx_note::bindings::__link_custom_section_describing_imports" @@ -422,7 +422,7 @@ end export."miden:base/note-script@1.0.0#note-script" exec."wit_bindgen_rt::run_ctors_once" push.7 - exec.::lift-imports-miden:cross-ctx-account/foo@1.0.0::"process-felt" + exec.::lower-imports-miden:cross-ctx-account/foo@1.0.0::"process-felt" push.10 assert_eq end From 8570205916e839f0685fc4f9d24c63f18b52bb15 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Mon, 16 Dec 2024 15:08:00 +0200 Subject: [PATCH 22/26] refactor: rename `Felt::from_u32_unchecked` to `Felt::from_u32` --- frontend-wasm/src/intrinsics/felt.rs | 2 +- sdk/stdlib-sys/src/intrinsics/felt.rs | 18 ++--- .../expected/rust_sdk/cross_ctx_account.wat | 10 +-- .../expected/rust_sdk/cross_ctx_note.wat | 12 ++-- .../miden_sdk_account_test.wat | 14 ++-- .../rust-sdk/basic-wallet/src/bindings.rs | 66 +++++++++---------- .../cross-ctx-account/src/bindings.rs | 42 ++++++------ .../rust-sdk/cross-ctx-note/src/bindings.rs | 38 +++++------ .../rust-sdk/wit-sdk/miden-core-import.wit | 2 +- 9 files changed, 103 insertions(+), 101 deletions(-) diff --git a/frontend-wasm/src/intrinsics/felt.rs b/frontend-wasm/src/intrinsics/felt.rs index 9f6437549..cbbda05c7 100644 --- a/frontend-wasm/src/intrinsics/felt.rs +++ b/frontend-wasm/src/intrinsics/felt.rs @@ -20,7 +20,7 @@ pub(crate) fn convert_felt_intrinsics( let inst = builder.ins().cast(args[0], Felt, span); vec![inst] } - "from_u32_unchecked" => { + "from_u32" => { assert_eq!(args.len(), 1, "{} takes exactly one argument", func_id); let inst = builder.ins().bitcast(args[0], Felt, span); vec![inst] diff --git a/sdk/stdlib-sys/src/intrinsics/felt.rs b/sdk/stdlib-sys/src/intrinsics/felt.rs index 3fba8e493..67c847ae0 100644 --- a/sdk/stdlib-sys/src/intrinsics/felt.rs +++ b/sdk/stdlib-sys/src/intrinsics/felt.rs @@ -7,8 +7,8 @@ extern "C" { #[link_name = "from-u64-unchecked"] fn extern_from_u64_unchecked(value: u64) -> Felt; - #[link_name = "from-u32-unchecked"] - fn extern_from_u32_unchecked(value: u32) -> Felt; + #[link_name = "from-u32"] + fn extern_from_u32(value: u32) -> Felt; #[link_name = "as_u64"] fn extern_as_u64(felt: Felt) -> u64; @@ -71,11 +71,13 @@ extern "C" { macro_rules! felt { // Trigger a compile-time error if the value is not a constant ($value:literal) => {{ - // const VALUE: u64 = $value as u64; + const VALUE: u64 = $value as u64; // assert!(VALUE <= Felt::M, "Invalid Felt value, must be >= 0 and <= 2^64 - 2^32 + 1"); - // Temporarily switch to `from_u32_unchecked` to use `bitcast` and avoid checks. - const VALUE: u32 = $value as u32; - Felt::from_u32_unchecked(VALUE) + // Temporarily switch to `from_u32` to use `bitcast` and avoid checks. + // see https://github.com/0xPolygonMiden/compiler/issues/361 + assert!(VALUE <= u32::MAX as u64, "Invalid value, must be >= 0 and <= 2^32"); + const VALUE_U32: u32 = $value as u32; + Felt::from_u32(VALUE_U32) }}; } @@ -100,8 +102,8 @@ impl Felt { } #[inline(always)] - pub fn from_u32_unchecked(value: u32) -> Self { - unsafe { extern_from_u32_unchecked(value) } + pub fn from_u32(value: u32) -> Self { + unsafe { extern_from_u32(value) } } #[inline(always)] diff --git a/tests/integration/expected/rust_sdk/cross_ctx_account.wat b/tests/integration/expected/rust_sdk/cross_ctx_account.wat index af61b90be..c46fcf3b0 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_account.wat +++ b/tests/integration/expected/rust_sdk/cross_ctx_account.wat @@ -18,7 +18,7 @@ (type (;0;) (func (param "a" float32) (param "b" float32) (result float32))) (export (;0;) "add" (func (type 0))) (type (;1;) (func (param "a" u32) (result float32))) - (export (;1;) "from-u32-unchecked" (func (type 1))) + (export (;1;) "from-u32" (func (type 1))) ) ) (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;2;) (type 2))) @@ -31,7 +31,7 @@ (type (;5;) (func (param i32 i32 i32 i32) (result i32))) (type (;6;) (func (param f32) (result f32))) (type (;7;) (func (param i32 i32 i32) (result i32))) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32 (;0;) (type 0))) (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;1;) (type 1))) (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;2;) (type 2))) (func $__wasm_call_ctors (;3;) (type 3)) @@ -67,7 +67,7 @@ call $wit_bindgen_rt::run_ctors_once local.get 0 i32.const 3 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 call $miden_stdlib_sys::intrinsics::felt::extern_add ) (func $cabi_realloc_wit_bindgen_0_28_0 (;8;) (type 5) (param i32 i32 i32 i32) (result i32) @@ -206,11 +206,11 @@ ) (alias export 2 "add" (func (;0;))) (core func (;0;) (canon lower (func 0))) - (alias export 2 "from-u32-unchecked" (func (;1;))) + (alias export 2 "from-u32" (func (;1;))) (core func (;1;) (canon lower (func 1))) (core instance (;0;) (export "add" (func 0)) - (export "from-u32-unchecked" (func 1)) + (export "from-u32" (func 1)) ) (alias export 1 "heap-base" (func (;2;))) (core func (;2;) (canon lower (func 2))) diff --git a/tests/integration/expected/rust_sdk/cross_ctx_note.wat b/tests/integration/expected/rust_sdk/cross_ctx_note.wat index e51fd9554..5a920ab02 100644 --- a/tests/integration/expected/rust_sdk/cross_ctx_note.wat +++ b/tests/integration/expected/rust_sdk/cross_ctx_note.wat @@ -26,7 +26,7 @@ (type (;4;) (instance (type (;0;) (func (param "a" u32) (result float32))) - (export (;0;) "from-u32-unchecked" (func (type 0))) + (export (;0;) "from-u32" (func (type 0))) (type (;1;) (func (param "a" float32) (param "b" float32))) (export (;1;) "assert-eq" (func (type 1))) ) @@ -41,7 +41,7 @@ (type (;5;) (func (param i32 i32) (result i32))) (type (;6;) (func (param i32 i32 i32 i32) (result i32))) (type (;7;) (func (param i32 i32 i32) (result i32))) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32 (;0;) (type 0))) (import "miden:cross-ctx-account/foo@1.0.0" "process-felt" (func $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import (;1;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "assert-eq" (func $miden_stdlib_sys::intrinsics::felt::extern_assert_eq (;2;) (type 2))) (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;3;) (type 3))) @@ -77,10 +77,10 @@ (func $miden:base/note-script@1.0.0#note-script (;8;) (type 4) call $wit_bindgen_rt::run_ctors_once i32.const 7 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 call $cross_ctx_note::bindings::miden::cross_ctx_account::foo::process_felt::wit_import i32.const 10 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 call $miden_stdlib_sys::intrinsics::felt::extern_assert_eq ) (func $cabi_realloc_wit_bindgen_0_28_0 (;9;) (type 6) (param i32 i32 i32 i32) (result i32) @@ -217,12 +217,12 @@ (elem (;0;) (i32.const 1) func $cross_ctx_note::bindings::__link_custom_section_describing_imports $cabi_realloc) (data $.rodata (;0;) (i32.const 1048576) "\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00") ) - (alias export 3 "from-u32-unchecked" (func (;0;))) + (alias export 3 "from-u32" (func (;0;))) (core func (;0;) (canon lower (func 0))) (alias export 3 "assert-eq" (func (;1;))) (core func (;1;) (canon lower (func 1))) (core instance (;0;) - (export "from-u32-unchecked" (func 0)) + (export "from-u32" (func 0)) (export "assert-eq" (func 1)) ) (alias export 1 "process-felt" (func (;2;))) diff --git a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat index 5dbc9cf43..2a9c2ffff 100644 --- a/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat +++ b/tests/integration/expected/rust_sdk_account_test/miden_sdk_account_test.wat @@ -26,7 +26,7 @@ (type (;24;) (func (param i32))) (type (;25;) (func (param i32 i32 i32))) (type (;26;) (func)) - (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32-unchecked" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked (;0;) (type 0))) + (import "miden:core-import/intrinsics-felt@1.0.0" "from-u32" (func $miden_stdlib_sys::intrinsics::felt::extern_from_u32 (;0;) (type 0))) (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;1;) (type 1))) (import "miden:core-import/intrinsics-felt@1.0.0" "as_u64" (func $miden_stdlib_sys::intrinsics::felt::extern_as_u64 (;2;) (type 2))) (import "miden:core-import/intrinsics-felt@1.0.0" "gt" (func $miden_stdlib_sys::intrinsics::felt::extern_gt (;3;) (type 3))) @@ -78,7 +78,7 @@ call $miden_base_sys::bindings::account::get_id local.set 0 i32.const 42 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 local.get 0 call $miden_stdlib_sys::intrinsics::felt::extern_add ) @@ -93,17 +93,17 @@ local.tee 1 global.set $__stack_pointer i32.const 1 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 local.set 2 i32.const 2 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 local.set 3 i32.const 3 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 local.set 4 local.get 1 i32.const 4 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 f32.store offset=12 local.get 1 local.get 4 @@ -792,7 +792,7 @@ i32.load offset=24 local.set 5 i32.const 0 - call $miden_stdlib_sys::intrinsics::felt::extern_from_u32_unchecked + call $miden_stdlib_sys::intrinsics::felt::extern_from_u32 local.tee 1 local.get 1 local.get 1 diff --git a/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs index 55d58f5ce..f3e1d93c5 100644 --- a/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/basic-wallet/src/bindings.rs @@ -62,14 +62,14 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] - pub fn from_u32_unchecked(a: u32) -> f32 { + pub fn from_u32(a: u32) -> f32 { unsafe { #[cfg(target_arch = "wasm32")] #[link( wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" )] extern "C" { - #[link_name = "from-u32-unchecked"] + #[link_name = "from-u32"] fn wit_import(_: i32) -> f32; } #[cfg(not(target_arch = "wasm32"))] @@ -611,8 +611,8 @@ pub(crate) use __export_basic_wallet_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:basic-wallet@1.0.0:basic-wallet-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1894] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xdd\x0d\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1884] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd3\x0d\x01A\x02\x01\ A\x17\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -626,35 +626,35 @@ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04 \x1bmiden:base/core-types@1.0.0\x05\0\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\0\ \x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x0a\x01@\x02\x01av\x01\ bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01@\x01\ -\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x12from-u3\ -2-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01\ -'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\ -\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-on\ -e-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\ -\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\ -\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-i\ -d\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03\ -ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:cor\ -e-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06\ -asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0are\ -cipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\ -\x06\x02\x03\0\0\x0acore-asset\x02\x03\0\0\x03tag\x02\x03\0\0\x09recipient\x02\x03\ -\0\0\x09note-type\x02\x03\0\0\x04felt\x01B\x0e\x02\x03\x02\x01\x07\x04\0\x0acore\ --asset\x03\0\0\x02\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\ -\0\x09recipient\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\ -\x02\x01\x0b\x04\0\x04felt\x03\0\x08\x01@\x01\x0acore-asset\x01\x01\0\x04\0\x0dr\ -eceive-asset\x01\x0a\x01@\x04\x0acore-asset\x01\x03tag\x03\x09note-type\x07\x09r\ -ecipient\x05\x01\0\x04\0\x0asend-asset\x01\x0b\x04\x01%miden:basic-wallet/basic-\ -wallet@1.0.0\x05\x0c\x01B\x14\x02\x03\x02\x01\x07\x04\0\x0acore-asset\x03\0\0\x02\ -\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09recipient\x03\ -\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\x02\x01\x0b\x04\0\ -\x04felt\x03\0\x08\x01@\x02\x01a\x09\x01b\x09\0\x09\x04\0\x14test-felt-intrinsic\ -s\x01\x0a\x01p}\x01@\x01\x05input\x0b\0\x0b\x04\0\x0btest-stdlib\x01\x0c\x01p\x09\ -\x01@\x01\x05input\x0d\0\x0d\x04\0\x11process-list-felt\x01\x0e\x01@\x01\x05inpu\ -t\x01\0\x01\x04\0\x12process-core-asset\x01\x0f\x04\x01\x1cmiden:basic-wallet/au\ -x@1.0.0\x05\x0d\x04\x01+miden:basic-wallet/basic-wallet-world@1.0.0\x04\0\x0b\x18\ -\x01\0\x12basic-wallet-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0d\ -wit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x08from-u3\ +2\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01'miden:co\ +re-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\x02a2z\x02\ +a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-one-to-one\x01\ +\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\x01B\x05\x01\ +@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\0\x04\0\x09\ +add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\ +\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03ptrz\0z\x04\ +\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:core-import/no\ +te@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x03\ +tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0arecipient3v\0\ +v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\x06\x02\x03\ +\0\0\x0acore-asset\x02\x03\0\0\x03tag\x02\x03\0\0\x09recipient\x02\x03\0\0\x09no\ +te-type\x02\x03\0\0\x04felt\x01B\x0e\x02\x03\x02\x01\x07\x04\0\x0acore-asset\x03\ +\0\0\x02\x03\x02\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09rec\ +ipient\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\x02\x01\ +\x0b\x04\0\x04felt\x03\0\x08\x01@\x01\x0acore-asset\x01\x01\0\x04\0\x0dreceive-a\ +sset\x01\x0a\x01@\x04\x0acore-asset\x01\x03tag\x03\x09note-type\x07\x09recipient\ +\x05\x01\0\x04\0\x0asend-asset\x01\x0b\x04\x01%miden:basic-wallet/basic-wallet@1\ +.0.0\x05\x0c\x01B\x14\x02\x03\x02\x01\x07\x04\0\x0acore-asset\x03\0\0\x02\x03\x02\ +\x01\x08\x04\0\x03tag\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09recipient\x03\0\x04\ +\x02\x03\x02\x01\x0a\x04\0\x09note-type\x03\0\x06\x02\x03\x02\x01\x0b\x04\0\x04f\ +elt\x03\0\x08\x01@\x02\x01a\x09\x01b\x09\0\x09\x04\0\x14test-felt-intrinsics\x01\ +\x0a\x01p}\x01@\x01\x05input\x0b\0\x0b\x04\0\x0btest-stdlib\x01\x0c\x01p\x09\x01\ +@\x01\x05input\x0d\0\x0d\x04\0\x11process-list-felt\x01\x0e\x01@\x01\x05input\x01\ +\0\x01\x04\0\x12process-core-asset\x01\x0f\x04\x01\x1cmiden:basic-wallet/aux@1.0\ +.0\x05\x0d\x04\x01+miden:basic-wallet/basic-wallet-world@1.0.0\x04\0\x0b\x18\x01\ +\0\x12basic-wallet-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-\ +component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs index 3e329ec99..fe3b63dc3 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/src/bindings.rs @@ -62,14 +62,14 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] - pub fn from_u32_unchecked(a: u32) -> f32 { + pub fn from_u32(a: u32) -> f32 { unsafe { #[cfg(target_arch = "wasm32")] #[link( wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" )] extern "C" { - #[link_name = "from-u32-unchecked"] + #[link_name = "from-u32"] fn wit_import(_: i32) -> f32; } #[cfg(not(target_arch = "wasm32"))] @@ -368,8 +368,8 @@ pub(crate) use __export_foo_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-account@1.0.0:foo-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1421] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x8d\x0a\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1411] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x83\x0a\x01A\x02\x01\ A\x11\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -383,23 +383,23 @@ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04 \x1bmiden:base/core-types@1.0.0\x05\0\x01B\x02\x01@\0\0z\x04\0\x09heap-base\x01\0\ \x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x01\x01B\x0a\x01@\x02\x01av\x01\ bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\x01\x01@\x01\ -\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x12from-u3\ -2-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01\ -'miden:core-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\ -\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-on\ -e-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\ -\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\ -\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-i\ -d\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03\ -ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:cor\ -e-import/note@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06\ -asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0are\ -cipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\ -\x06\x02\x03\0\0\x04felt\x01B\x04\x02\x03\x02\x01\x07\x04\0\x04felt\x03\0\0\x01@\ -\x01\x05input\x01\0\x01\x04\0\x0cprocess-felt\x01\x02\x04\x01!miden:cross-ctx-ac\ -count/foo@1.0.0\x05\x08\x04\x01'miden:cross-ctx-account/foo-world@1.0.0\x04\0\x0b\ -\x0f\x01\0\x09foo-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-c\ -omponent\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\0\x08from-u3\ +2\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\x01'miden:co\ +re-import/intrinsics-felt@1.0.0\x05\x02\x01B\x02\x01@\x09\x02a0z\x02a1z\x02a2z\x02\ +a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash-one-to-one\x01\ +\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\x03\x01B\x05\x01\ +@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptrz\x01\0\x04\0\x09\ +add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06get-id\x01\x01\x03\ +\x01\x1fmiden:core-import/account@1.0.0\x05\x04\x01B\x03\x01@\x01\x03ptrz\0z\x04\ +\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden:core-import/no\ +te@1.0.0\x05\x05\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x03\ +tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\x0arecipient3v\0\ +v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.0.0\x05\x06\x02\x03\ +\0\0\x04felt\x01B\x04\x02\x03\x02\x01\x07\x04\0\x04felt\x03\0\0\x01@\x01\x05inpu\ +t\x01\0\x01\x04\0\x0cprocess-felt\x01\x02\x04\x01!miden:cross-ctx-account/foo@1.\ +0.0\x05\x08\x04\x01'miden:cross-ctx-account/foo-world@1.0.0\x04\0\x0b\x0f\x01\0\x09\ +foo-world\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.\ +216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs index 57655e6ea..ac6fdc8d9 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/src/bindings.rs @@ -62,14 +62,14 @@ pub mod miden { } } #[allow(unused_unsafe, clippy::all)] - pub fn from_u32_unchecked(a: u32) -> f32 { + pub fn from_u32(a: u32) -> f32 { unsafe { #[cfg(target_arch = "wasm32")] #[link( wasm_import_module = "miden:core-import/intrinsics-felt@1.0.0" )] extern "C" { - #[link_name = "from-u32-unchecked"] + #[link_name = "from-u32"] fn wit_import(_: i32) -> f32; } #[cfg(not(target_arch = "wasm32"))] @@ -393,8 +393,8 @@ pub(crate) use __export_cross_ctx_note_world_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.31.0:miden:cross-ctx-note@1.0.0:cross-ctx-note-world:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1497] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xce\x0a\x01A\x02\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1487] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xc4\x0a\x01A\x02\x01\ A\x13\x01B\x1f\x01r\x01\x05innerv\x04\0\x04felt\x03\0\0\x01o\x04\x01\x01\x01\x01\ \x01r\x01\x05inner\x02\x04\0\x04word\x03\0\x03\x01r\x01\x05inner\x01\x04\0\x0aac\ count-id\x03\0\x05\x01r\x01\x05inner\x04\x04\0\x09recipient\x03\0\x07\x01r\x01\x05\ @@ -411,21 +411,21 @@ r\x01\x05inner\x04\x04\0\x10vault-commitment\x03\0\x19\x01r\x01\x05inner\x01\x04 heap-base\x01\0\x03\x01&miden:core-import/intrinsics-mem@1.0.0\x05\x03\x01B\x0a\x01\ @\x02\x01av\x01bv\0v\x04\0\x03add\x01\0\x01@\x02\x01av\x01bv\0\x7f\x04\0\x02eq\x01\ \x01\x01@\x01\x01aw\0v\x04\0\x12from-u64-unchecked\x01\x02\x01@\x01\x01ay\0v\x04\ -\0\x12from-u32-unchecked\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\ -\x04\x03\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x04\x01B\x02\x01@\x09\x02\ -a0z\x02a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0f\ -hash-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.\ -0\x05\x05\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresul\ -t-ptrz\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\ -\x06get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x06\x01B\x03\x01\ -@\x01\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1c\ -miden:core-import/note@1.0.0\x05\x07\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06\ -asset2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipi\ -ent2v\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/\ -tx@1.0.0\x05\x08\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-script\x01\0\x04\x01\x1cmid\ -en:base/note-script@1.0.0\x05\x09\x04\x01/miden:cross-ctx-note/cross-ctx-note-wo\ -rld@1.0.0\x04\0\x0b\x1a\x01\0\x14cross-ctx-note-world\x03\0\0\0G\x09producers\x01\ -\x0cprocessed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; +\0\x08from-u32\x01\x03\x01@\x02\x01av\x01bv\x01\0\x04\0\x09assert-eq\x01\x04\x03\ +\x01'miden:core-import/intrinsics-felt@1.0.0\x05\x04\x01B\x02\x01@\x09\x02a0z\x02\ +a1z\x02a2z\x02a3z\x02a4z\x02a5z\x02a6z\x02a7z\x0aresult-ptrz\x01\0\x04\0\x0fhash\ +-one-to-one\x01\0\x03\x013miden:core-import/stdlib-crypto-hashes-blake3@1.0.0\x05\ +\x05\x01B\x05\x01@\x05\x06asset0v\x06asset1v\x06asset2v\x06asset3v\x0aresult-ptr\ +z\x01\0\x04\0\x09add-asset\x01\0\x04\0\x0cremove-asset\x01\0\x01@\0\0v\x04\0\x06\ +get-id\x01\x01\x03\x01\x1fmiden:core-import/account@1.0.0\x05\x06\x01B\x03\x01@\x01\ +\x03ptrz\0z\x04\0\x0aget-inputs\x01\0\x04\0\x0aget-assets\x01\0\x03\x01\x1cmiden\ +:core-import/note@1.0.0\x05\x07\x01B\x02\x01@\x0a\x06asset0v\x06asset1v\x06asset\ +2v\x06asset3v\x03tagv\x09note-typev\x0arecipient0v\x0arecipient1v\x0arecipient2v\ +\x0arecipient3v\0v\x04\0\x0bcreate-note\x01\0\x03\x01\x1amiden:core-import/tx@1.\ +0.0\x05\x08\x01B\x02\x01@\0\x01\0\x04\0\x0bnote-script\x01\0\x04\x01\x1cmiden:ba\ +se/note-script@1.0.0\x05\x09\x04\x01/miden:cross-ctx-note/cross-ctx-note-world@1\ +.0.0\x04\0\x0b\x1a\x01\0\x14cross-ctx-note-world\x03\0\0\0G\x09producers\x01\x0c\ +processed-by\x02\x0dwit-component\x070.216.0\x10wit-bindgen-rust\x060.31.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit b/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit index dfb49747a..bae8a40b4 100644 --- a/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit +++ b/tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit @@ -13,7 +13,7 @@ interface intrinsics-felt { add: func(a: f32, b: f32) -> f32; eq: func(a: f32, b: f32) -> bool; from-u64-unchecked: func(a: u64) -> f32; - from-u32-unchecked: func(a: u32) -> f32; + from-u32: func(a: u32) -> f32; assert-eq: func(a: f32, b: f32); } From eb2a0cae6b8b4c265e174297f94781ed48a46c05 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 17 Dec 2024 14:30:46 +0200 Subject: [PATCH 23/26] refactor: replace `CallConv::CrossCtx` with `CanonLift` and `CanonLower` --- hir/src/asm/builder.rs | 6 +++++- hir/src/function.rs | 15 ++++++++++++-- midenc-compile/src/stages/cross_ctx/flat.rs | 20 ++++++------------- .../src/stages/cross_ctx/lift_exports.rs | 7 +++---- .../src/stages/cross_ctx/lower_imports.rs | 11 +++++----- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/hir/src/asm/builder.rs b/hir/src/asm/builder.rs index e65061ab8..d5985fca9 100644 --- a/hir/src/asm/builder.rs +++ b/hir/src/asm/builder.rs @@ -2211,7 +2211,11 @@ fn execute_call( } match import.signature.cc { // For now, we're treating all calling conventions the same as SystemV - CallConv::Fast | CallConv::SystemV | CallConv::Kernel | CallConv::CrossCtx => { + CallConv::Fast + | CallConv::SystemV + | CallConv::Kernel + | CallConv::CanonLift + | CallConv::CanonLower => { // Visit the argument list in reverse (so that the top of the stack on entry // is the first argument), and allocate elements based on the argument types. let mut elements_needed = 0; diff --git a/hir/src/function.rs b/hir/src/function.rs index e0ca4e9b6..fde281914 100644 --- a/hir/src/function.rs +++ b/hir/src/function.rs @@ -62,13 +62,23 @@ pub enum CallConv { /// /// In all other respects, this calling convention is the same as `SystemV` Kernel, + /// This calling convention is used for the synthetic functions generated for the Wasm CM + /// export (`canon lift`), see + /// https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#lifting-and-lowering-values + /// /// A function with this calling convention is expected to be called using the `call` /// instruction. Since execution moves to a different contexe he callee does not have access to /// caller's memory, so arguments and results are passed through the stack or through the /// advice provider. + /// see https://0xpolygonmiden.github.io/miden-vm/user_docs/assembly/execution_contexts.html + CanonLift, + /// This calling convention is used for the synthetic functions generated for the Wasm CM + /// import (`canon lower`), see + /// https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#lifting-and-lowering-values /// + /// A function with this calling convention is expected to be called using the `exec` instruction. /// see https://0xpolygonmiden.github.io/miden-vm/user_docs/assembly/execution_contexts.html - CrossCtx, + CanonLower, } impl fmt::Display for CallConv { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -77,7 +87,8 @@ impl fmt::Display for CallConv { Self::SystemV => f.write_str("C"), Self::Wasm => f.write_str("wasm"), Self::Kernel => f.write_str("kernel"), - Self::CrossCtx => f.write_str("cctx"), + Self::CanonLift => f.write_str("lift"), + Self::CanonLower => f.write_str("lower"), } } } diff --git a/midenc-compile/src/stages/cross_ctx/flat.rs b/midenc-compile/src/stages/cross_ctx/flat.rs index 7e640f2bd..3289d85f4 100644 --- a/midenc-compile/src/stages/cross_ctx/flat.rs +++ b/midenc-compile/src/stages/cross_ctx/flat.rs @@ -9,12 +9,6 @@ use midenc_hir::{ Signature, StructType, Type, }; -/// Lowering the import or lifting the export function -pub enum FlatteningDirection { - Lift, - Lower, -} - /// Flattens the given CanonABI type into a list of ABI parameters. pub fn flatten_type(ty: &Type) -> Result, String> { // see https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening @@ -90,10 +84,7 @@ pub fn flatten_types(tys: &[Type]) -> Result, String> { } /// Flattens the given CanonABI function type -pub fn flatten_function_type( - func_ty: &FunctionType, - dir: FlatteningDirection, -) -> Result { +pub fn flatten_function_type(func_ty: &FunctionType, cc: CallConv) -> Result { // from https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening // // For a variety of practical reasons, we need to limit the total number of flattened @@ -124,20 +115,21 @@ pub fn flatten_function_type( // returning an `i32` as a return value. assert_eq!(func_ty.results.len(), 1, "expected a single result"); let result = func_ty.results.first().expect("unexpected empty results").clone(); - match dir { - FlatteningDirection::Lift => { + match cc { + CallConv::CanonLift => { flat_results = vec![AbiParam::sret(Type::Ptr(result.into()))]; } - FlatteningDirection::Lower => { + CallConv::CanonLower => { flat_params.push(AbiParam::sret(Type::Ptr(result.into()))); flat_results = vec![]; } + _ => panic!("unexpected call convention, only CanonLift and CanonLower are supported"), } } Ok(Signature { params: flat_params, results: flat_results, - cc: CallConv::CrossCtx, + cc, linkage: Linkage::External, }) } diff --git a/midenc-compile/src/stages/cross_ctx/lift_exports.rs b/midenc-compile/src/stages/cross_ctx/lift_exports.rs index feacaeced..cb6b1c870 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_exports.rs @@ -7,13 +7,12 @@ use midenc_hir::{ diagnostics::Severity, pass::AnalysisManager, types::Abi::{self, Canonical}, - ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, + CallConv, ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, }; use midenc_session::{DiagnosticsHandler, Session}; use super::flat::{ assert_core_wasm_signature_equivalence, flatten_function_type, needs_transformation, - FlatteningDirection, }; use crate::{stage::Stage, CompilerResult, LinkerInput}; @@ -110,8 +109,8 @@ fn generate_lifting_function( // get or create the module for the interface let module_id = export_id.interface.full_name; let mut module_builder = component_builder.module(module_id); - let cross_ctx_export_sig = - flatten_function_type(&export.function_ty, FlatteningDirection::Lift).map_err(|e| { + let cross_ctx_export_sig = flatten_function_type(&export.function_ty, CallConv::CanonLift) + .map_err(|e| { let message = format!( "Miden CCABI export lifting generation. Signature for exported function {} \ requires flattening. Error: {}", diff --git a/midenc-compile/src/stages/cross_ctx/lower_imports.rs b/midenc-compile/src/stages/cross_ctx/lower_imports.rs index 2a0973a07..e50e8ebe9 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_imports.rs @@ -4,15 +4,14 @@ use std::collections::{BTreeMap, VecDeque}; use miden_assembly::Spanned; use midenc_hir::{ - diagnostics::Severity, pass::AnalysisManager, types::Abi, Block, Call, ComponentBuilder, - ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, Instruction, - MidenAbiImport, Signature, SourceSpan, Symbol, UnsafeRef, + diagnostics::Severity, pass::AnalysisManager, types::Abi, Block, Call, CallConv, + ComponentBuilder, ComponentImport, Function, FunctionIdent, FunctionType, InstBuilder, + Instruction, MidenAbiImport, Signature, SourceSpan, Symbol, UnsafeRef, }; use midenc_session::{DiagnosticsHandler, Session}; use super::flat::{ assert_core_wasm_signature_equivalence, flatten_function_type, needs_transformation, - FlatteningDirection, }; use crate::{stage::Stage, CompilerResult, LinkerInput}; @@ -122,8 +121,8 @@ fn generate_lowering_function( // dbg!(&lowering_module_id); let mut module_builder = component_builder.module(lowering_module_id); - let import_lowered_sig = flatten_function_type(high_func_ty, FlatteningDirection::Lower) - .map_err(|e| { + let import_lowered_sig = + flatten_function_type(high_func_ty, CallConv::CanonLower).map_err(|e| { let message = format!( "Miden CCABI import lowering generation. Signature for imported function {} \ requires flattening. Error: {}", From 167f0a049ece7b761b7b1a00d73bf5dcfcd258e7 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 17 Dec 2024 15:14:50 +0200 Subject: [PATCH 24/26] chore: add comments for the handling of the lifting/lowering in the future --- midenc-compile/src/stages/cross_ctx/lift_exports.rs | 2 ++ midenc-compile/src/stages/cross_ctx/lower_imports.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/midenc-compile/src/stages/cross_ctx/lift_exports.rs b/midenc-compile/src/stages/cross_ctx/lift_exports.rs index cb6b1c870..00318b67a 100644 --- a/midenc-compile/src/stages/cross_ctx/lift_exports.rs +++ b/midenc-compile/src/stages/cross_ctx/lift_exports.rs @@ -151,6 +151,8 @@ fn generate_lifting_function( })?; } let span = export.function.function.span(); + // NOTE: handle lifting/lowering for non-scalar types + // see https://github.com/0xPolygonMiden/compiler/pull/357 let call = builder.ins().exec(export.function, ¶ms, span); // dbg!(&sig); let result = builder.first_result(call); diff --git a/midenc-compile/src/stages/cross_ctx/lower_imports.rs b/midenc-compile/src/stages/cross_ctx/lower_imports.rs index e50e8ebe9..2cc39345b 100644 --- a/midenc-compile/src/stages/cross_ctx/lower_imports.rs +++ b/midenc-compile/src/stages/cross_ctx/lower_imports.rs @@ -162,6 +162,8 @@ fn generate_lowering_function( diagnostics.diagnostic(Severity::Error).with_message(message).into_report() })?; } + // NOTE: handle lifting/lowering for non-scalar types + // see https://github.com/0xPolygonMiden/compiler/pull/357 let call = builder.ins().call(import_func_id, ¶ms, span); // dbg!(&sig); let result = builder.first_result(call); From 5f755493484ffcf14acbb79dc205dbc93d51c7f9 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 17 Dec 2024 16:18:51 +0200 Subject: [PATCH 25/26] Update midenc-debug/src/exec/executor.rs Co-authored-by: Paul Schoenfelder <955793+bitwalker@users.noreply.github.com> --- midenc-debug/src/exec/executor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/midenc-debug/src/exec/executor.rs b/midenc-debug/src/exec/executor.rs index 01051a04e..ed936eb23 100644 --- a/midenc-debug/src/exec/executor.rs +++ b/midenc-debug/src/exec/executor.rs @@ -104,7 +104,7 @@ impl Executor { Ok(self) } - /// Set the contents of memory for the shadow stack frame of the entrypint + /// Set the contents of memory for the shadow stack frame of the entrypoint pub fn with_advice_inputs(&mut self, advice: AdviceInputs) -> &mut Self { self.advice.extend(advice); self From 6e4ea6c601a0487a44c735e4315ceaad843a5414 Mon Sep 17 00:00:00 2001 From: Denys Zadorozhnyi Date: Tue, 17 Dec 2024 16:34:38 +0200 Subject: [PATCH 26/26] test: enable `debug-assertions` in cargo-miden test projects --- tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml | 3 +-- tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml index 14dc3efbe..be9f61659 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-account/Cargo.toml @@ -31,7 +31,7 @@ panic = "abort" # library code unintentionally panic = "abort" opt-level = 1 -debug-assertions = false +debug-assertions = true overflow-checks = false debug = true @@ -42,4 +42,3 @@ package = "miden:cross-ctx-account" [package.metadata.component.target.dependencies] "miden:base" = { path = "../wit-sdk/miden.wit" } "miden:core-import" = { path = "../wit-sdk/miden-core-import.wit" } - diff --git a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml index 03c508fad..6f3af3e02 100644 --- a/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml +++ b/tests/rust-apps-wasm/rust-sdk/cross-ctx-note/Cargo.toml @@ -31,7 +31,7 @@ panic = "abort" # library code unintentionally panic = "abort" opt-level = 1 -debug-assertions = false +debug-assertions = true overflow-checks = false debug = true