Skip to content

Commit

Permalink
feature: draft LowerExportsCrossCtxStage implementation with a lot of
Browse files Browse the repository at this point in the history
hardcoded shortcuts.
  • Loading branch information
greenhat committed Nov 29, 2024
1 parent 6ebfeae commit d855730
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 5 deletions.
122 changes: 117 additions & 5 deletions midenc-compile/src/stages/lower_cross_ctx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
//! Lowering the exports for cross-context calls.
use midenc_hir::pass::AnalysisManager;
use midenc_session::Session;
use std::collections::BTreeMap;

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

use super::LinkerInput;
use crate::{stage::Stage, CompilerResult};
Expand All @@ -17,7 +23,9 @@ pub struct LowerExportsCrossCtxStage;

// TODO: load the rodata into the memory in the lowering to ensure that the fresh context is
// correctly initialized
// TODO: Don't lower the note script's entry point

// TODO: swap `lift` and `lower` in the component import/export pretty-printing to sync with
// this stage's terminology (an export is lowered, an import is lifted)

impl Stage for LowerExportsCrossCtxStage {
type Input = LinkerInput;
Expand All @@ -27,8 +35,112 @@ impl Stage for LowerExportsCrossCtxStage {
&mut self,
input: Self::Input,
_analyses: &mut AnalysisManager,
_session: &Session,
session: &Session,
) -> CompilerResult<Self::Output> {
Ok(input)
let component = if let LinkerInput::Hir(component) = input {
component
} else {
return Ok(input);
};

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

// For each component export ensure a module for each interface that exports lowered functions
// which and the end call this Wasm core module exported function

let mut lowered_exports: BTreeMap<InterfaceFunctionIdent, ComponentExport> =
BTreeMap::new();
let exports = component_builder.exports().clone();
for (id, export) in exports.into_iter() {
if let Canonical = export.function_ty.abi() {
// skip exports that are already lowered
lowered_exports.insert(id, export);
continue;
}
if let Some(entrypoint) = &session.options.entrypoint {
// skip the entrypoint
if entrypoint == &id.to_string() {
lowered_exports.insert(id, export);
continue;
}
}
let new_export = generate_lowered_function(
&mut component_builder,
id,
export,
&session.diagnostics,
)?;
lowered_exports.insert(id, new_export);
}

let component_builder = component_builder.with_exports(lowered_exports);

let component = component_builder.build();
// dbg!(&component.exports());
// dbg!(&component.modules().len());
Ok(LinkerInput::Hir(component.into()))
}
}

fn generate_lowered_function(
component_builder: &mut ComponentBuilder,
export_id: InterfaceFunctionIdent,
export: ComponentExport,
diagnostics: &DiagnosticsHandler,
) -> CompilerResult<ComponentExport> {
// get or create the module for the interface
let module_id = export_id.interface.full_name;
let mut module_builder = component_builder.module(module_id);
// TODO: analyze the signature and speculate what cross-context Miden ABI signature we need to export.
// For now just assume passing <16 felts and returning 1 and copy the signature
let cc_export_sig = Signature {
params: vec![AbiParam::new(Type::Felt)],
results: vec![AbiParam::new(Type::Felt)],
// TODO: add CallConv::CrossCtx
cc: CallConv::SystemV,
linkage: Linkage::External,
};
let mut builder = module_builder.function(export_id.function, cc_export_sig.clone())?;
let entry = builder.current_block();
let params = builder.block_params(entry).to_vec();
// TODO: lift the params from the cross-context Miden ABI to the Wasm CABI

// TODO: put the core function signature in the export
let core_sig = Signature {
params: vec![AbiParam::new(Type::Felt)],
results: vec![AbiParam::new(Type::Felt)],
cc: CallConv::SystemV,
linkage: Linkage::Internal,
};
let dfg = builder.data_flow_graph_mut();
// import the Wasm core function
if dfg.get_import(&export.function).is_none() {
dfg.import_function(export.function.module, export.function.function, core_sig)
.map_err(|_e| {
let message = format!(
"Function(callee of the lowering) with name {} in module {} with signature \
{cc_export_sig:?} is already imported (function call) with a different \
signature",
export.function.function, export.function.module
);
diagnostics.diagnostic(Severity::Error).with_message(message).into_report()
})?;
}
// TODO: use the span from the callee
let call = builder.ins().exec(export.function, &params, SourceSpan::UNKNOWN);
// dbg!(&sig);
// TODO: lower the result from the Wasm CABI to the cross-context Miden ABI
let result = builder.first_result(call);
builder.ins().ret(Some(result), SourceSpan::UNKNOWN);
let function_id = builder.build()?;
module_builder.build()?;
let component_export = ComponentExport {
function: function_id,
function_ty: FunctionType {
abi: Canonical,
..export.function_ty
},
..export
};
Ok(component_export)
}
9 changes: 9 additions & 0 deletions tests/integration/expected/rust_sdk/cross_ctx_account.masm
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# mod #anon::miden:cross-ctx-account/[email protected]

use.cross_ctx_account

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


# mod cross_ctx_account

use.intrinsics::mem
Expand Down

0 comments on commit d855730

Please sign in to comment.