Skip to content

Commit

Permalink
feature: draft lifting function generation in LiftImportsCrossCtxStage
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Dec 10, 2024
1 parent 9e10242 commit 4d45e2e
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions frontend-wasm/src/component/translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> {
}
}
for (name, export) in &wasm_translation.component.exports {
self.build_export(export, name, None, &mut component_builder)?;
self.build_export(export, name.clone(), None, &mut component_builder)?;
}
Ok(component_builder.build())
}
Expand Down Expand Up @@ -353,13 +353,13 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> {
fn build_export(
&self,
export: &Export,
name: &String,
name: String,
interface: Option<String>,
component_builder: &mut ComponentBuilder,
) -> WasmResult<()> {
match export {
Export::LiftedFunction { ty, func, options } => {
dbg!(name);
// dbg!(name);
// The inline export does no have an interface name
let interface = interface.unwrap_or_default();
// dbg!(&interface);
Expand All @@ -372,7 +372,12 @@ impl<'a, 'data> ComponentTranslator<'a, 'data> {
let interface = Some(name.clone());
// Flatten any(nested) interface instance exports into the IR `Component` exports
for (export_name, export) in exports {
self.build_export(export, export_name, interface.clone(), component_builder)?;
self.build_export(
export,
export_name.clone(),
interface.clone(),
component_builder,
)?;
}
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions hir/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl MidenAbiImport {
}

/// A component import
#[derive(Debug, Clone)]
#[derive(Debug, Clone, derive_more::From)]
pub enum ComponentImport {
/// A Wasm import that is following the Wasm Component Model Canonical ABI
CanonAbiImport(CanonAbiImport),
Expand Down Expand Up @@ -193,7 +193,7 @@ impl Component {
// Temporary imterim solution until we have a proper way to name components
let module_names = self.modules.keys().fold(String::new(), |acc, name| {
if acc.is_empty() {
name.to_string()
name.as_str().to_string()
} else {
acc + "+" + name.as_str()
}
Expand Down
1 change: 1 addition & 0 deletions midenc-compile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ midenc-hir-transform.workspace = true
midenc-session.workspace = true
thiserror.workspace = true
wat.workspace = true
derive_more.workspace = true
105 changes: 93 additions & 12 deletions midenc-compile/src/stages/lift_cross_ctx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
use std::collections::BTreeMap;

use midenc_hir::{pass::AnalysisManager, ComponentBuilder, ComponentImport, FunctionIdent};
use midenc_hir::{
diagnostics::Severity, pass::AnalysisManager, types::Abi, AbiParam, CallConv, CanonAbiImport,
ComponentBuilder, ComponentImport, FunctionIdent, FunctionType, InstBuilder, Linkage,
MidenAbiImport, Signature, SourceSpan, Symbol, Type,
};
use midenc_session::{DiagnosticsHandler, Session};

use super::LinkerInput;
Expand Down Expand Up @@ -33,6 +37,14 @@ impl Stage for LiftImportsCrossCtxStage {
return Ok(input);
};

// So far only hardcoded lift imports for the cross_ctx_note
if component.name().as_str() != "cross_ctx_note" {
return Ok(LinkerInput::Hir(component));
}

// dbg!(&component.imports());
// dbg!(&component.modules().keys());

let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics);

let mut lifted_imports: BTreeMap<FunctionIdent, ComponentImport> = BTreeMap::new();
Expand All @@ -43,32 +55,101 @@ impl Stage for LiftImportsCrossCtxStage {
lifted_imports.insert(id, import);
continue;
}
let new_import = generate_lifting_function(
let (new_import, lifting_func_id) = generate_lifting_function(
&mut component_builder,
id,
import,
import.unwrap_canon_abi_import(),
&session.diagnostics,
)?;
lifted_imports.insert(id, new_import);
lifted_imports.insert(lifting_func_id, new_import.into());

// TODO: find all the calls to the component import and replace them with the generated lifting function
}

let component_builder = component_builder.with_imports(lifted_imports);

let component = component_builder.build();

// dbg!(&component.imports());
// dbg!(&component.modules().len());
// dbg!(&component.modules().keys());

Ok(LinkerInput::Hir(component.into()))
}
}

fn generate_lifting_function(
_component_builder: &mut ComponentBuilder<'_>,
_id: FunctionIdent,
import: ComponentImport,
_diagnostics: &DiagnosticsHandler,
) -> CompilerResult<ComponentImport> {
// TODO: implement the lifting function generation
Ok(import)
component_builder: &mut ComponentBuilder<'_>,
_core_import_function: FunctionIdent,
import: &CanonAbiImport,
diagnostics: &DiagnosticsHandler,
) -> CompilerResult<(MidenAbiImport, FunctionIdent)> {
// get or create the module for the interface
let module_id = Symbol::intern(format!(
"lift-imports-{}",
import.interface_function.interface.full_name.as_str()
));
dbg!(&module_id);
// TODO: prefix the module name with "lift-imports-"? The same for the lowering exports module.
let mut module_builder = component_builder.module(module_id);
// TODO: put the core function signature (as imported in the core module) in the component import
let import_core_sig = Signature {
params: vec![AbiParam::new(Type::Felt)],
results: vec![AbiParam::new(Type::Felt)],
cc: CallConv::SystemV,
linkage: Linkage::External,
};
let mut builder =
module_builder.function(import.interface_function.function, import_core_sig.clone())?;
let entry = builder.current_block();
let params = builder.block_params(entry).to_vec();

// TODO: analyze the signature and speculate what cross-context Miden ABI signature would
// export have.
// For now just assume passing <16 felts and returning 1 and copy the signature
let import_lowered_sig = Signature {
params: vec![AbiParam::new(Type::Felt)],
results: vec![AbiParam::new(Type::Felt)],
// TODO: add CallConv::CrossCtx
cc: CallConv::SystemV,
linkage: Linkage::External,
};
let dfg = builder.data_flow_graph_mut();
// import the Wasm CM interface function
let import_func_id = FunctionIdent {
module: import.interface_function.interface.full_name.into(),
function: import.interface_function.function.into(),
};
if dfg.get_import(&import_func_id).is_none() {
dfg.import_function(
import_func_id.module,
import_func_id.function,
import_lowered_sig.clone(),
)
.map_err(|_e| {
let message = format!(
"Lifting function with name {} in module {} with signature {import_lowered_sig:?} \
is already imported (function call) with a different signature",
import_func_id.function, import_func_id.module
);
diagnostics.diagnostic(Severity::Error).with_message(message).into_report()
})?;
}
// TODO: use the span from the caller
// TODO: lower the params from the Wasm CABI to the cross-context Miden ABI
let call = builder.ins().call(import_func_id, &params, SourceSpan::UNKNOWN);
// dbg!(&sig);
// TODO: lift the result from the cross-context Miden ABI to Wasm CABI
let result = builder.first_result(call);
builder.ins().ret(Some(result), SourceSpan::UNKNOWN);
let function_id = builder.build()?;
module_builder.build()?;
let component_import = MidenAbiImport::new(FunctionType {
abi: Abi::Canonical,
params: import_lowered_sig.params.into_iter().map(|p| p.ty).collect(),
results: import_lowered_sig.results.into_iter().map(|r| r.ty).collect(),
});
// dbg!(&component_import);
// dbg!(&function_id);

Ok((component_import, function_id))
}
22 changes: 15 additions & 7 deletions midenc-compile/src/stages/lower_cross_ctx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use std::collections::BTreeMap;

use midenc_hir::{
diagnostics::Severity, pass::AnalysisManager, types::Abi::Canonical, AbiParam, CallConv,
ComponentBuilder, ComponentExport, FunctionType, InstBuilder, InterfaceFunctionIdent, Linkage,
Signature, SourceSpan, Type,
diagnostics::Severity,
pass::AnalysisManager,
types::Abi::{self, Canonical},
AbiParam, CallConv, ComponentBuilder, ComponentExport, FunctionType, InstBuilder,
InterfaceFunctionIdent, Linkage, Signature, SourceSpan, Type,
};
use midenc_session::{DiagnosticsHandler, Session};

Expand Down Expand Up @@ -45,6 +47,9 @@ impl Stage for LowerExportsCrossCtxStage {
return Ok(input);
};

// dbg!(&component.exports());
// dbg!(&component.modules().keys());

let mut component_builder = ComponentBuilder::load(*component, &session.diagnostics);

let mut lowered_exports: BTreeMap<InterfaceFunctionIdent, ComponentExport> =
Expand Down Expand Up @@ -80,6 +85,10 @@ impl Stage for LowerExportsCrossCtxStage {
let component_builder = component_builder.with_exports(lowered_exports);

let component = component_builder.build();

// dbg!(&component.exports());
// dbg!(&component.modules().keys());

Ok(LinkerInput::Hir(component.into()))
}
}
Expand Down Expand Up @@ -126,9 +135,8 @@ fn generate_lowering_function(
dfg.import_function(export.function.module, export.function.function, core_sig)
.map_err(|_e| {
let message = format!(
"Function(callee of the lowering) with name {} in module {} with signature \
{cc_export_sig:?} is already imported (function call) with a different \
signature",
"Lowering function with name {} in module {} with signature {cc_export_sig:?} \
is already imported (function call) with a different signature",
export.function.function, export.function.module
);
diagnostics.diagnostic(Severity::Error).with_message(message).into_report()
Expand All @@ -145,7 +153,7 @@ fn generate_lowering_function(
let component_export = ComponentExport {
function: function_id,
function_ty: FunctionType {
abi: Canonical,
abi: Abi::Canonical,
..export.function_ty
},
..export
Expand Down
9 changes: 9 additions & 0 deletions tests/integration/expected/rust_sdk/cross_ctx_note.masm
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# mod #anon::lift-imports-miden:cross-ctx-account/[email protected]

use.miden:cross-ctx-account/[email protected]

export."process-felt"
call.::miden:cross-ctx-account/[email protected]::"process-felt"
end


# mod cross_ctx_note

use.intrinsics::mem
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/src/compiler_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ impl CompilerTestBuilder {
},
)
}));
dbg!(&inputs);
// dbg!(&inputs);

CompilerTest {
config: self.config,
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/src/rust_masm_tests/rust_sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ fn rust_sdk_cross_ctx_note() {
.iter()
.map(|s| s.to_string())
.collect();
dbg!(env::current_dir().unwrap().display());
// dbg!(env::current_dir().unwrap().display());
let outputs = cargo_miden::run(args.into_iter(), cargo_miden::OutputType::Masm)
.expect("Failed to compile the cross-ctx-account package for cross-ctx-note");
let masp_path: PathBuf = outputs.first().unwrap().clone();
dbg!(&masp_path);
// dbg!(&masp_path);

let _ = env_logger::builder().is_test(true).try_init();

Expand Down

0 comments on commit 4d45e2e

Please sign in to comment.