Skip to content

Commit 81e56a4

Browse files
committed
feature: convert add felt intrinsic to use stub library instead of WIT interface
1 parent 6b4c9fd commit 81e56a4

24 files changed

+1074
-816
lines changed

frontend/wasm/src/module/linker_stubs.rs

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use midenc_hir::{
1616
use wasmparser::{FunctionBody, Operator};
1717

1818
use crate::{
19-
intrinsics::Intrinsic,
19+
intrinsics::{convert_intrinsics_call, Intrinsic},
2020
miden_abi::{
2121
is_miden_abi_module, miden_abi_function_type,
22-
transform::{no_transform, transform_miden_abi_call},
22+
transform::transform_miden_abi_call,
2323
},
2424
module::{
2525
function_builder_ext::{FunctionBuilderContext, FunctionBuilderExt, SSABuilderListener},
@@ -81,16 +81,19 @@ pub fn maybe_lower_linker_stub(
8181
return Ok(false);
8282
}
8383

84-
// MASM callee function type
85-
let import_sig = if is_intrinsic {
86-
// For intrinsics, use the same signature as the stub function
87-
function_ref.borrow().signature().clone()
88-
} else {
89-
let import_ft: FunctionType = miden_abi_function_type(&import_path);
90-
Signature::new(
91-
import_ft.params.into_iter().map(AbiParam::new),
92-
import_ft.results.into_iter().map(AbiParam::new),
93-
)
84+
// Classify intrinsics and obtain signature when needed
85+
let (import_sig, intrinsic): (Signature, Option<Intrinsic>) = match Intrinsic::try_from(&import_path) {
86+
Ok(intr) => (function_ref.borrow().signature().clone(), Some(intr)),
87+
Err(_) => {
88+
let import_ft: FunctionType = miden_abi_function_type(&import_path);
89+
(
90+
Signature::new(
91+
import_ft.params.into_iter().map(AbiParam::new),
92+
import_ft.results.into_iter().map(AbiParam::new),
93+
),
94+
None,
95+
)
96+
}
9497
};
9598

9699
// Build the function body for the stub and replace it with an exec to MASM
@@ -112,18 +115,40 @@ pub fn maybe_lower_linker_stub(
112115
.collect();
113116

114117
// Declare MASM import callee in world and exec via TransformStrategy
115-
let import_module_ref = module_state
116-
.world_builder
117-
.declare_module_tree(&import_path.without_leaf())
118-
.wrap_err("failed to create module for MASM imports")?;
119-
let mut import_module_builder = ModuleBuilder::new(import_module_ref);
120-
let import_func_ref = import_module_builder
121-
.define_function(import_path.name().into(), import_sig)
122-
.expect("failed to create MASM import function ref");
123-
124-
let results = if is_intrinsic {
125-
no_transform(import_func_ref, &args, &mut fb)
118+
let results: Vec<ValueRef> = if let Some(intr) = intrinsic {
119+
// Decide whether the intrinsic is implemented as a function or an operation
120+
let conv = intr
121+
.conversion_result()
122+
.expect("unknown intrinsic");
123+
if conv.is_function() {
124+
// Declare callee and call via convert_intrinsics_call with function_ref
125+
let import_module_ref = module_state
126+
.world_builder
127+
.declare_module_tree(&import_path.without_leaf())
128+
.wrap_err("failed to create module for intrinsics imports")?;
129+
let mut import_module_builder = ModuleBuilder::new(import_module_ref);
130+
let intrinsic_func_ref = import_module_builder
131+
.define_function(import_path.name().into(), import_sig.clone())
132+
.expect("failed to create intrinsic function ref");
133+
convert_intrinsics_call(intr, Some(intrinsic_func_ref), &args, &mut fb, span)
134+
.expect("convert_intrinsics_call failed")
135+
.to_vec()
136+
} else {
137+
// Inline conversion of intrinsic operation
138+
convert_intrinsics_call(intr, None, &args, &mut fb, span)
139+
.expect("convert_intrinsics_call failed")
140+
.to_vec()
141+
}
126142
} else {
143+
// Miden ABI path: exec import with TransformStrategy
144+
let import_module_ref = module_state
145+
.world_builder
146+
.declare_module_tree(&import_path.without_leaf())
147+
.wrap_err("failed to create module for MASM imports")?;
148+
let mut import_module_builder = ModuleBuilder::new(import_module_ref);
149+
let import_func_ref = import_module_builder
150+
.define_function(import_path.name().into(), import_sig)
151+
.expect("failed to create MASM import function ref");
127152
transform_miden_abi_call(import_func_ref, &import_path, &args, &mut fb)
128153
};
129154

sdk/stdlib-sys/src/intrinsics/felt.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ extern "C" {
1010

1111
#[link_name = "as-u64"]
1212
fn extern_as_u64(felt: Felt) -> u64;
13-
14-
#[link_name = "add"]
15-
fn extern_add(a: Felt, b: Felt) -> Felt;
13+
// add moved to stub; see separate extern block below
1614

1715
#[link_name = "sub"]
1816
fn extern_sub(a: Felt, b: Felt) -> Felt;
@@ -63,6 +61,12 @@ extern "C" {
6361
fn extern_assert_eq(a: Felt, b: Felt);
6462
}
6563

64+
// Resolve add via linker stub rather than WIT import
65+
extern "C" {
66+
#[link_name = "intrinsics::felt::add"]
67+
fn extern_add(a: Felt, b: Felt) -> Felt;
68+
}
69+
6670
/// Creates a `Felt` from an integer constant checking that it is within the
6771
/// valid range at compile time.
6872
#[macro_export]

sdk/stdlib-sys/wit/miden-core-intrinsics.wit

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ interface intrinsics-felt {
1818
as-u64: func(a: f32) -> u64;
1919

2020
// Arithmetic operations
21-
add: func(a: f32, b: f32) -> f32;
21+
// add moved to linker stub
22+
// add: func(a: f32, b: f32) -> f32;
2223
sub: func(a: f32, b: f32) -> f32;
2324
mul: func(a: f32, b: f32) -> f32;
2425
div: func(a: f32, b: f32) -> f32;

tests/integration/expected/add_felt.hir

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ builtin.component root_ns:[email protected] {
22
builtin.module public @add_felt {
33
public builtin.function @entrypoint(v0: felt, v1: felt) -> felt {
44
^block4(v0: felt, v1: felt):
5-
v3 = arith.add v0, v1 : felt #[overflow = unchecked];
5+
v3 = hir.exec @root_ns:[email protected]/add_felt/intrinsics::felt::add(v0, v1) : felt
66
builtin.ret v3;
77
};
88

9+
private builtin.function @intrinsics::felt::add(v4: felt, v5: felt) -> felt {
10+
^block6(v4: felt, v5: felt):
11+
v6 = arith.add v4, v5 : felt #[overflow = unchecked];
12+
builtin.ret v6;
13+
};
14+
915
builtin.global_variable private @#__stack_pointer : i32 {
1016
builtin.ret_imm 1048576;
1117
};

tests/integration/expected/add_felt.masm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ end
1313
# mod root_ns:[email protected]::add_felt
1414

1515
export.entrypoint
16+
trace.240
17+
nop
18+
exec.::root_ns:[email protected]::add_felt::intrinsics::felt::add
19+
trace.252
20+
nop
21+
end
22+
23+
proc.intrinsics::felt::add
1624
add
1725
end
1826

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
(module $add_felt.wasm
22
(type (;0;) (func (param f32 f32) (result f32)))
3-
(import "miden:core-intrinsics/[email protected]" "add" (func $miden_stdlib_sys::intrinsics::felt::extern_add (;0;) (type 0)))
43
(table (;0;) 1 1 funcref)
54
(memory (;0;) 16)
65
(global $__stack_pointer (;0;) (mut i32) i32.const 1048576)
76
(export "memory" (memory 0))
87
(export "entrypoint" (func $entrypoint))
9-
(func $entrypoint (;1;) (type 0) (param f32 f32) (result f32)
8+
(func $entrypoint (;0;) (type 0) (param f32 f32) (result f32)
109
local.get 0
1110
local.get 1
12-
call $miden_stdlib_sys::intrinsics::felt::extern_add
11+
call $intrinsics::felt::add
12+
)
13+
(func $intrinsics::felt::add (;1;) (type 0) (param f32 f32) (result f32)
14+
unreachable
1315
)
1416
)

0 commit comments

Comments
 (0)