Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6e2dbae
wip: v0.25 migration
bitwalker Jul 17, 2026
65d3499
fix debugvarinfo
bitwalker Jul 22, 2026
0fd2b82
feat(sdk): migrate SDK and examples to protocol 0.16 (#1292)
greenhat Jul 22, 2026
7c5109c
fix(sdk): preserve canonical interfaces in FPI bindings
greenhat Jul 10, 2026
4d0a087
fix(sdk): stabilize synthetic FPI binding identities
greenhat Jul 10, 2026
adfa3d6
refactor(sdk): centralize FPI binding invariants
greenhat Jul 13, 2026
6feef4d
fix(sdk): preserve semantic FPI signature types
greenhat Jul 13, 2026
1f2fa79
fix(sdk): distinguish FPI binding import worlds
greenhat Jul 13, 2026
8c1aba6
fix(sdk): reject ambient synthetic FPI package collisions
greenhat Jul 13, 2026
fa3727f
fix(sdk): qualify component metadata by package identity
greenhat Jul 13, 2026
162e52c
feat(sdk): add opt-in inline WIT emission
greenhat Jul 13, 2026
4e5f9bf
test: emit WIT artifacts from compiler fixtures
greenhat Jul 13, 2026
1df2b36
build(sdk): inherit wit-component from workspace
greenhat Jul 13, 2026
b37c5b7
perf(wasm): lower aligned accesses through element pointers
greenhat Jul 14, 2026
9e2706a
refactor(wasm): document and harden the element-pointer path in prepa…
greenhat Jul 14, 2026
2e590de
refactor(tests): share the test-component setup between compile helpers
greenhat Jul 14, 2026
73626da
test(wasm): pin element addressing and alignment fallback at runtime
greenhat Jul 14, 2026
36cea7d
refactor: un-link ELEMENT_SIZE_BYTES from ELEMENT_ALIGMENT_LOG2
greenhat Jul 16, 2026
20354e8
perf(cargo): optimize release guests at level two
greenhat Jul 14, 2026
6ce419b
fix(cargo): derive guest optimization from compiler settings
greenhat Jul 16, 2026
a7ec01e
feat(debug): propagate DWARF inline call chains
djolertrk Jul 23, 2026
7c48163
fix(masm): accept inline-call debug instructions
djolertrk Jul 23, 2026
8fbc4ef
fix(debug): resolve consolidated source locations
djolertrk Jul 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,644 changes: 1,034 additions & 610 deletions Cargo.lock

Large diffs are not rendered by default.

50 changes: 27 additions & 23 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,22 @@ litcheck-filecheck = "0.4"
log = { version = "0.4", features = ["kv"] }

# Miden Dependencies
miden-assembly = { version = "0.23", default-features = false }
miden-core = { version = "0.23", default-features = false }
miden-debug = { version = "0.8" }
miden-debug-types = { version = "0.23", default-features = false }
miden-assembly-syntax = { version = "0.23", default-features = false }
miden-assembly = { version = "0.25", default-features = false }
miden-core = { version = "0.25", default-features = false }
miden-debug = { version = "0.9" }
miden-debug-types = { version = "0.25", default-features = false }
miden-assembly-syntax = { version = "0.25", default-features = false }
miden-formatting = { version = "0.1", default-features = false }
miden-protocol = { version = "0.15", default-features = false }
miden-standards = { version = "0.15", default-features = false }
miden-protocol = { version = "=0.16.0-alpha.4", default-features = false }
miden-standards = { version = "=0.16.0-alpha.4", default-features = false }
miden-processor = { version = "0.25", default-features = false }
miden-core-lib = { version = "0.25", default-features = false }
miden-mast-package = { version = "0.25", default-features = false }
miden-package-registry = { version = "0.25", default-features = false }
miden-project = { version = "0.25", default-features = false }
miden-utils-sync = { version = "0.25", default-features = false }
midenc-hir-type = "0.9"

miden-processor = { version = "0.23", default-features = false }
miden-core-lib = { version = "0.23", default-features = false }
miden-mast-package = { version = "0.23", default-features = false }
miden-package-registry = { version = "0.23", default-features = false }
miden-project = { version = "0.23", default-features = false }
paste = "1.0"
parking_lot = "0.12"
petgraph = { version = "0.8", default-features = false, features = [
Expand Down Expand Up @@ -137,6 +139,7 @@ wasmparser = { version = "^0.248", default-features = false, features = [
"validate",
"simd",
] }
wit-component = "0.247"

# Workspace crates
midenc-codegen-masm = { version = "0.9.2", path = "codegen/masm" }
Expand Down Expand Up @@ -167,17 +170,18 @@ miden-field-repr = { version = "0.13.1", path = "sdk/field-repr/repr" }
miden-stdlib-sys = { version = "0.13.1", path = "sdk/stdlib-sys" }

[patch.crates-io]
#miden-assembly = { git = "https://github.com/0xMiden/miden-vm", rev = "614cd7f9b52f45238b0ab59c71ebb49325051e5d" }
#miden-assembly = { path = "../miden-vm/assembly" }
#miden-assembly-syntax = { path = "../miden-vm/assembly-syntax" }
#miden-core = { git = "https://github.com/0xMiden/miden-vm", rev = "614cd7f9b52f45238b0ab59c71ebb49325051e5d" }
#miden-core = { path = "../miden-vm/core" }
# miden-debug = { git = "https://github.com/0xMiden/miden-debug", branch = "main" }
#miden-debug-types = { path = "../miden-vm/crates/debug/types" }
#miden-processor = { git = "https://github.com/0xMiden/miden-vm", rev = "614cd7f9b52f45238b0ab59c71ebb49325051e5d" }
#miden-processor = { path = "../miden-vm/processor" }
#miden-mast-package = { git = "https://github.com/0xMiden/miden-vm", rev = "614cd7f9b52f45238b0ab59c71ebb49325051e5d" }
#miden-mast-package = { path = "../miden-vm/package" }
midenc-hir-type = { path = "../miden-vm/crates/midenc-hir-type"}
miden-assembly = { path = "../miden-vm/crates/assembly" }
miden-assembly-syntax = { path = "../miden-vm/crates/assembly-syntax" }
miden-core = { path = "../miden-vm/core" }
miden-core-lib = { path = "../miden-vm/crates/lib/core" }
miden-debug = { path = "../miden-debug" }
miden-debug-types = { path = "../miden-vm/crates/debug-types" }
miden-processor = { path = "../miden-vm/processor" }
miden-mast-package = { path = "../miden-vm/crates/mast-package" }
miden-package-registry = { path = "../miden-vm/crates/package-registry" }
miden-project = { path = "../miden-vm/crates/project" }
miden-utils-sync = { path = "../miden-vm/crates/utils-sync" }
#miden-protocol = { git = "https://github.com/0xMiden/protocol", rev = "a53bbe2209f506df87876c8b9c9a1730214f456b" }
#miden-standards = { git = "https://github.com/0xMiden/protocol", rev = "a53bbe2209f506df87876c8b9c9a1730214f456b" }
#miden-tx = { tag = "v0.14.0-beta.4", git = "https://github.com/0xMiden/miden-base" }
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ This will run all of the unit tests in the workspace, as well as all of our `lit
(comma-delimited), where `PATH` is treated either as folder e.g. `MIDENC_EMIT=ir=target/emit` or file `MIDENC_EMIT=hir=my_name.hir`.
- `MIDENC_EMIT_MACRO_EXPAND[=<dir>]`: When set, integration tests dump `cargo expand`
output for Rust fixtures to `<fixture>.expanded.rs` files in `<dir>` (or the CWD if empty/`1`).
- `MIDENC_EMIT_WIT[=<dir>]`: When set, integration tests emit public component WIT as
`<fixture>.wit` and resolved macro-generated inline worlds as `<package>.<world>.inline.wit` in
`<dir>` (or the CWD if empty/`1`). Resolved FPI worlds include their injected synthetic packages
and `fpi-*` functions. Generated SDK integration fixtures enable the internal WIT-printer
feature in their Cargo manifests.

## Docs

Expand Down
8 changes: 8 additions & 0 deletions codegen/masm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ doctest = false
default = ["std"]
std = [
"miden-assembly/std",
"miden-utils-sync/std",
"midenc-hir/std",
"midenc-dialect-hir/std",
"petgraph/std",
Expand All @@ -33,6 +34,7 @@ miden-core.workspace = true
miden-mast-package.workspace = true
miden-processor.workspace = true
miden-protocol.workspace = true
miden-utils-sync.workspace = true
midenc-hir.workspace = true
midenc-hir-analysis.workspace = true
midenc-dialect-arith.workspace = true
Expand All @@ -53,3 +55,9 @@ itertools = "0.14.0"
midenc-expect-test = { path = "../../tools/expect-test" }
midenc-hir = { path = "../../hir", features = ["logging"] }
proptest.workspace = true

[build-dependencies]
miden-assembly = { workspace = true, features = ["std"] }
miden-core-lib.workspace = true
midenc-log.workspace = true
midenc-session = { workspace = true, features = ["std"] }
51 changes: 51 additions & 0 deletions codegen/masm/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::{
env,
path::{Path, PathBuf},
};

use miden_assembly::{Assembler, Report, diagnostics::IntoDiagnostic};
use miden_core_lib::CoreLibrary;
use midenc_session::miden_package_registry::PackageCache;

fn main() -> Result<(), Report> {
use miden_assembly::diagnostics::reporting::ReportHandlerOpts;

// Rebuild the package if the content of the `intrinsics` directory changes
println!("cargo:rerun-if-changed=intrinsics");

miden_assembly::diagnostics::reporting::set_hook(Box::new(|_| {
Box::new(ReportHandlerOpts::new().build())
}))
.unwrap();
miden_assembly::diagnostics::reporting::set_panic_hook();

// Enable debug tracing to stderr via the MIDEN_LOG environment variable, if present
midenc_log::Builder::from_env("MIDENC_TRACE").format_timestamp(None).init();

// Build compiler-intrinsics library
let intrinsics_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("intrinsics");
let toolchain_dir = std::env::var_os("MIDEN_SYSROOT").map(PathBuf::from);
let cwd = env::current_dir().into_diagnostic()?;
let target_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let options =
midenc_session::Options::new(None, None, cwd, target_dir.clone(), None, toolchain_dir);

let mut registry = midenc_session::registry::HybridPackageRegistry::new(&options)?;
// Extend the registry with the built-in core library, in case the midenup toolchain is not
// available
registry.cache_package(CoreLibrary::default().package())?;

let assembler = Assembler::default();
let mut project_assembler =
assembler.for_project_at_path(intrinsics_dir.join("miden-project.toml"), &mut registry)?;

let package =
project_assembler.assemble(miden_assembly::ProjectTargetSelector::Library, "release")?;

let build_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

// write the masp output
package.write_masp_file(&build_dir).into_diagnostic()?;

Ok(())
}
13 changes: 13 additions & 0 deletions codegen/masm/intrinsics/miden-project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "compiler-intrinsics"
version = "0.9.0"

[lib]
namespace = "intrinsics"
path = "mod.masm"

[dependencies]
miden-core = "*"

[profile.release]
debug = true
4 changes: 4 additions & 0 deletions codegen/masm/intrinsics/mod.masm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod advice
pub mod i32
pub mod i64
pub mod mem
97 changes: 44 additions & 53 deletions codegen/masm/src/artifact.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use alloc::sync::Arc;
use core::fmt;

use miden_assembly::{Path, ast::InvocationTarget};
use miden_assembly::{Path, ProjectSourceInputs, ast::InvocationTarget};
use miden_core::Word;
use miden_mast_package::Package;
use midenc_hir::{constants::ConstantData, dialects::builtin, interner::Symbol};
use midenc_session::{
Emit, OutputMode, OutputType, Session, Writer,
diagnostics::{IntoDiagnostic, Report, SourceSpan, Span, WrapErr},
};

use crate::{TraceEvent, lower::NativePtr, masm};
use crate::{Event, lower::NativePtr, masm};

mod project_support;
//mod project_support;

pub struct MasmComponent {
pub id: Option<builtin::ComponentId>,
Expand All @@ -29,8 +28,6 @@ pub struct MasmComponent {
///
/// If unset, it indicates that the component is a library, even if it could be made executable.
pub entrypoint: Option<masm::InvocationTarget>,
/// The kernel library to link against
pub kernel: Option<masm::KernelLibrary>,
/// The rodata segments of this component keyed by the offset of the segment
pub rodata: Vec<Rodata>,
/// The address of the start of the global heap
Expand Down Expand Up @@ -150,55 +147,43 @@ inventory::submit! {

impl fmt::Display for MasmComponent {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use crate::intrinsics::INTRINSICS_MODULE_NAMES;

for module in self.modules.iter() {
// Skip printing the standard library modules and intrinsics modules to focus on the
// user-defined modules and avoid the
// stack overflow error when printing large programs
// https://github.com/0xMiden/miden-formatting/issues/4
let module_name = module.path().as_str();
let module_name_trimmed = module_name.trim_start_matches("::");
if INTRINSICS_MODULE_NAMES.contains(&module_name) {
continue;
}
if module.is_in_namespace(Path::new("std"))
|| module_name_trimmed.starts_with("miden::core")
|| module_name_trimmed.starts_with("miden::protocol")
{
continue;
} else {
writeln!(f, "# mod {}\n", &module_name)?;
writeln!(f, "{module}")?;
}
writeln!(f, "# mod {}\n", module.path())?;
writeln!(f, "{module}")?;
}
Ok(())
}
}

impl MasmComponent {
/// Assemble this component into a Miden package.
pub fn assemble(
pub fn source_inputs(
&self,
account_component_metadata_bytes: Option<&[u8]>,
target: &midenc_session::miden_project::Target,
session: &Session,
) -> Result<Arc<Package>, Report> {
project_support::assemble(self, account_component_metadata_bytes, session)
}
) -> Result<ProjectSourceInputs, Report> {
let is_executable_target = target.is_executable();
let emit_test_harness = session.get_flag("test_harness");
let mut support = Vec::with_capacity(self.modules.len());
let mut root = None;
for module in self.modules.iter() {
if module.path() == self.root.as_ref() {
root = Some(Box::new(Arc::unwrap_or_clone(module.clone())));
continue;
}

/// Assemble this component into a Miden package using a pre-populated package registry.
pub fn assemble_with_registry(
&self,
account_component_metadata_bytes: Option<&[u8]>,
session: &Session,
registry: &mut midenc_session::registry::HybridPackageRegistry,
) -> Result<Arc<Package>, Report> {
project_support::assemble_with_registry(
self,
account_component_metadata_bytes,
session,
registry,
)
support.push(Box::new(Arc::unwrap_or_clone(module.clone())));
}

if is_executable_target && let Some(entrypoint) = self.entrypoint.as_ref() {
// Our generated main module takes precedence here, so move the root module into support
support.extend(root);
let root =
self.generate_main(entrypoint, emit_test_harness, session.source_manager.clone())?;
return Ok(ProjectSourceInputs { root, support });
}

let root = root.expect("components must always have a root module");
Ok(ProjectSourceInputs { root, support })
}

/// Generate an executable module which when run expects the raw data segment data to be
Expand All @@ -208,7 +193,7 @@ impl MasmComponent {
&self,
entrypoint: &InvocationTarget,
emit_test_harness: bool,
source_manager: Arc<dyn midenc_session::SourceManager + Send + Sync>,
source_manager: Arc<dyn midenc_session::SourceManager>,
) -> Result<Box<masm::Module>, Report> {
use masm::{Instruction as Inst, Op};

Expand All @@ -231,12 +216,14 @@ impl MasmComponent {
// Invoke the program entrypoint
block.push(Op::Inst(Span::new(
span,
Inst::Trace(TraceEvent::FrameStart.as_u32().into()),
Inst::EmitImm(Event::FrameStart.as_event_id().as_felt().into()),
)));
invoked.push(masm::Invoke::new(masm::InvokeKind::Exec, entrypoint.clone()));
block.push(Op::Inst(Span::new(span, Inst::Exec(entrypoint.clone()))));
block
.push(Op::Inst(Span::new(span, Inst::Trace(TraceEvent::FrameEnd.as_u32().into()))));
block.push(Op::Inst(Span::new(
span,
Inst::EmitImm(Event::FrameEnd.as_event_id().as_felt().into()),
)));

// Truncate the stack to 16 elements on exit
let truncate_stack = {
Expand Down Expand Up @@ -302,11 +289,15 @@ impl MasmComponent {
loop_body.push(Op::Inst(Span::new(span, Inst::AdvPush)));
loop_body.push(Op::Inst(Span::new(span, Inst::AdvPush)));
// => [C, B, A, dest_ptr, inits'] on operand stack
loop_body
.push(Op::Inst(Span::new(span, Inst::Trace(TraceEvent::FrameStart.as_u32().into()))));
loop_body.push(Op::Inst(Span::new(
span,
Inst::EmitImm(Event::FrameStart.as_event_id().as_felt().into()),
)));
loop_body.push(Op::Inst(Span::new(span, Inst::Exec(pipe_words_to_memory))));
loop_body
.push(Op::Inst(Span::new(span, Inst::Trace(TraceEvent::FrameEnd.as_u32().into()))));
loop_body.push(Op::Inst(Span::new(
span,
Inst::EmitImm(Event::FrameEnd.as_event_id().as_felt().into()),
)));
// Drop C, B, A
loop_body.push(Op::Inst(Span::new(span, Inst::DropW)));
loop_body.push(Op::Inst(Span::new(span, Inst::DropW)));
Expand Down
Loading