diff --git a/Cargo.lock b/Cargo.lock index 4c5a55d0..651ec431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3380,6 +3380,7 @@ dependencies = [ "miden-thiserror", "midenc-hir", "midenc-hir-type", + "midenc-hir2", "midenc-session", "rustc-hash", "smallvec", diff --git a/frontend-wasm/Cargo.toml b/frontend-wasm/Cargo.toml index 55f45e44..793b20f6 100644 --- a/frontend-wasm/Cargo.toml +++ b/frontend-wasm/Cargo.toml @@ -24,6 +24,7 @@ log.workspace = true hashbrown.workspace = true miden-core.workspace = true midenc-hir.workspace = true +midenc-hir2.workspace = true midenc-hir-type.workspace = true midenc-session.workspace = true rustc-hash.workspace = true diff --git a/frontend-wasm/src/code_translator/mod.rs b/frontend-wasm/src/code_translator/mod.rs index 3ca0ad10..05e25017 100644 --- a/frontend-wasm/src/code_translator/mod.rs +++ b/frontend-wasm/src/code_translator/mod.rs @@ -15,7 +15,7 @@ use midenc_hir::{ cranelift_entity::packed_option::ReservedValue, - diagnostics::{DiagnosticsHandler, IntoDiagnostic, Report, Severity, SourceSpan}, + diagnostics::{DiagnosticsHandler, IntoDiagnostic, Report, SourceSpan}, Block, FieldElement, Immediate, Inst, InstBuilder, Type, Type::*, Value, diff --git a/frontend-wasm/src/component/build_ir.rs b/frontend-wasm/src/component/build_ir.rs index 0190cd55..74ebf81a 100644 --- a/frontend-wasm/src/component/build_ir.rs +++ b/frontend-wasm/src/component/build_ir.rs @@ -1,9 +1,12 @@ +use std::rc::Rc; + use midenc_hir::diagnostics::Report; +use midenc_hir2::{dialects::builtin::BuiltinDialect, Context}; use midenc_session::Session; use super::{ - inline, translator::ComponentTranslator, ComponentTypesBuilder, LinearComponentTranslation, - ParsedRootComponent, + inline, translator::ComponentTranslator, translator2::ComponentTranslator2, + ComponentTypesBuilder, LinearComponentTranslation, ParsedRootComponent, }; use crate::{ component::ComponentParser, error::WasmResult, supported_component_model_features, @@ -61,3 +64,23 @@ fn inline( .map_err(Report::msg)?; Ok(component_dfg.finish()) } + +/// Translate a Wasm component binary into Miden IR component +pub fn translate_component2( + wasm: &[u8], + config: &WasmTranslationConfig, + session: Rc, +) -> WasmResult { + let (mut component_types_builder, parsed_root_component) = parse(config, wasm, &session)?; + let context = Rc::new(Context::new(session)); + let dialect = context.get_or_register_dialect::(); + dialect.expect_registered_name::(); + // context.get_or_register_dialect::(); + let translator = ComponentTranslator2::new( + &parsed_root_component.static_modules, + &parsed_root_component.static_components, + config, + context, + ); + translator.translate2(&parsed_root_component.root_component, &mut component_types_builder) +} diff --git a/frontend-wasm/src/component/inline.rs b/frontend-wasm/src/component/inline.rs index f080b22f..d835dd79 100644 --- a/frontend-wasm/src/component/inline.rs +++ b/frontend-wasm/src/component/inline.rs @@ -58,7 +58,7 @@ use super::{ LocalCanonicalOptions, ParsedComponent, StringEncoding, }; use crate::{ - component::{dfg, LocalInitializer}, + component::{dfg, CanonLift, CanonLower, ComponentInstantiation, LocalInitializer}, module::{module_env::ParsedModule, types::*, ModuleImport}, }; @@ -501,12 +501,12 @@ impl<'a> Inliner<'a> { // Lowering a component function to a core wasm function. Here // various metadata is recorded and then the final component gets an // initializer recording the lowering. - Lower { + Lower(CanonLower { func, options, canonical_abi, lower_ty, - } => { + }) => { let lower_ty = types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?; let options_lower = self.adapter_options(frame, options); @@ -580,7 +580,7 @@ impl<'a> Inliner<'a> { // Lifting a core wasm function is relatively easy for now in that // some metadata about the lifting is simply recorded. This'll get // plumbed through to exports or a fused adapter later on. - Lift(ty, func, options) => { + Lift(CanonLift { ty, func, options }) => { let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?; let options = self.adapter_options(frame, options); frame.component_funcs.push(ComponentFuncDef::Lifted { @@ -732,7 +732,11 @@ impl<'a> Inliner<'a> { // of this entire module, so the "easy" step here is to simply // create a new inliner frame and return it to get pushed onto the // stack. - ComponentInstantiate(component, args, ty) => { + ComponentInstantiate(ComponentInstantiation { + component, + args, + ty, + }) => { let component: &ComponentDef<'a> = &frame.components[*component]; let index = RuntimeComponentInstanceIndex::from_u32( self.result.num_runtime_component_instances, @@ -826,7 +830,7 @@ impl<'a> Inliner<'a> { frame.components.push(frame.closed_over_component(idx)); } - Export(item) => match item { + Export(_, item) => match item { ComponentItem::Func(i) => { frame.component_funcs.push(frame.component_funcs[*i].clone()); } diff --git a/frontend-wasm/src/component/mod.rs b/frontend-wasm/src/component/mod.rs index 8b237754..784dc83b 100644 --- a/frontend-wasm/src/component/mod.rs +++ b/frontend-wasm/src/component/mod.rs @@ -9,6 +9,7 @@ pub mod info; mod inline; mod parser; mod translator; +mod translator2; mod types; pub use self::{info::*, parser::*, types::*}; diff --git a/frontend-wasm/src/component/parser.rs b/frontend-wasm/src/component/parser.rs index 51bd871c..baa8462b 100644 --- a/frontend-wasm/src/component/parser.rs +++ b/frontend-wasm/src/component/parser.rs @@ -7,9 +7,7 @@ use std::mem; use indexmap::IndexMap; use midenc_hir::{ - cranelift_entity::PrimaryMap, - diagnostics::{IntoDiagnostic, Severity}, - FxBuildHasher, FxHashMap, + cranelift_entity::PrimaryMap, diagnostics::IntoDiagnostic, FxBuildHasher, FxHashMap, }; use midenc_session::Session; use wasmparser::{ @@ -183,23 +181,42 @@ pub struct ParsedComponent<'data> { pub types: Option, } +#[derive(Debug, Clone)] +pub struct CanonLower { + pub func: ComponentFuncIndex, + pub lower_ty: ComponentFuncTypeId, + pub canonical_abi: SignatureIndex, + pub options: LocalCanonicalOptions, +} + +#[derive(Debug, Clone)] +pub struct CanonLift { + pub ty: ComponentFuncTypeId, + pub func: FuncIndex, + pub options: LocalCanonicalOptions, +} + +#[derive(Debug, Clone)] +// component instances +pub struct ComponentInstantiation<'data> { + pub component: ComponentIndex, + pub args: FxHashMap<&'data str, ComponentItem>, + pub ty: ComponentInstanceTypeId, +} + // NB: the type information contained in `LocalInitializer` should always point // to `wasmparser`'s type information, not ours. Component types cannot be // fully determined due to resources until instantiations are known which is // tracked during the inlining phase. This means that all type information below // is straight from `wasmparser`'s passes. +#[derive(Debug)] pub enum LocalInitializer<'data> { // imports Import(ComponentImportName<'data>, ComponentEntityType), // canonical function sections - Lower { - func: ComponentFuncIndex, - lower_ty: ComponentFuncTypeId, - canonical_abi: SignatureIndex, - options: LocalCanonicalOptions, - }, - Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions), + Lower(CanonLower), + Lift(CanonLift), // resources Resource(AliasableResourceId, WasmType, Option), @@ -217,12 +234,7 @@ pub enum LocalInitializer<'data> { // components ComponentStatic(StaticComponentIndex, ClosedOverVars), - // component instances - ComponentInstantiate( - ComponentIndex, - FxHashMap<&'data str, ComponentItem>, - ComponentInstanceTypeId, - ), + ComponentInstantiate(ComponentInstantiation<'data>), ComponentSynthetic(FxHashMap<&'data str, ComponentItem>), // alias section @@ -235,13 +247,13 @@ pub enum LocalInitializer<'data> { AliasComponent(ClosedOverComponent), // export section - Export(ComponentItem), + Export(&'data str, ComponentItem), } /// The "closure environment" of components themselves. /// /// For more information see `LexicalScope`. -#[derive(Default)] +#[derive(Default, Debug)] pub struct ClosedOverVars { pub components: PrimaryMap, pub modules: PrimaryMap, @@ -251,6 +263,7 @@ pub struct ClosedOverVars { /// a component are being created. /// /// For more information see `LexicalScope`. +#[derive(Debug)] pub enum ClosedOverComponent { /// A closed over component is coming from the local component's index /// space, meaning a previously defined component is being captured. @@ -263,12 +276,14 @@ pub enum ClosedOverComponent { } /// Same as `ClosedOverComponent`, but for modules. +#[derive(Debug)] pub enum ClosedOverModule { Local(ModuleIndex), Upvar(ModuleUpvarIndex), } /// Representation of canonical ABI options. +#[derive(Debug, Clone)] pub struct LocalCanonicalOptions { pub string_encoding: StringEncoding, pub memory: Option, @@ -349,6 +364,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { } => { self.validator.version(num, encoding, &range).into_diagnostic()?; + // dbg!(&encoding); match encoding { Encoding::Component => {} Encoding::Module => { @@ -470,6 +486,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { let import = import.into_diagnostic()?; let types = self.validator.types(0).unwrap(); let ty = types.component_entity_type_of_import(import.name.0).unwrap(); + // dbg!(&import.name, &ty); self.result.initializers.push(LocalInitializer::Import(import.name, ty)); } Ok(()) @@ -494,7 +511,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { let ty = types.component_any_type_at(type_index).unwrap_func(); let func = FuncIndex::from_u32(core_func_index); let options = canonical_options(&options); - LocalInitializer::Lift(ty, func, options) + LocalInitializer::Lift(CanonLift { ty, func, options }) } wasmparser::CanonicalFunction::Lower { func_index, @@ -506,12 +523,12 @@ impl<'a, 'data> ComponentParser<'a, 'data> { let canonical_abi = self.core_func_signature(core_func_index); core_func_index += 1; - LocalInitializer::Lower { + LocalInitializer::Lower(CanonLower { func, options, canonical_abi, lower_ty, - } + }) } wasmparser::CanonicalFunction::ResourceNew { resource } => { let resource = types.component_any_type_at(resource).unwrap_resource(); @@ -532,6 +549,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { LocalInitializer::ResourceRep(resource, ty) } }; + // dbg!(&init); self.result.initializers.push(init); } Ok(()) @@ -611,6 +629,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { instantiate_module_from_exports(&exports) } }; + // dbg!(&init); self.result.initializers.push(init); } Ok(()) @@ -637,6 +656,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { self.instantiate_component_from_exports(&exports)? } }; + // dbg!(&init); self.result.initializers.push(init); index += 1; } @@ -655,10 +675,11 @@ impl<'a, 'data> ComponentParser<'a, 'data> { self.validator.component_export_section(&s).into_diagnostic()?; for export in s { let export = export.into_diagnostic()?; + // dbg!(&export); let item = self.kind_to_item(export.kind, export.index)?; let prev = self.result.exports.insert(export.name.0, item); assert!(prev.is_none()); - self.result.initializers.push(LocalInitializer::Export(item)); + self.result.initializers.push(LocalInitializer::Export(export.name.0, item)); } Ok(()) } @@ -694,6 +715,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { alias_module_instance_export(kind, instance, name) } }; + // dbg!(&init); self.result.initializers.push(init); } Ok(()) @@ -712,7 +734,11 @@ impl<'a, 'data> ComponentParser<'a, 'data> { args.insert(arg.name, idx); } - Ok(LocalInitializer::ComponentInstantiate(component, args, ty)) + Ok(LocalInitializer::ComponentInstantiate(ComponentInstantiation { + component, + args, + ty, + })) } /// Creates a synthetic module from the list of items currently in the @@ -727,6 +753,7 @@ impl<'a, 'data> ComponentParser<'a, 'data> { map.insert(export.name.0, idx); } + // dbg!(&map); Ok(LocalInitializer::ComponentSynthetic(map)) } diff --git a/frontend-wasm/src/component/translator.rs b/frontend-wasm/src/component/translator.rs index e5c3c315..ad4aa301 100644 --- a/frontend-wasm/src/component/translator.rs +++ b/frontend-wasm/src/component/translator.rs @@ -1,7 +1,6 @@ use midenc_hir::{ - cranelift_entity::PrimaryMap, diagnostics::Severity, CanonAbiImport, ComponentBuilder, - ComponentExport, FunctionIdent, FunctionType, FxHashMap, Ident, InterfaceFunctionIdent, - InterfaceIdent, MidenAbiImport, Symbol, + cranelift_entity::PrimaryMap, CanonAbiImport, ComponentBuilder, ComponentExport, FunctionIdent, + FunctionType, FxHashMap, Ident, InterfaceFunctionIdent, InterfaceIdent, MidenAbiImport, Symbol, }; use midenc_hir_type::Abi; use midenc_session::{DiagnosticsHandler, Session}; @@ -487,7 +486,10 @@ fn function_id_from_export(exporting_module: &Module, func_idx: FuncIndex) -> Fu } /// Convert the given Wasm component function type to the Miden IR lifted function type -fn convert_lifted_func_ty(ty: &TypeFuncIndex, component_types: &ComponentTypes) -> FunctionType { +pub fn convert_lifted_func_ty( + ty: &TypeFuncIndex, + component_types: &ComponentTypes, +) -> FunctionType { let type_func = component_types[*ty].clone(); let params_types = component_types[type_func.params].clone().types; let results_types = component_types[type_func.results].clone().types; diff --git a/frontend-wasm/src/component/translator2.rs b/frontend-wasm/src/component/translator2.rs new file mode 100644 index 00000000..9c84330f --- /dev/null +++ b/frontend-wasm/src/component/translator2.rs @@ -0,0 +1,837 @@ +// TODO:remove after its completed +#![allow(unused)] + +// TODO: document + +use std::{borrow::BorrowMut, rc::Rc}; + +use midenc_hir::{ + cranelift_entity::PrimaryMap, diagnostics::Report, AbiParam, CallConv, FunctionIdent, + FxHashMap, Ident, Linkage, Signature, SourceSpan, Symbol, +}; +use midenc_hir2::{ + self as hir2, + dialects::builtin::{Component, ComponentBuilder, ComponentRef}, + version::Version, + BuilderExt, Context, EntityMut, OpBuilder, +}; +use midenc_session::{DiagnosticsHandler, Session}; +use wasmparser::types::{ComponentEntityType, TypesRef}; + +use super::{ + translator::convert_lifted_func_ty, CanonLift, CanonLower, ClosedOverComponent, + ClosedOverModule, ComponentFuncIndex, ComponentIndex, ComponentInstanceIndex, + ComponentInstantiation, ComponentTypesBuilder, ComponentUpvarIndex, ModuleIndex, + ModuleInstanceIndex, ModuleUpvarIndex, ParsedComponent, StaticModuleIndex, + TypeComponentInstanceIndex, TypeDef, TypeModuleIndex, +}; +use crate::{ + component::{ComponentItem, LocalInitializer, StaticComponentIndex}, + error::WasmResult, + module::{ + module_env::ParsedModule, + types::{EntityIndex, FuncIndex}, + }, + unsupported_diag, WasmTranslationConfig, +}; + +pub mod hir2_sketch; + +/// A translator from the linearized Wasm component model to the Miden IR component +pub struct ComponentTranslator2<'a> { + /// The translation configuration + config: &'a WasmTranslationConfig, + + /// The list of static modules that were found during initial translation of + /// the component. + /// + /// This is used during the instantiation of these modules to ahead-of-time + /// order the arguments precisely according to what the module is defined as + /// needing which avoids the need to do string lookups or permute arguments + /// at runtime. + nested_modules: &'a PrimaryMap>, + + /// The list of static components that were found during initial translation of + /// the component. + /// + /// This is used when instantiating nested components to push a new + /// `ComponentFrame` with the `ParsedComponent`s here. + nested_components: &'a PrimaryMap>, + + result: ComponentBuilder, + + context: Rc, +} + +impl<'a> ComponentTranslator2<'a> { + pub fn new( + nested_modules: &'a PrimaryMap>, + nested_components: &'a PrimaryMap>, + config: &'a WasmTranslationConfig, + context: Rc, + ) -> Self { + let mut builder = context.clone().builder(); + let component_builder = + builder.create::(Default::default()); + // TODO: get proper ns and name (from exported interfaces?) + let ns = hir2::Ident::from("root_ns"); + let name = hir2::Ident::from("root"); + let ver = Version::parse("1.0.0").unwrap(); + let mut raw_entity_ref = component_builder(ns, name, ver).unwrap(); + let result = ComponentBuilder::new(raw_entity_ref); + Self { + config, + context, + nested_modules, + nested_components, + result, + } + } + + pub fn translate2( + mut self, + root_component: &'a ParsedComponent, + types: &mut ComponentTypesBuilder, + ) -> WasmResult { + let mut frame = ComponentFrame::new(root_component.types_ref(), FxHashMap::default()); + + for init in &root_component.initializers { + self.initializer(&mut frame, types, init)?; + } + + Ok(self.result.component) + } + + fn initializer( + &mut self, + frame: &mut ComponentFrame<'a>, + types: &mut ComponentTypesBuilder, + init: &'a LocalInitializer<'a>, + ) -> WasmResult<()> { + match init { + LocalInitializer::Import(name, ty) => { + match frame.args.get(name.0) { + Some(arg) => { + frame.push_item(arg.clone()); + } + + // Not all arguments need to be provided for instantiation, namely the root + // component doesn't require structural type imports to be satisfied. + None => { + match ty { + ComponentEntityType::Instance(_) => { + self.component_import(frame, types, name, ty)?; + } + _ => { + unsupported_diag!( + &self.context.session.diagnostics, + "Importing of {:?} is not yet supported", + ty + ) + } + }; + } + }; + } + LocalInitializer::Lower(lower) => { + frame.funcs.push(CoreDef::Lower(lower.clone())); + } + LocalInitializer::Lift(lift) => { + frame.component_funcs.push(ComponentFuncDef::Lifted(lift.clone())); + } + LocalInitializer::Resource(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Resource initializers are not supported" + ) + } + LocalInitializer::ResourceNew(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Resource creation is not supported" + ) + } + LocalInitializer::ResourceRep(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Resource representation is not supported" + ) + } + LocalInitializer::ResourceDrop(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Resource dropping is not supported" + ) + } + LocalInitializer::ModuleStatic(static_module_idx) => { + frame.modules.push(ModuleDef::Static(*static_module_idx)); + } + LocalInitializer::ModuleInstantiate(module_idx, ref args) => { + self.module_instantiation(frame, types, module_idx, args)?; + } + LocalInitializer::ModuleSynthetic(entities) => { + frame.module_instances.push(ModuleInstanceDef::Synthetic(entities)); + } + LocalInitializer::ComponentStatic(idx, ref vars) => { + frame.components.push(ComponentDef { + index: *idx, + closure: ComponentClosure { + modules: vars + .modules + .iter() + .map(|(_, m)| frame.closed_over_module(m)) + .collect(), + components: vars + .components + .iter() + .map(|(_, m)| frame.closed_over_component(m)) + .collect(), + }, + }); + } + LocalInitializer::ComponentInstantiate( + instance @ ComponentInstantiation { + component, + ref args, + ty: _, + }, + ) => { + let component: &ComponentDef = &frame.components[*component]; + + let translation = &self.nested_components[component.index]; + let mut new_frame = ComponentFrame::new( + translation.types_ref(), + args.iter() + .map(|(name, item)| Ok((*name, frame.item(*item, types)?))) + .collect::>()?, + ); + for init in &translation.initializers { + self.initializer(&mut new_frame, types, init)?; + } + let instance_idx = frame + .component_instances + .push(ComponentInstanceDef::Instantiated(instance.clone())); + frame.frames.insert(instance_idx, new_frame); + } + LocalInitializer::ComponentSynthetic(_) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Synthetic components are not yet supported" + ) + } + LocalInitializer::AliasExportFunc(module_instance_idx, name) => { + frame.funcs.push(CoreDef::Export(*module_instance_idx, name)); + } + LocalInitializer::AliasExportTable(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Table exports are not yet supported" + ) + } + LocalInitializer::AliasExportGlobal(..) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Global exports are not yet supported" + ) + } + LocalInitializer::AliasExportMemory(..) => { + // Do nothing, assuming Rust compiled code having one memory instance. + } + LocalInitializer::AliasComponentExport(component_instance_idx, name) => { + let import = &frame.component_instances[*component_instance_idx].unwrap_import(); + let def = ComponentItemDef::from_import( + name, + types[import.ty].exports[*name], + *component_instance_idx, + ); + frame.push_item(def); + } + LocalInitializer::AliasModule(_) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Module aliases are not yet supported" + ) + } + LocalInitializer::AliasComponent(_) => { + unsupported_diag!( + &self.context.session.diagnostics, + "Component aliases are not yet supported" + ) + } + LocalInitializer::Export(name, component_item) => { + match component_item { + ComponentItem::Func(i) => { + frame.component_funcs.push(frame.component_funcs[*i].clone()); + } + ComponentItem::ComponentInstance(_) => { + let unwrap_instance = component_item.unwrap_instance(); + let interface_name = name.to_string(); + self.component_export(frame, types, unwrap_instance, interface_name)?; + } + ComponentItem::Type(_) => { + // do nothing + } + _ => unsupported_diag!( + &self.context.session.diagnostics, + "Exporting of {:?} is not yet supported", + component_item + ), + } + } + } + Ok(()) + } + + fn component_export( + &mut self, + frame: &mut ComponentFrame<'a>, + types: &mut ComponentTypesBuilder, + component_instance_idx: ComponentInstanceIndex, + interface_name: String, + ) -> Result<(), Report> { + let instance = &frame.component_instances[component_instance_idx].unwrap_instantiated(); + let static_component_idx = frame.components[instance.component].index; + let parsed_component = &self.nested_components[static_component_idx]; + let module = Ident::new(Symbol::intern(interface_name.clone()), SourceSpan::default()); + // let functions = parsed_component + // .exports + // .iter() + // .flat_map(|(name, item)| { + // if let ComponentItem::Func(f) = item { + // self.component_export_func( + // frame, + // types, + // component_instance_idx, + // module, + // name, + // f, + // ) + // } else { + // // we're only interested in exported functions + // vec![] + // } + // }) + // .collect(); + // let interface = Interface { + // name: interface_name, + // functions, + // }; + // self.result.root_mut().interfaces.push(interface); + frame.component_instances.push(ComponentInstanceDef::Export); + Ok(()) + } + + fn component_export_func( + &self, + frame: &ComponentFrame<'a>, + types: &mut ComponentTypesBuilder, + component_instance_idx: ComponentInstanceIndex, + module: Ident, + name: &str, + f: &ComponentFuncIndex, + ) -> Vec { + let nested_frame = &frame.frames[&component_instance_idx]; + let canon_lift = nested_frame.component_funcs[*f].unwrap_canon_lift(); + let type_func_idx = types.convert_component_func_type(frame.types, canon_lift.ty).unwrap(); + + let component_types = types.resources_mut_and_types().1; + let func_ty = convert_lifted_func_ty(&type_func_idx, component_types); + let signature = Signature { + params: func_ty.params.into_iter().map(AbiParam::new).collect(), + results: func_ty.results.into_iter().map(AbiParam::new).collect(), + cc: CallConv::CanonLift, + linkage: Linkage::External, + }; + + let function_id = FunctionIdent { + module, + function: Ident::new(Symbol::intern(name.to_string()), SourceSpan::default()), + }; + let function = hir2_sketch::SyntheticFunction { + id: function_id, + signature, + inner_function: self.core_module_export_func_id(frame, canon_lift), + }; + vec![function] + } + + fn core_module_export_func_id( + &self, + frame: &ComponentFrame<'a>, + canon_lift: &CanonLift, + ) -> FunctionIdent { + let core_func_id: FunctionIdent = match &frame.funcs[canon_lift.func] { + CoreDef::Export(module_instance_idx, name) => { + match &frame.module_instances[*module_instance_idx] { + ModuleInstanceDef::Instantiated { + module_idx, + args: _, + } => match frame.modules[*module_idx] { + ModuleDef::Static(static_module_idx) => { + let parsed_module = &self.nested_modules[static_module_idx]; + let func_idx = parsed_module.module.exports[*name].unwrap_func(); + let func_name = parsed_module.module.func_name(func_idx); + let module_ident = parsed_module.module.name(); + FunctionIdent { + module: module_ident, + function: Ident::new(func_name, SourceSpan::default()), + } + } + ModuleDef::Import(_) => { + panic!("expected static module") + } + }, + ModuleInstanceDef::Synthetic(_hash_map) => { + panic!("expected instantiated module") + } + } + } + CoreDef::Lower(canon_lower) => { + panic!("expected export, got {:?}", canon_lower) + } + }; + core_func_id + } + + fn module_instantiation( + &mut self, + frame: &mut ComponentFrame<'a>, + types: &mut ComponentTypesBuilder, + module_idx: &ModuleIndex, + args: &'a FxHashMap<&str, ModuleInstanceIndex>, + ) -> Result<(), Report> { + frame.module_instances.push(ModuleInstanceDef::Instantiated { + module_idx: *module_idx, + args: args.clone(), + }); + + let mut import_canon_lower_args: FxHashMap = FxHashMap::default(); + match &frame.modules[*module_idx] { + ModuleDef::Static(static_module_idx) => { + let parsed_module = &self.nested_modules[*static_module_idx]; + // let mut module = Module { + // name: parsed_module.module.name(), + // functions: vec![], + // }; + for module_arg in args { + let arg_module_name = module_arg.0; + let module_ident = + Ident::new(Symbol::intern(*arg_module_name), SourceSpan::default()); + let arg_module = &frame.module_instances[*module_arg.1]; + match arg_module { + ModuleInstanceDef::Instantiated { + module_idx: _, + args: _, + } => { + unsupported_diag!( + &self.context.session.diagnostics, + "Instantiated module as another module instantiation argument is \ + not supported yet" + ) + } + ModuleInstanceDef::Synthetic(entities) => { + // module with CanonLower synthetic functions + for (func_name, entity) in entities.iter() { + let (signature, func_id) = + canon_lower_func(frame, types, module_ident, func_name, entity); + import_canon_lower_args.insert(func_id, signature); + } + } + } + } + + // TODO: the part below happens inside `build_ir` while translating the + // core module with `import_canon_lower_args` passed as a parameter. + for import in &parsed_module.module.imports { + // find the CanonLower function signature in the instantiation args for + // every core module function import + let internal_import_func_name = match import.index { + EntityIndex::Function(func_idx) => parsed_module.module.func_name(func_idx), + _ => panic!( + "only function import supported in Wasm core modules yet, got {:?}", + import.index + ), + }; + let import_func_id = FunctionIdent { + module: Ident::new(Symbol::intern(&import.module), SourceSpan::default()), + function: Ident::new(Symbol::intern(&import.field), SourceSpan::default()), + }; + // TODO: handle error + let import_canon_lower_func_sig = + &import_canon_lower_args.remove(&import_func_id).unwrap(); + + // let internal_func_id = FunctionIdent { + // module: module.name, + // function: Ident::new(internal_import_func_name, SourceSpan::default()), + // }; + // let function = hir2_sketch::SyntheticFunction { + // id: internal_func_id, + // signature: import_canon_lower_func_sig.clone(), + // inner_function: import_func_id, + // }; + // module.functions.push(function); + } + + // self.result.root_mut().modules.push(module); + } + ModuleDef::Import(_) => { + panic!("Module import instantiation is not supported yet") + } + }; + Ok(()) + } + + fn component_import( + &mut self, + frame: &mut ComponentFrame<'a>, + types: &mut ComponentTypesBuilder, + name: &wasmparser::ComponentImportName<'_>, + ty: &ComponentEntityType, + ) -> Result<(), Report> { + let ty = types.convert_component_entity_type(frame.types, *ty).map_err(Report::msg)?; + let ty = match ty { + TypeDef::ComponentInstance(type_component_instance_idx) => type_component_instance_idx, + _ => panic!("expected component instance"), + }; + frame + .component_instances + .push(ComponentInstanceDef::Import(ComponentInstanceImport { + name: name.0.to_string(), + ty, + })); + // TODO: create World in hir2 + // + // let interface_name = name.0.to_string(); + // let module = Ident::new(Symbol::intern(interface_name.clone()), SourceSpan::default()); + // let inner_function_empty = FunctionIdent { + // module: Ident::new(Symbol::intern(""), SourceSpan::default()), + // function: Ident::new(Symbol::intern(""), SourceSpan::default()), + // }; + // let component_types = types.resources_mut_and_types().1; + // let instance_type = &component_types[ty]; + // let functions = instance_type + // // TODO: need `exports` to have a stable order or find a different source for the + // // function list + // // + // .exports + // .iter() + // .filter_map(|(name, ty)| { + // import_component_export_func( + // module, + // inner_function_empty, + // component_types, + // name, + // ty, + // ) + // }) + // .collect(); + // let interface = Interface { + // name: interface_name.clone(), + // functions, + // }; + // let import_component = Component { + // name: interface_name, + // interfaces: vec![interface], + // modules: Default::default(), + // }; + // self.result.add_import(import_component); + Ok(()) + } +} + +fn import_component_export_func( + module: Ident, + inner_function_empty: FunctionIdent, + component_types: &super::ComponentTypes, + name: &String, + ty: &TypeDef, +) -> Option { + if let TypeDef::ComponentFunc(func_ty) = ty { + let func_ty = convert_lifted_func_ty(func_ty, component_types); + let signature = Signature { + params: func_ty.params.into_iter().map(AbiParam::new).collect(), + results: func_ty.results.into_iter().map(AbiParam::new).collect(), + cc: CallConv::CanonLift, + linkage: Linkage::External, + }; + Some(hir2_sketch::SyntheticFunction { + id: FunctionIdent { + module, + function: Ident::new(Symbol::intern(name), SourceSpan::default()), + }, + signature, + inner_function: inner_function_empty, + }) + } else { + None + } +} + +fn canon_lower_func( + frame: &mut ComponentFrame, + types: &mut ComponentTypesBuilder, + module_ident: Ident, + func_name: &str, + entity: &EntityIndex, +) -> (Signature, FunctionIdent) { + let func_id = entity.unwrap_func(); + let canon_lower = frame.funcs[func_id].unwrap_canon_lower(); + let func_name_ident = Ident::new(Symbol::intern(func_name), SourceSpan::default()); + // TODO: handle error + let type_func_idx = + types.convert_component_func_type(frame.types, canon_lower.lower_ty).unwrap(); + + let component_types = types.resources_mut_and_types().1; + let func_ty = convert_lifted_func_ty(&type_func_idx, component_types); + let signature = Signature { + params: func_ty.params.into_iter().map(AbiParam::new).collect(), + results: func_ty.results.into_iter().map(AbiParam::new).collect(), + cc: CallConv::CanonLower, + linkage: Linkage::External, + }; + + let func_id = FunctionIdent { + module: module_ident, + function: func_name_ident, + }; + (signature, func_id) +} + +#[derive(Clone, Debug)] +enum ComponentInstanceDef<'a> { + Import(ComponentInstanceImport), + Instantiated(ComponentInstantiation<'a>), + Export, +} +impl<'a> ComponentInstanceDef<'a> { + fn unwrap_import(&self) -> ComponentInstanceImport { + match self { + ComponentInstanceDef::Import(import) => import.clone(), + _ => panic!("expected import"), + } + } + + fn unwrap_instantiated(&self) -> &ComponentInstantiation { + match self { + ComponentInstanceDef::Instantiated(i) => i, + _ => panic!("expected instantiated"), + } + } +} + +#[derive(Debug, Clone)] +struct ComponentInstanceImport { + name: String, + ty: TypeComponentInstanceIndex, +} + +#[derive(Clone, Debug)] +enum ComponentFuncDef<'a> { + /// A host-imported component function. + Import(ComponentInstanceIndex, &'a str), + + /// A core wasm function was lifted into a component function. + Lifted(CanonLift), +} +impl<'a> ComponentFuncDef<'a> { + fn unwrap_canon_lift(&self) -> &CanonLift { + match self { + ComponentFuncDef::Lifted(lift) => lift, + _ => panic!("expected lift, got {:?}", self), + } + } +} + +#[derive(Clone)] +enum ModuleDef { + /// A core wasm module statically defined within the original component. + /// + /// The `StaticModuleIndex` indexes into the `static_modules` map in the + /// `Inliner`. + Static(StaticModuleIndex), + + /// A core wasm module that was imported from the host. + Import(TypeModuleIndex), +} + +/// "Closure state" for a component which is resolved from the `ClosedOverVars` +/// state that was calculated during translation. +#[derive(Default, Clone)] +struct ComponentClosure { + modules: PrimaryMap, + components: PrimaryMap, +} + +#[derive(Clone)] +struct ComponentDef { + index: StaticComponentIndex, + closure: ComponentClosure, +} + +/// Definition of a core wasm item and where it can come from within a +/// component. +#[derive(Debug, Clone)] +pub enum CoreDef<'a> { + /// This item refers to an export of a previously instantiated core wasm + /// instance. + Export(ModuleInstanceIndex, &'a str), + Lower(CanonLower), +} + +impl<'a> CoreDef<'a> { + pub fn unwrap_canon_lower(&self) -> &CanonLower { + match self { + CoreDef::Lower(lower) => lower, + _ => panic!("expected lower"), + } + } +} + +enum ModuleInstanceDef<'a> { + /// A core wasm module instance was created through the instantiation of a + /// module. + Instantiated { + module_idx: ModuleIndex, + args: FxHashMap<&'a str, ModuleInstanceIndex>, + }, + + /// A "synthetic" core wasm module which is just a bag of named indices. + Synthetic(&'a FxHashMap<&'a str, EntityIndex>), +} + +/// Representation of all items which can be defined within a component. +/// +/// This is the "value" of an item defined within a component and is used to +/// represent both imports and exports. +#[derive(Clone)] +enum ComponentItemDef<'a> { + Component(ComponentDef), + Instance(ComponentInstanceDef<'a>), + Func(ComponentFuncDef<'a>), + Module(ModuleDef), + Type(TypeDef), +} + +impl<'a> ComponentItemDef<'a> { + fn from_import( + name: &'a str, + ty: TypeDef, + component_instance_idx: ComponentInstanceIndex, + ) -> ComponentItemDef<'a> { + let item = match ty { + TypeDef::Module(ty) => ComponentItemDef::Module(ModuleDef::Import(ty)), + TypeDef::ComponentInstance(ty) => { + ComponentItemDef::Instance(ComponentInstanceDef::Import(ComponentInstanceImport { + name: name.to_string(), + ty, + })) + } + TypeDef::ComponentFunc(_ty) => { + ComponentItemDef::Func(ComponentFuncDef::Import(component_instance_idx, name)) + } + TypeDef::Component(_ty) => panic!("root-level component imports are not supported"), + TypeDef::Interface(_) | TypeDef::Resource(_) => ComponentItemDef::Type(ty), + }; + item + } +} + +struct ComponentFrame<'a> { + types: TypesRef<'a>, + + /// The "closure arguments" to this component, or otherwise the maps indexed + /// by `ModuleUpvarIndex` and `ComponentUpvarIndex`. This is created when + /// a component is created and stored as part of a component's state during + /// inlining. + closure: ComponentClosure, + + /// The arguments to the creation of this component. + /// + /// At the root level these are all imports from the host and between + /// components this otherwise tracks how all the arguments are defined. + args: FxHashMap<&'a str, ComponentItemDef<'a>>, + + // core wasm index spaces + funcs: PrimaryMap>, + // memories: PrimaryMap>, + // tables: PrimaryMap>, + // globals: PrimaryMap>, + modules: PrimaryMap, + + // component model index spaces + component_funcs: PrimaryMap>, + module_instances: PrimaryMap>, + component_instances: PrimaryMap>, + frames: FxHashMap>, + components: PrimaryMap, +} + +impl<'a> ComponentFrame<'a> { + fn new(types: TypesRef<'a>, args: FxHashMap<&'a str, ComponentItemDef<'a>>) -> Self { + Self { + types, + funcs: PrimaryMap::new(), + component_funcs: PrimaryMap::new(), + component_instances: PrimaryMap::new(), + components: PrimaryMap::new(), + modules: PrimaryMap::new(), + closure: Default::default(), + module_instances: Default::default(), + args, + frames: Default::default(), + } + } + + fn closed_over_module(&self, index: &ClosedOverModule) -> ModuleDef { + match *index { + ClosedOverModule::Local(i) => self.modules[i].clone(), + ClosedOverModule::Upvar(i) => self.closure.modules[i].clone(), + } + } + + fn closed_over_component(&self, index: &ClosedOverComponent) -> ComponentDef { + match *index { + ClosedOverComponent::Local(i) => self.components[i].clone(), + ClosedOverComponent::Upvar(i) => self.closure.components[i].clone(), + } + } + + fn item( + &self, + index: ComponentItem, + types: &mut ComponentTypesBuilder, + ) -> WasmResult> { + Ok(match index { + ComponentItem::Func(i) => ComponentItemDef::Func(self.component_funcs[i].clone()), + ComponentItem::Component(i) => ComponentItemDef::Component(self.components[i].clone()), + ComponentItem::ComponentInstance(i) => { + ComponentItemDef::Instance(self.component_instances[i].clone()) + } + ComponentItem::Module(i) => ComponentItemDef::Module(self.modules[i].clone()), + ComponentItem::Type(t) => { + // TODO: handle error + ComponentItemDef::Type(types.convert_type(self.types, t).unwrap()) + } + }) + } + + /// Pushes the component `item` definition provided into the appropriate + /// index space within this component. + fn push_item(&mut self, item: ComponentItemDef<'a>) { + match item { + ComponentItemDef::Func(i) => { + self.component_funcs.push(i); + } + ComponentItemDef::Module(i) => { + self.modules.push(i); + } + ComponentItemDef::Component(i) => { + self.components.push(i); + } + ComponentItemDef::Instance(i) => { + self.component_instances.push(i); + } + ComponentItemDef::Type(_ty) => {} + } + } +} diff --git a/frontend-wasm/src/component/translator2/hir2_sketch.rs b/frontend-wasm/src/component/translator2/hir2_sketch.rs new file mode 100644 index 00000000..7bc9714a --- /dev/null +++ b/frontend-wasm/src/component/translator2/hir2_sketch.rs @@ -0,0 +1,218 @@ +use std::fmt; + +use midenc_hir::{formatter::PrettyPrint, FunctionIdent, Ident, Signature}; + +#[derive(Debug)] +pub struct SyntheticFunction { + pub id: FunctionIdent, + pub signature: Signature, + pub inner_function: FunctionIdent, +} + +impl fmt::Display for SyntheticFunction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.pretty_print(f) + } +} + +impl PrettyPrint for SyntheticFunction { + fn render(&self) -> midenc_hir::formatter::Document { + use midenc_hir::formatter::*; + + const_text("(") + + const_text("synth_func") + + const_text(" ") + + display(self.id) + + const_text(" ") + + self.signature.render() + + const_text(" (inner ") + + self.inner_function.render() + + const_text(")") + + const_text(")") + } +} + +#[derive(Debug)] +pub struct Interface { + pub name: String, + pub functions: Vec, +} + +impl fmt::Display for Interface { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.pretty_print(f) + } +} + +impl PrettyPrint for Interface { + fn render(&self) -> midenc_hir::formatter::Document { + use midenc_hir::formatter::*; + + let functions = self + .functions + .iter() + .map(PrettyPrint::render) + .reduce(|acc, doc| acc + nl() + doc) + .unwrap_or(Document::Empty); + + const_text("(") + + const_text("interface") + + const_text(" ") + + text(&self.name) + + indent(4, nl() + functions) + + nl() + + const_text(")") + } +} + +#[derive(Debug)] +pub struct Module { + pub name: Ident, + pub functions: Vec, +} + +impl fmt::Display for Module { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.pretty_print(f) + } +} + +impl PrettyPrint for Module { + fn render(&self) -> midenc_hir::formatter::Document { + use midenc_hir::formatter::*; + + let functions = self + .functions + .iter() + .map(PrettyPrint::render) + .reduce(|acc, doc| acc + nl() + doc) + .unwrap_or(Document::Empty); + + const_text("(") + + const_text("module") + + const_text(" ") + + display(self.name) + + indent(4, nl() + functions) + + nl() + + const_text(")") + } +} + +#[derive(Debug, Default)] +pub struct Component { + pub name: String, + pub interfaces: Vec, + pub modules: Vec, +} + +impl fmt::Display for Component { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.pretty_print(f) + } +} + +impl PrettyPrint for Component { + fn render(&self) -> midenc_hir::formatter::Document { + use midenc_hir::formatter::*; + + let interfaces = self + .interfaces + .iter() + .map(PrettyPrint::render) + .reduce(|acc, doc| acc + nl() + doc) + .map(|doc| const_text(";; Interfaces") + nl() + doc) + .unwrap_or(Document::Empty); + + let modules = self + .modules + .iter() + .map(PrettyPrint::render) + .reduce(|acc, doc| acc + nl() + doc) + .map(|doc| const_text(";; Modules") + nl() + doc) + .unwrap_or(Document::Empty); + + let body = vec![interfaces, modules] + .into_iter() + .filter(|section| !section.is_empty()) + .fold(nl(), |a, b| { + if matches!(a, Document::Newline) { + indent(4, a + b) + } else { + a + nl() + indent(4, nl() + b) + } + }); + + const_text("(") + + const_text("component") + + const_text(" ") + + text(&self.name) + + body + + nl() + + const_text(")") + + nl() + } +} + +#[derive(Debug, Default)] +pub struct World { + pub components: Vec, +} + +impl fmt::Display for World { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.pretty_print(f) + } +} + +impl PrettyPrint for World { + fn render(&self) -> midenc_hir::formatter::Document { + use midenc_hir::formatter::*; + + let components = self + .components + .iter() + .map(PrettyPrint::render) + .reduce(|acc, doc| acc + nl() + doc) + .unwrap_or(Document::Empty); + + const_text("(") + + const_text("world") + + indent(4, nl() + components) + + nl() + + const_text(")") + + nl() + } +} + +pub struct WorldBuilder { + root: Component, + imports: Vec, +} + +impl WorldBuilder { + pub fn new(name: String) -> Self { + Self { + root: Component { + name, + interfaces: vec![], + modules: vec![], + }, + imports: vec![], + } + } + + pub fn root_mut(&mut self) -> &mut Component { + &mut self.root + } + + pub fn add_import(&mut self, component: Component) { + self.imports.push(component); + } + + pub fn build(self) -> World { + let mut components = Vec::with_capacity(1 + self.imports.len()); + components.extend(self.imports); + components.push(self.root); + World { components } + } +} diff --git a/frontend-wasm/src/component/types/mod.rs b/frontend-wasm/src/component/types/mod.rs index 727c14d7..3485f1ed 100644 --- a/frontend-wasm/src/component/types/mod.rs +++ b/frontend-wasm/src/component/types/mod.rs @@ -248,6 +248,14 @@ pub enum ComponentItem { ComponentInstance(ComponentInstanceIndex), Type(types::ComponentAnyTypeId), } +impl ComponentItem { + pub(crate) fn unwrap_instance(&self) -> ComponentInstanceIndex { + match self { + ComponentItem::ComponentInstance(i) => *i, + _ => panic!("expected a component instance, got {:?}", self), + } + } +} /// Runtime information about the type information contained within a component. /// diff --git a/frontend-wasm/src/error.rs b/frontend-wasm/src/error.rs index a42b399c..ec83bfdf 100644 --- a/frontend-wasm/src/error.rs +++ b/frontend-wasm/src/error.rs @@ -72,7 +72,7 @@ pub type WasmResult = Result; macro_rules! unsupported_diag { ($diagnostics:expr, $($arg:tt)*) => {{ return Err($diagnostics - .diagnostic(Severity::Error) + .diagnostic(midenc_hir::diagnostics::Severity::Error) .with_message(format!($($arg)*)) .into_report()); }} diff --git a/frontend-wasm/src/lib.rs b/frontend-wasm/src/lib.rs index 58c311f6..67bfb5e7 100644 --- a/frontend-wasm/src/lib.rs +++ b/frontend-wasm/src/lib.rs @@ -21,6 +21,7 @@ mod translation_utils; mod test_utils; use component::build_ir::translate_component; +pub use component::build_ir::translate_component2; use error::WasmResult; use midenc_session::Session; use module::build_ir::translate_module_as_component; diff --git a/frontend-wasm/src/module/mod.rs b/frontend-wasm/src/module/mod.rs index 7cb100ef..115c8326 100644 --- a/frontend-wasm/src/module/mod.rs +++ b/frontend-wasm/src/module/mod.rs @@ -8,7 +8,7 @@ use std::{borrow::Cow, collections::BTreeMap, ops::Range}; use indexmap::IndexMap; use midenc_hir::{ cranelift_entity::{packed_option::ReservedValue, EntityRef, PrimaryMap}, - diagnostics::{DiagnosticsHandler, Severity}, + diagnostics::DiagnosticsHandler, FxHashMap, Ident, Symbol, }; diff --git a/frontend-wasm/src/translation_utils.rs b/frontend-wasm/src/translation_utils.rs index e4861aeb..452fb7df 100644 --- a/frontend-wasm/src/translation_utils.rs +++ b/frontend-wasm/src/translation_utils.rs @@ -1,7 +1,7 @@ //! Helper functions and structures for the translation. use midenc_hir::{ - diagnostics::{DiagnosticsHandler, Severity, SourceSpan}, + diagnostics::{DiagnosticsHandler, SourceSpan}, AbiParam, CallConv, Felt, FieldElement, InstBuilder, Linkage, Signature, Value, }; use midenc_hir_type::{FunctionType, Type}; diff --git a/hir2/src/dialects/builtin/builders/component.rs b/hir2/src/dialects/builtin/builders/component.rs index c12bfa7a..8fea49ad 100644 --- a/hir2/src/dialects/builtin/builders/component.rs +++ b/hir2/src/dialects/builtin/builders/component.rs @@ -1,24 +1,27 @@ use crate::{ dialects::builtin::{ - Component, InterfaceRef, ModuleRef, PrimInterfaceBuilder, PrimModuleBuilder, + ComponentRef, InterfaceRef, ModuleRef, PrimInterfaceBuilder, PrimModuleBuilder, }, Builder, Ident, Op, OpBuilder, Report, Spanned, }; -pub struct ComponentBuilder<'b> { - pub component: &'b mut Component, +pub struct ComponentBuilder { + pub component: ComponentRef, builder: OpBuilder, } -impl<'b> ComponentBuilder<'b> { - pub fn new(component: &'b mut Component) -> Self { - let context = component.as_operation().context_rc(); +impl ComponentBuilder { + pub fn new(component: ComponentRef) -> Self { + let component_ref = component.borrow(); + let context = component_ref.as_operation().context_rc(); let mut builder = OpBuilder::new(context); - if component.body().is_empty() { - builder.create_block(component.body().as_region_ref(), None, &[]); - } else { - let current_block = component.body().entry_block_ref().unwrap(); + let body = component_ref.body(); + if let Some(current_block) = body.entry_block_ref() { builder.set_insertion_point_to_end(current_block); + } else { + let body_ref = body.as_region_ref(); + drop(body); + builder.create_block(body_ref, None, &[]); } Self { component, builder } diff --git a/hir2/src/dialects/builtin/ops.rs b/hir2/src/dialects/builtin/ops.rs index 1e81fef3..46bc0cc1 100644 --- a/hir2/src/dialects/builtin/ops.rs +++ b/hir2/src/dialects/builtin/ops.rs @@ -8,7 +8,7 @@ mod segment; pub use self::{ component::{ Component, ComponentBuilder as PrimComponentBuilder, ComponentExport, ComponentId, - ComponentInterface, ModuleExport, ModuleInterface, + ComponentInterface, ComponentRef, ModuleExport, ModuleInterface, }, function::{Function, FunctionBuilder as PrimFunctionBuilder, FunctionRef, LocalId}, global_variable::*, diff --git a/hir2/src/dialects/builtin/ops/component.rs b/hir2/src/dialects/builtin/ops/component.rs index 7fc5fba9..61def999 100644 --- a/hir2/src/dialects/builtin/ops/component.rs +++ b/hir2/src/dialects/builtin/ops/component.rs @@ -7,14 +7,17 @@ use crate::{ derive::operation, dialects::builtin::BuiltinDialect, traits::{ - GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, NoRegionArguments, - NoTerminator, SingleBlock, SingleRegion, + GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, NoTerminator, SingleBlock, + SingleRegion, }, version::Version, Ident, Operation, RegionKind, RegionKindInterface, Symbol, SymbolManager, SymbolManagerMut, - SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolUseList, Usable, Visibility, + SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolUseList, UnsafeIntrusiveEntityRef, Usable, + Visibility, }; +pub type ComponentRef = UnsafeIntrusiveEntityRef; + /// A [Component] is a modular abstraction operation, i.e. it is designed to model shared-nothing /// boundaries between groups of shared-everything modules in a system. /// @@ -61,7 +64,7 @@ use crate::{ traits( SingleRegion, SingleBlock, - NoRegionArguments, + // NoRegionArguments, NoTerminator, HasOnlyGraphRegion, GraphRegionNoTerminator, diff --git a/hir2/src/ir/block.rs b/hir2/src/ir/block.rs index 7253e7d3..3f7c95b7 100644 --- a/hir2/src/ir/block.rs +++ b/hir2/src/ir/block.rs @@ -624,6 +624,7 @@ impl Block { /// Insert this block after `after` in its containing region. /// /// Panics if this block is already attached to a region, or if `after` is not attached. + #[track_caller] pub fn insert_after(&mut self, after: BlockRef) { assert!( self.region.is_none(), @@ -643,6 +644,7 @@ impl Block { /// Insert this block before `before` in its containing region. /// /// Panics if this block is already attached to a region, or if `before` is not attached. + #[track_caller] pub fn insert_before(&mut self, before: BlockRef) { assert!( self.region.is_none(), @@ -662,6 +664,7 @@ impl Block { /// Insert this block at the end of `region`. /// /// Panics if this block is already attached to a region. + #[track_caller] pub fn insert_at_end(&mut self, mut region: RegionRef) { assert!( self.region.is_none(), @@ -675,6 +678,7 @@ impl Block { } /// Unlink this block from its current region and insert it right before `before` + #[track_caller] pub fn move_before(&mut self, before: BlockRef) { self.unlink(); self.insert_before(before); diff --git a/hir2/src/ir/entity.rs b/hir2/src/ir/entity.rs index e6c3d968..2b8b9ce3 100644 --- a/hir2/src/ir/entity.rs +++ b/hir2/src/ir/entity.rs @@ -1132,11 +1132,13 @@ impl RawEntityMetadata { } } impl RawEntityMetadata { + #[track_caller] pub(crate) fn borrow(&self) -> EntityRef<'_, T> { let ptr = self as *const Self; unsafe { (*core::ptr::addr_of!((*ptr).entity)).borrow() } } + #[track_caller] pub(crate) fn borrow_mut(&self) -> EntityMut<'_, T> { let ptr = (self as *const Self).cast_mut(); unsafe { (*core::ptr::addr_of_mut!((*ptr).entity)).borrow_mut() } diff --git a/hir2/src/ir/entity/list.rs b/hir2/src/ir/entity/list.rs index d6d8b43e..0307345b 100644 --- a/hir2/src/ir/entity/list.rs +++ b/hir2/src/ir/entity/list.rs @@ -251,8 +251,9 @@ impl<'a, T> EntityCursor<'a, T> { /// Consume the cursor and convert it into a borrow of the current entity, or `None` if null. #[inline] + #[track_caller] pub fn into_borrow(self) -> Option> { - self.cursor.get().map(|item| item.borrow()) + Some(self.cursor.get()?.borrow()) } /// Moves the cursor to the next element of the [EntityList]. diff --git a/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.hir b/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.hir new file mode 100644 index 00000000..aaad43c6 --- /dev/null +++ b/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.hir @@ -0,0 +1,26 @@ +(world + (component root + ;; Interfaces + (interface miden:basic-wallet/basic-wallet@1.0.0 + (synth_func (#miden:basic-wallet/basic-wallet@1.0.0 #receive-asset (cc lift) (param (struct (struct (struct (struct felt) (struct felt) (struct felt) (struct felt))))) (inner (#basic_wallet #miden:basic-wallet/basic-wallet@1.0.0#receive-asset)) + (synth_func (#miden:basic-wallet/basic-wallet@1.0.0 #send-asset (cc lift) (param (struct (struct (struct (struct felt) (struct felt) (struct felt) (struct felt))))) (param (struct (struct felt))) (param (struct (struct felt))) (param (struct (struct (struct (struct felt) (struct felt) (struct felt) (struct felt))))) (inner (#basic_wallet #miden:basic-wallet/basic-wallet@1.0.0#send-asset)) + ) + (interface miden:basic-wallet/aux@1.0.0 + (synth_func (#miden:basic-wallet/aux@1.0.0 #test-felt-intrinsics (cc lift) (param (struct felt)) (param (struct felt)) (result (struct felt)) (inner (#basic_wallet #miden:basic-wallet/aux@1.0.0#test-felt-intrinsics)) + (synth_func (#miden:basic-wallet/aux@1.0.0 #test-stdlib (cc lift) (param (list u8)) (result (list u8)) (inner (#basic_wallet #miden:basic-wallet/aux@1.0.0#test-stdlib)) + (synth_func (#miden:basic-wallet/aux@1.0.0 #process-list-felt (cc lift) (param (list (struct felt))) (result (list (struct felt))) (inner (#basic_wallet #miden:basic-wallet/aux@1.0.0#process-list-felt)) + (synth_func (#miden:basic-wallet/aux@1.0.0 #process-core-asset (cc lift) (param (struct (struct (struct (struct felt) (struct felt) (struct felt) (struct felt))))) (result (struct (struct (struct (struct felt) (struct felt) (struct felt) (struct felt))))) (inner (#basic_wallet #miden:basic-wallet/aux@1.0.0#process-core-asset)) + ) + + ;; Modules + (module #basic_wallet + (synth_func (#basic_wallet #miden_stdlib_sys::intrinsics::felt::extern_add (cc lower) (param felt) (param felt) (result felt) (inner (#miden:core-import/intrinsics-felt@1.0.0 #add)) + (synth_func (#basic_wallet #miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_1to1 (cc lower) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (inner (#miden:core-import/stdlib-crypto-hashes-blake3@1.0.0 #hash-one-to-one)) + (synth_func (#basic_wallet #miden_sdk_alloc::heap_base (cc lower) (result i32) (inner (#miden:core-import/intrinsics-mem@1.0.0 #heap-base)) + (synth_func (#basic_wallet #miden_base_sys::bindings::account::extern_account_add_asset (cc lower) (param felt) (param felt) (param felt) (param felt) (param i32) (inner (#miden:core-import/account@1.0.0 #add-asset)) + (synth_func (#basic_wallet #miden_base_sys::bindings::account::extern_account_remove_asset (cc lower) (param felt) (param felt) (param felt) (param felt) (param i32) (inner (#miden:core-import/account@1.0.0 #remove-asset)) + (synth_func (#basic_wallet #miden_base_sys::bindings::tx::extern_tx_create_note (cc lower) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (param felt) (result felt) (inner (#miden:core-import/tx@1.0.0 #create-note)) + ) + ) + +) diff --git a/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.wat b/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.wat new file mode 100644 index 00000000..8c21a741 --- /dev/null +++ b/tests/integration/expected/rust_sdk/hir2_sketch_multi_interface.wat @@ -0,0 +1,1003 @@ +(component + (type (;0;) + (instance + (type (;0;) (record (field "inner" float32))) + (export (;1;) "felt" (type (eq 0))) + (type (;2;) (tuple 1 1 1 1)) + (type (;3;) (record (field "inner" 2))) + (export (;4;) "word" (type (eq 3))) + (type (;5;) (record (field "inner" 4))) + (export (;6;) "core-asset" (type (eq 5))) + (type (;7;) (record (field "inner" 1))) + (export (;8;) "tag" (type (eq 7))) + (type (;9;) (record (field "inner" 4))) + (export (;10;) "recipient" (type (eq 9))) + (type (;11;) (record (field "inner" 1))) + (export (;12;) "note-type" (type (eq 11))) + ) + ) + (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))) + ) + ) + (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;2;) (type 2))) + (type (;3;) + (instance + (type (;0;) (func (param "a0" s32) (param "a1" s32) (param "a2" s32) (param "a3" s32) (param "a4" s32) (param "a5" s32) (param "a6" s32) (param "a7" s32) (param "result-ptr" s32))) + (export (;0;) "hash-one-to-one" (func (type 0))) + ) + ) + (import "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" (instance (;3;) (type 3))) + (type (;4;) + (instance + (type (;0;) (func (param "asset0" float32) (param "asset1" float32) (param "asset2" float32) (param "asset3" float32) (param "result-ptr" s32))) + (export (;0;) "add-asset" (func (type 0))) + (export (;1;) "remove-asset" (func (type 0))) + ) + ) + (import "miden:core-import/account@1.0.0" (instance (;4;) (type 4))) + (type (;5;) + (instance + (type (;0;) (func (param "asset0" float32) (param "asset1" float32) (param "asset2" float32) (param "asset3" float32) (param "tag" float32) (param "note-type" float32) (param "recipient0" float32) (param "recipient1" float32) (param "recipient2" float32) (param "recipient3" float32) (result float32))) + (export (;0;) "create-note" (func (type 0))) + ) + ) + (import "miden:core-import/tx@1.0.0" (instance (;5;) (type 5))) + (core module (;0;) + (type (;0;) (func (param f32 f32) (result f32))) + (type (;1;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (type (;2;) (func (result i32))) + (type (;3;) (func (param f32 f32 f32 f32 i32))) + (type (;4;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) (result f32))) + (type (;5;) (func)) + (type (;6;) (func (param i32 i32) (result i32))) + (type (;7;) (func (param i32 i32 i32))) + (type (;8;) (func (param i32 i32 i32 i32) (result i32))) + (type (;9;) (func (param f32 f32 f32 f32))) + (type (;10;) (func (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32))) + (type (;11;) (func (param i32))) + (type (;12;) (func (param f32 f32 f32 f32) (result i32))) + (type (;13;) (func (param i32 i32 i32) (result i32))) + (type (;14;) (func (param i32 i32))) + (type (;15;) (func (param i32 f32 f32 i32) (result f32))) + (type (;16;) (func (param i32 i32 i32 i32))) + (import "miden:core-import/intrinsics-felt@1.0.0" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;0;) (type 0))) + (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 (;1;) (type 1))) + (import "miden:core-import/intrinsics-mem@1.0.0" "heap-base" (func $miden_sdk_alloc::heap_base (;2;) (type 2))) + (import "miden:core-import/account@1.0.0" "add-asset" (func $miden_base_sys::bindings::account::extern_account_add_asset (;3;) (type 3))) + (import "miden:core-import/account@1.0.0" "remove-asset" (func $miden_base_sys::bindings::account::extern_account_remove_asset (;4;) (type 3))) + (import "miden:core-import/tx@1.0.0" "create-note" (func $miden_base_sys::bindings::tx::extern_tx_create_note (;5;) (type 4))) + (func $__wasm_call_ctors (;6;) (type 5)) + (func $basic_wallet::bindings::__link_custom_section_describing_imports (;7;) (type 5)) + (func $__rust_alloc (;8;) (type 6) (param i32 i32) (result i32) + i32.const 1048632 + local.get 1 + local.get 0 + call $::alloc + ) + (func $__rust_dealloc (;9;) (type 7) (param i32 i32 i32)) + (func $__rust_realloc (;10;) (type 8) (param i32 i32 i32 i32) (result i32) + block ;; label = @1 + i32.const 1048632 + 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 $__rust_alloc_zeroed (;11;) (type 6) (param i32 i32) (result i32) + block ;; label = @1 + i32.const 1048632 + local.get 1 + local.get 0 + call $::alloc + local.tee 1 + i32.eqz + br_if 0 (;@1;) + local.get 1 + i32.const 0 + local.get 0 + memory.fill + end + local.get 1 + ) + (func $miden:basic-wallet/basic-wallet@1.0.0#receive-asset (;12;) (type 9) (param f32 f32 f32 f32) + (local i32 i32) + global.get $__stack_pointer + local.tee 4 + i32.const 64 + i32.sub + i32.const -32 + i32.and + local.tee 5 + global.set $__stack_pointer + call $wit_bindgen_rt::run_ctors_once + local.get 5 + local.get 3 + f32.store offset=12 + local.get 5 + local.get 2 + f32.store offset=8 + local.get 5 + local.get 1 + f32.store offset=4 + local.get 5 + local.get 0 + f32.store + local.get 5 + i32.const 32 + i32.add + local.get 5 + call $miden_base_sys::bindings::account::add_asset + local.get 4 + global.set $__stack_pointer + ) + (func $miden:basic-wallet/basic-wallet@1.0.0#send-asset (;13;) (type 10) (param f32 f32 f32 f32 f32 f32 f32 f32 f32 f32) + (local i32 i32) + global.get $__stack_pointer + local.tee 10 + i32.const 96 + i32.sub + i32.const -32 + i32.and + local.tee 11 + global.set $__stack_pointer + call $wit_bindgen_rt::run_ctors_once + local.get 11 + local.get 3 + f32.store offset=12 + local.get 11 + local.get 2 + f32.store offset=8 + local.get 11 + local.get 1 + f32.store offset=4 + local.get 11 + local.get 0 + f32.store + local.get 11 + local.get 9 + f32.store offset=44 + local.get 11 + local.get 8 + f32.store offset=40 + local.get 11 + local.get 7 + f32.store offset=36 + local.get 11 + local.get 6 + f32.store offset=32 + local.get 11 + i32.const 64 + i32.add + local.get 11 + call $miden_base_sys::bindings::account::remove_asset + local.get 11 + i32.const 64 + i32.add + local.get 4 + local.get 5 + local.get 11 + i32.const 32 + i32.add + call $miden_base_sys::bindings::tx::create_note + drop + local.get 10 + global.set $__stack_pointer + ) + (func $miden:basic-wallet/aux@1.0.0#test-felt-intrinsics (;14;) (type 0) (param f32 f32) (result f32) + call $wit_bindgen_rt::run_ctors_once + local.get 0 + local.get 1 + call $miden_stdlib_sys::intrinsics::felt::extern_add + ) + (func $miden:basic-wallet/aux@1.0.0#test-stdlib (;15;) (type 6) (param i32 i32) (result i32) + (local i32 i32 i32 i32 i32 i32 i32 i32) + global.get $__stack_pointer + local.tee 2 + local.set 3 + local.get 2 + i32.const 96 + i32.sub + i32.const -32 + i32.and + local.tee 2 + global.set $__stack_pointer + call $wit_bindgen_rt::run_ctors_once + local.get 2 + local.get 0 + i32.store offset=24 + local.get 2 + local.get 1 + i32.store offset=20 + block ;; label = @1 + block ;; label = @2 + local.get 1 + i32.const 32 + i32.ne + br_if 0 (;@2;) + local.get 2 + i32.const 0 + i32.store offset=28 + local.get 0 + i32.load align=1 + local.set 1 + local.get 0 + i32.load offset=4 align=1 + local.set 4 + local.get 0 + i32.load offset=8 align=1 + local.set 5 + local.get 0 + i32.load offset=12 align=1 + local.set 6 + local.get 0 + i32.load offset=16 align=1 + local.set 7 + local.get 0 + i32.load offset=20 align=1 + local.set 8 + local.get 0 + i32.load offset=24 align=1 + local.set 9 + local.get 0 + i32.load offset=28 align=1 + local.set 0 + local.get 2 + i32.const 20 + i32.add + call $ as core::ops::drop::Drop>::drop + local.get 2 + i32.const 20 + i32.add + call $ as core::ops::drop::Drop>::drop + local.get 1 + local.get 4 + local.get 5 + local.get 6 + local.get 7 + local.get 8 + local.get 9 + local.get 0 + local.get 2 + i32.const 32 + i32.add + call $miden_stdlib_sys::stdlib::crypto::hashes::extern_blake3_hash_1to1 + local.get 2 + i32.const 84 + i32.add + i32.const 32 + i32.const 0 + call $alloc::raw_vec::RawVec::try_allocate_in + local.get 2 + i32.load offset=88 + local.set 1 + local.get 2 + i32.load offset=84 + i32.const 1 + i32.eq + br_if 1 (;@1;) + local.get 2 + i32.load offset=92 + local.tee 0 + i32.const 24 + i32.add + local.get 2 + i64.load offset=56 + i64.store align=1 + local.get 0 + i32.const 16 + i32.add + local.get 2 + i64.load offset=48 + i64.store align=1 + local.get 0 + i32.const 8 + i32.add + local.get 2 + i64.load offset=40 + i64.store align=1 + local.get 0 + local.get 2 + i64.load offset=32 + i64.store align=1 + local.get 2 + i32.const 32 + i32.store offset=92 + local.get 2 + local.get 0 + i32.store offset=88 + local.get 2 + local.get 1 + i32.store offset=84 + local.get 2 + i32.const 8 + i32.add + local.get 2 + i32.const 84 + i32.add + call $alloc::vec::Vec::into_boxed_slice + i32.const 0 + local.get 2 + i64.load offset=8 + i64.store offset=1048616 align=4 + local.get 3 + global.set $__stack_pointer + i32.const 1048616 + return + end + unreachable + end + local.get 1 + local.get 2 + i32.load offset=92 + call $alloc::raw_vec::handle_error + unreachable + ) + (func $miden:basic-wallet/aux@1.0.0#process-list-felt (;16;) (type 6) (param i32 i32) (result i32) + call $wit_bindgen_rt::run_ctors_once + unreachable + ) + (func $cabi_post_miden:basic-wallet/aux@1.0.0#process-list-felt (;17;) (type 11) (param i32)) + (func $miden:basic-wallet/aux@1.0.0#process-core-asset (;18;) (type 12) (param f32 f32 f32 f32) (result i32) + call $wit_bindgen_rt::run_ctors_once + unreachable + ) + (func $cabi_realloc_wit_bindgen_0_28_0 (;19;) (type 8) (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 (;20;) (type 8) (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=1048636 + 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 (;21;) (type 5) + block ;; label = @1 + i32.const 0 + i32.load8_u offset=1048637 + br_if 0 (;@1;) + call $__wasm_call_ctors + i32.const 0 + i32.const 1 + i32.store8 offset=1048637 + end + ) + (func $::alloc (;22;) (type 13) (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 $miden_base_sys::bindings::account::add_asset (;23;) (type 14) (param i32 i32) + local.get 1 + f32.load + local.get 1 + f32.load offset=4 + local.get 1 + f32.load offset=8 + local.get 1 + f32.load offset=12 + local.get 0 + call $miden_base_sys::bindings::account::extern_account_add_asset + ) + (func $miden_base_sys::bindings::account::remove_asset (;24;) (type 14) (param i32 i32) + local.get 1 + f32.load + local.get 1 + f32.load offset=4 + local.get 1 + f32.load offset=8 + local.get 1 + f32.load offset=12 + local.get 0 + call $miden_base_sys::bindings::account::extern_account_remove_asset + ) + (func $miden_base_sys::bindings::tx::create_note (;25;) (type 15) (param i32 f32 f32 i32) (result f32) + local.get 0 + f32.load + local.get 0 + f32.load offset=4 + local.get 0 + f32.load offset=8 + local.get 0 + f32.load offset=12 + local.get 1 + local.get 2 + local.get 3 + f32.load + local.get 3 + f32.load offset=4 + local.get 3 + f32.load offset=8 + local.get 3 + f32.load offset=12 + call $miden_base_sys::bindings::tx::extern_tx_create_note + ) + (func $alloc::vec::Vec::into_boxed_slice (;26;) (type 14) (param i32 i32) + (local i32 i32) + global.get $__stack_pointer + i32.const 16 + i32.sub + local.tee 2 + global.set $__stack_pointer + block ;; label = @1 + block ;; label = @2 + local.get 1 + i32.load + local.get 1 + i32.load offset=8 + local.tee 3 + i32.le_u + br_if 0 (;@2;) + local.get 2 + i32.const 8 + i32.add + local.get 1 + local.get 3 + call $alloc::raw_vec::RawVec::shrink_unchecked + local.get 2 + i32.load offset=8 + i32.const -2147483647 + i32.ne + br_if 1 (;@1;) + local.get 1 + i32.load offset=8 + local.set 3 + end + local.get 0 + local.get 3 + i32.store offset=4 + local.get 0 + local.get 1 + i32.load offset=4 + i32.store + local.get 2 + i32.const 16 + i32.add + global.set $__stack_pointer + return + end + unreachable + ) + (func $ as core::ops::drop::Drop>::drop (;27;) (type 11) (param i32)) + (func $ as core::ops::drop::Drop>::drop (;28;) (type 11) (param i32) + (local i32) + block ;; label = @1 + local.get 0 + i32.load + local.tee 1 + i32.eqz + br_if 0 (;@1;) + local.get 0 + i32.load offset=4 + i32.const 1 + local.get 1 + call $::deallocate + end + ) + (func $alloc::raw_vec::RawVec::try_allocate_in (;29;) (type 7) (param i32 i32 i32) + (local i32 i32) + global.get $__stack_pointer + i32.const 16 + i32.sub + local.tee 3 + global.set $__stack_pointer + block ;; label = @1 + block ;; label = @2 + local.get 1 + br_if 0 (;@2;) + local.get 0 + i64.const 4294967296 + i64.store offset=4 align=4 + i32.const 0 + local.set 1 + br 1 (;@1;) + end + block ;; label = @2 + block ;; label = @3 + local.get 1 + i32.const -1 + i32.gt_s + local.tee 4 + br_if 0 (;@3;) + local.get 0 + i32.const 0 + i32.store offset=4 + br 1 (;@2;) + end + block ;; label = @3 + block ;; label = @4 + local.get 2 + br_if 0 (;@4;) + local.get 3 + i32.const 8 + i32.add + local.get 4 + local.get 1 + call $::allocate + local.get 3 + i32.load offset=8 + local.set 2 + br 1 (;@3;) + end + local.get 3 + local.get 4 + local.get 1 + i32.const 1 + call $alloc::alloc::Global::alloc_impl + local.get 3 + i32.load + local.set 2 + end + block ;; label = @3 + local.get 2 + i32.eqz + br_if 0 (;@3;) + local.get 0 + local.get 2 + i32.store offset=8 + local.get 0 + local.get 1 + i32.store offset=4 + i32.const 0 + local.set 1 + br 2 (;@1;) + end + local.get 0 + local.get 1 + i32.store offset=8 + local.get 0 + local.get 4 + i32.store offset=4 + end + i32.const 1 + local.set 1 + end + local.get 0 + local.get 1 + i32.store + local.get 3 + i32.const 16 + i32.add + global.set $__stack_pointer + ) + (func $::allocate (;30;) (type 7) (param i32 i32 i32) + (local i32) + global.get $__stack_pointer + i32.const 16 + i32.sub + local.tee 3 + global.set $__stack_pointer + local.get 3 + i32.const 8 + i32.add + local.get 1 + local.get 2 + i32.const 0 + call $alloc::alloc::Global::alloc_impl + local.get 3 + i32.load offset=12 + local.set 2 + local.get 0 + local.get 3 + i32.load offset=8 + i32.store + local.get 0 + local.get 2 + i32.store offset=4 + local.get 3 + i32.const 16 + i32.add + global.set $__stack_pointer + ) + (func $alloc::alloc::Global::alloc_impl (;31;) (type 16) (param i32 i32 i32 i32) + block ;; label = @1 + local.get 2 + i32.eqz + br_if 0 (;@1;) + block ;; label = @2 + local.get 3 + br_if 0 (;@2;) + i32.const 0 + i32.load8_u offset=1048636 + drop + local.get 2 + local.get 1 + call $__rust_alloc + local.set 1 + br 1 (;@1;) + end + local.get 2 + local.get 1 + call $__rust_alloc_zeroed + local.set 1 + end + local.get 0 + local.get 2 + i32.store offset=4 + local.get 0 + local.get 1 + i32.store + ) + (func $alloc::raw_vec::RawVec::shrink_unchecked (;32;) (type 7) (param i32 i32 i32) + (local i32 i32 i32 i32) + i32.const -2147483647 + local.set 3 + block ;; label = @1 + local.get 1 + i32.load + local.tee 4 + i32.eqz + br_if 0 (;@1;) + local.get 1 + i32.load offset=4 + local.set 5 + block ;; label = @2 + block ;; label = @3 + local.get 2 + br_if 0 (;@3;) + i32.const 1 + local.set 6 + local.get 5 + i32.const 1 + local.get 4 + call $::deallocate + br 1 (;@2;) + end + i32.const 1 + local.set 3 + local.get 5 + local.get 4 + i32.const 1 + local.get 2 + call $__rust_realloc + local.tee 6 + i32.eqz + br_if 1 (;@1;) + end + local.get 1 + local.get 2 + i32.store + local.get 1 + local.get 6 + i32.store offset=4 + i32.const -2147483647 + local.set 3 + end + local.get 0 + local.get 2 + i32.store offset=4 + local.get 0 + local.get 3 + i32.store + ) + (func $::deallocate (;33;) (type 7) (param i32 i32 i32) + block ;; label = @1 + local.get 2 + i32.eqz + br_if 0 (;@1;) + local.get 0 + local.get 2 + local.get 1 + call $__rust_dealloc + end + ) + (func $alloc::raw_vec::handle_error (;34;) (type 14) (param i32 i32) + unreachable + ) + (func $cabi_realloc (;35;) (type 8) (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:basic-wallet/basic-wallet@1.0.0#receive-asset" (func $miden:basic-wallet/basic-wallet@1.0.0#receive-asset)) + (export "miden:basic-wallet/basic-wallet@1.0.0#send-asset" (func $miden:basic-wallet/basic-wallet@1.0.0#send-asset)) + (export "miden:basic-wallet/aux@1.0.0#test-felt-intrinsics" (func $miden:basic-wallet/aux@1.0.0#test-felt-intrinsics)) + (export "miden:basic-wallet/aux@1.0.0#test-stdlib" (func $miden:basic-wallet/aux@1.0.0#test-stdlib)) + (export "miden:basic-wallet/aux@1.0.0#process-list-felt" (func $miden:basic-wallet/aux@1.0.0#process-list-felt)) + (export "cabi_post_miden:basic-wallet/aux@1.0.0#process-list-felt" (func $cabi_post_miden:basic-wallet/aux@1.0.0#process-list-felt)) + (export "miden:basic-wallet/aux@1.0.0#process-core-asset" (func $miden:basic-wallet/aux@1.0.0#process-core-asset)) + (export "cabi_post_miden:basic-wallet/aux@1.0.0#test-stdlib" (func $cabi_post_miden:basic-wallet/aux@1.0.0#process-list-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 $basic_wallet::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 2 "add" (func (;0;))) + (core func (;0;) (canon lower (func 0))) + (core instance (;0;) + (export "add" (func 0)) + ) + (alias export 3 "hash-one-to-one" (func (;1;))) + (core func (;1;) (canon lower (func 1))) + (core instance (;1;) + (export "hash-one-to-one" (func 1)) + ) + (alias export 1 "heap-base" (func (;2;))) + (core func (;2;) (canon lower (func 2))) + (core instance (;2;) + (export "heap-base" (func 2)) + ) + (alias export 4 "add-asset" (func (;3;))) + (core func (;3;) (canon lower (func 3))) + (alias export 4 "remove-asset" (func (;4;))) + (core func (;4;) (canon lower (func 4))) + (core instance (;3;) + (export "add-asset" (func 3)) + (export "remove-asset" (func 4)) + ) + (alias export 5 "create-note" (func (;5;))) + (core func (;5;) (canon lower (func 5))) + (core instance (;4;) + (export "create-note" (func 5)) + ) + (core instance (;5;) (instantiate 0 + (with "miden:core-import/intrinsics-felt@1.0.0" (instance 0)) + (with "miden:core-import/stdlib-crypto-hashes-blake3@1.0.0" (instance 1)) + (with "miden:core-import/intrinsics-mem@1.0.0" (instance 2)) + (with "miden:core-import/account@1.0.0" (instance 3)) + (with "miden:core-import/tx@1.0.0" (instance 4)) + ) + ) + (alias core export 5 "memory" (core memory (;0;))) + (alias core export 5 "cabi_realloc" (core func (;6;))) + (alias export 0 "core-asset" (type (;6;))) + (type (;7;) (func (param "core-asset" 6))) + (alias core export 5 "miden:basic-wallet/basic-wallet@1.0.0#receive-asset" (core func (;7;))) + (func (;6;) (type 7) (canon lift (core func 7))) + (alias export 0 "tag" (type (;8;))) + (alias export 0 "note-type" (type (;9;))) + (alias export 0 "recipient" (type (;10;))) + (type (;11;) (func (param "core-asset" 6) (param "tag" 8) (param "note-type" 9) (param "recipient" 10))) + (alias core export 5 "miden:basic-wallet/basic-wallet@1.0.0#send-asset" (core func (;8;))) + (func (;7;) (type 11) (canon lift (core func 8))) + (alias export 0 "felt" (type (;12;))) + (alias export 0 "word" (type (;13;))) + (alias export 0 "core-asset" (type (;14;))) + (alias export 0 "tag" (type (;15;))) + (alias export 0 "recipient" (type (;16;))) + (alias export 0 "note-type" (type (;17;))) + (component (;0;) + (type (;0;) (record (field "inner" float32))) + (import "import-type-felt" (type (;1;) (eq 0))) + (type (;2;) (tuple 1 1 1 1)) + (type (;3;) (record (field "inner" 2))) + (import "import-type-word" (type (;4;) (eq 3))) + (type (;5;) (record (field "inner" 4))) + (import "import-type-core-asset" (type (;6;) (eq 5))) + (type (;7;) (record (field "inner" 1))) + (import "import-type-tag" (type (;8;) (eq 7))) + (type (;9;) (record (field "inner" 4))) + (import "import-type-recipient" (type (;10;) (eq 9))) + (type (;11;) (record (field "inner" 1))) + (import "import-type-note-type" (type (;12;) (eq 11))) + (import "import-type-core-asset0" (type (;13;) (eq 6))) + (type (;14;) (func (param "core-asset" 13))) + (import "import-func-receive-asset" (func (;0;) (type 14))) + (import "import-type-tag0" (type (;15;) (eq 8))) + (import "import-type-note-type0" (type (;16;) (eq 12))) + (import "import-type-recipient0" (type (;17;) (eq 10))) + (type (;18;) (func (param "core-asset" 13) (param "tag" 15) (param "note-type" 16) (param "recipient" 17))) + (import "import-func-send-asset" (func (;1;) (type 18))) + (export (;19;) "core-asset" (type 6)) + (export (;20;) "tag" (type 8)) + (export (;21;) "recipient" (type 10)) + (export (;22;) "note-type" (type 12)) + (export (;23;) "felt" (type 1)) + (type (;24;) (func (param "core-asset" 19))) + (export (;2;) "receive-asset" (func 0) (func (type 24))) + (type (;25;) (func (param "core-asset" 19) (param "tag" 20) (param "note-type" 22) (param "recipient" 21))) + (export (;3;) "send-asset" (func 1) (func (type 25))) + ) + (instance (;6;) (instantiate 0 + (with "import-func-receive-asset" (func 6)) + (with "import-func-send-asset" (func 7)) + (with "import-type-felt" (type 12)) + (with "import-type-word" (type 13)) + (with "import-type-core-asset" (type 14)) + (with "import-type-tag" (type 15)) + (with "import-type-recipient" (type 16)) + (with "import-type-note-type" (type 17)) + (with "import-type-core-asset0" (type 6)) + (with "import-type-tag0" (type 8)) + (with "import-type-note-type0" (type 9)) + (with "import-type-recipient0" (type 10)) + ) + ) + (export (;7;) "miden:basic-wallet/basic-wallet@1.0.0" (instance 6)) + (alias export 0 "felt" (type (;18;))) + (type (;19;) (func (param "a" 18) (param "b" 18) (result 18))) + (alias core export 5 "miden:basic-wallet/aux@1.0.0#test-felt-intrinsics" (core func (;9;))) + (func (;8;) (type 19) (canon lift (core func 9))) + (type (;20;) (list u8)) + (type (;21;) (func (param "input" 20) (result 20))) + (alias core export 5 "miden:basic-wallet/aux@1.0.0#test-stdlib" (core func (;10;))) + (alias core export 5 "cabi_post_miden:basic-wallet/aux@1.0.0#test-stdlib" (core func (;11;))) + (func (;9;) (type 21) (canon lift (core func 10) (memory 0) (realloc 6) (post-return 11))) + (type (;22;) (list 18)) + (type (;23;) (func (param "input" 22) (result 22))) + (alias core export 5 "miden:basic-wallet/aux@1.0.0#process-list-felt" (core func (;12;))) + (alias core export 5 "cabi_post_miden:basic-wallet/aux@1.0.0#process-list-felt" (core func (;13;))) + (func (;10;) (type 23) (canon lift (core func 12) (memory 0) (realloc 6) (post-return 13))) + (type (;24;) (func (param "input" 6) (result 6))) + (alias core export 5 "miden:basic-wallet/aux@1.0.0#process-core-asset" (core func (;14;))) + (func (;11;) (type 24) (canon lift (core func 14) (memory 0))) + (component (;1;) + (type (;0;) (record (field "inner" float32))) + (import "import-type-felt" (type (;1;) (eq 0))) + (type (;2;) (tuple 1 1 1 1)) + (type (;3;) (record (field "inner" 2))) + (import "import-type-word" (type (;4;) (eq 3))) + (type (;5;) (record (field "inner" 4))) + (import "import-type-core-asset" (type (;6;) (eq 5))) + (type (;7;) (record (field "inner" 1))) + (import "import-type-tag" (type (;8;) (eq 7))) + (type (;9;) (record (field "inner" 4))) + (import "import-type-recipient" (type (;10;) (eq 9))) + (type (;11;) (record (field "inner" 1))) + (import "import-type-note-type" (type (;12;) (eq 11))) + (import "import-type-felt0" (type (;13;) (eq 1))) + (type (;14;) (func (param "a" 13) (param "b" 13) (result 13))) + (import "import-func-test-felt-intrinsics" (func (;0;) (type 14))) + (type (;15;) (list u8)) + (type (;16;) (func (param "input" 15) (result 15))) + (import "import-func-test-stdlib" (func (;1;) (type 16))) + (type (;17;) (list 13)) + (type (;18;) (func (param "input" 17) (result 17))) + (import "import-func-process-list-felt" (func (;2;) (type 18))) + (import "import-type-core-asset0" (type (;19;) (eq 6))) + (type (;20;) (func (param "input" 19) (result 19))) + (import "import-func-process-core-asset" (func (;3;) (type 20))) + (export (;21;) "core-asset" (type 6)) + (export (;22;) "tag" (type 8)) + (export (;23;) "recipient" (type 10)) + (export (;24;) "note-type" (type 12)) + (export (;25;) "felt" (type 1)) + (type (;26;) (func (param "a" 25) (param "b" 25) (result 25))) + (export (;4;) "test-felt-intrinsics" (func 0) (func (type 26))) + (type (;27;) (list u8)) + (type (;28;) (func (param "input" 27) (result 27))) + (export (;5;) "test-stdlib" (func 1) (func (type 28))) + (type (;29;) (list 25)) + (type (;30;) (func (param "input" 29) (result 29))) + (export (;6;) "process-list-felt" (func 2) (func (type 30))) + (type (;31;) (func (param "input" 21) (result 21))) + (export (;7;) "process-core-asset" (func 3) (func (type 31))) + ) + (instance (;8;) (instantiate 1 + (with "import-func-test-felt-intrinsics" (func 8)) + (with "import-func-test-stdlib" (func 9)) + (with "import-func-process-list-felt" (func 10)) + (with "import-func-process-core-asset" (func 11)) + (with "import-type-felt" (type 12)) + (with "import-type-word" (type 13)) + (with "import-type-core-asset" (type 14)) + (with "import-type-tag" (type 15)) + (with "import-type-recipient" (type 16)) + (with "import-type-note-type" (type 17)) + (with "import-type-felt0" (type 18)) + (with "import-type-core-asset0" (type 6)) + ) + ) + (export (;9;) "miden:basic-wallet/aux@1.0.0" (instance 8)) +) \ No newline at end of file diff --git a/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.hir b/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.hir new file mode 100644 index 00000000..a5c55443 --- /dev/null +++ b/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.hir @@ -0,0 +1,16 @@ +(world + (component root + ;; Interfaces + (interface miden:cross-ctx-account/foo@1.0.0 + (synth_func (#miden:cross-ctx-account/foo@1.0.0 #process-felt (cc lift) (param (struct felt)) (result (struct felt)) (inner (#cross_ctx_account #miden:cross-ctx-account/foo@1.0.0#process-felt)) + ) + + ;; Modules + (module #cross_ctx_account + (synth_func (#cross_ctx_account #miden_stdlib_sys::intrinsics::felt::extern_from_u32 (cc lower) (param u32) (result felt) (inner (#miden:core-import/intrinsics-felt@1.0.0 #from-u32)) + (synth_func (#cross_ctx_account #miden_stdlib_sys::intrinsics::felt::extern_add (cc lower) (param felt) (param felt) (result felt) (inner (#miden:core-import/intrinsics-felt@1.0.0 #add)) + (synth_func (#cross_ctx_account #miden_sdk_alloc::heap_base (cc lower) (result i32) (inner (#miden:core-import/intrinsics-mem@1.0.0 #heap-base)) + ) + ) + +) diff --git a/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.wat b/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.wat new file mode 100644 index 00000000..2dd92066 --- /dev/null +++ b/tests/integration/expected/rust_sdk/hir2_sketch_single_interface.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))) + (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" u32) (result float32))) + (export (;1;) "from-u32" (func (type 1))) + ) + ) + (import "miden:core-import/intrinsics-felt@1.0.0" (instance (;2;) (type 2))) + (core module (;0;) + (type (;0;) (func (param i32) (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-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)) + (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 + i32.const 3 + 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) + 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 3 + i32.popcnt + i32.const 1 + i32.ne + br_if 0 (;@1;) + i32.const -2147483648 + local.get 1 + local.get 3 + call $core::ptr::alignment::Alignment::max + local.tee 1 + i32.sub + local.get 2 + i32.lt_u + br_if 0 (;@1;) + i32.const 0 + local.set 3 + local.get 2 + local.get 1 + 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 $core::ptr::alignment::Alignment::max (;12;) (type 4) (param i32 i32) (result i32) + local.get 0 + local.get 1 + local.get 0 + local.get 1 + i32.gt_u + select + ) + (func $cabi_realloc (;13;) (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-u32" (func (;1;))) + (core func (;1;) (canon lower (func 1))) + (core instance (;0;) + (export "add" (func 0)) + (export "from-u32" (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/src/compiler_test.rs b/tests/integration/src/compiler_test.rs index 3ed91aa4..aaad22e4 100644 --- a/tests/integration/src/compiler_test.rs +++ b/tests/integration/src/compiler_test.rs @@ -1081,6 +1081,18 @@ impl CompilerTest { } } + /// Expect test that builds the IR2(sketch) + pub fn expect_ir2(&mut self, expected_hir_file: expect_test::ExpectFile) { + let ir = midenc_frontend_wasm::translate_component2( + &self.wasm_bytes(), + &self.config, + self.session.clone(), + ) + .expect("Failed to translate Wasm binary to IR component"); + let src = demangle(ir.borrow().as_ref().as_operation_ref().to_string()); + expected_hir_file.assert_eq(&src); + } + /// Compare the compiled MASM against the expected output pub fn expect_masm(&mut self, expected_masm_file: expect_test::ExpectFile) { let program = demangle(self.masm_src().as_str()); @@ -1241,7 +1253,10 @@ where { use midenc_hir::diagnostics::reporting::{self, ReportHandlerOpts}; - let result = reporting::set_hook(Box::new(|_| Box::new(ReportHandlerOpts::new().build()))); + let result = reporting::set_hook(Box::new(|_| { + let wrapping_width = 300; // avoid wrapped file paths in the backtrace + Box::new(ReportHandlerOpts::new().width(wrapping_width).build()) + })); if result.is_ok() { reporting::set_panic_hook(); } diff --git a/tests/integration/src/rust_masm_tests/rust_sdk.rs b/tests/integration/src/rust_masm_tests/rust_sdk.rs index ee883602..d53f21c3 100644 --- a/tests/integration/src/rust_masm_tests/rust_sdk.rs +++ b/tests/integration/src/rust_masm_tests/rust_sdk.rs @@ -218,3 +218,35 @@ fn rust_sdk_cross_ctx_note() { let trace = exec.execute(&package.unwrap_program(), &test.session); } + +#[test] +fn rust_sdk_hir2_sketch_multiple_interface_exports() { + // Testing the new frontend's Wasm component translator producing HIR2(sketch) + // from a Wasm component exporting two interfaces + 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/basic-wallet", + config, + [], + ); + let artifact_name = "hir2_sketch_multi_interface"; + test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); + test.expect_ir2(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); +} + +#[test] +fn rust_sdk_hir2_single_interface_export() { + // Testing the new frontend's Wasm component translator producing HIR2(sketch) + // from a Wasm component exporting one interface + 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 = "hir2_sketch_single_interface"; + test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]); + test.expect_ir2(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]); +}