@@ -16,6 +16,9 @@ use super::*;
16
16
17
17
const MEMORY_SIZE_BYTES : u32 = 1048576 * 2 ; // Twice the size of the default Rust shadow stack size
18
18
const MEMORY_SIZE_VM_WORDS : u32 = MEMORY_SIZE_BYTES / 16 ;
19
+ /// In miden-sdk-alloc we require all allocations to be minimally word-aligned, i.e. 32 byte
20
+ /// alignment
21
+ const MIN_ALIGN : u32 = 32 ;
19
22
20
23
#[ cfg( test) ]
21
24
#[ allow( unused_macros) ]
@@ -638,6 +641,87 @@ fn codegen_mem_store_dw_load_dw() {
638
641
. unwrap ( ) ;
639
642
}
640
643
644
+ #[ test]
645
+ fn codegen_mem_store_felt_load_felt ( ) {
646
+ let context = TestContext :: default ( ) ;
647
+ let mut builder = ProgramBuilder :: new ( & context. session . diagnostics ) ;
648
+ let mut mb = builder. module ( "test" ) ;
649
+ let id = {
650
+ let mut fb = mb
651
+ . function (
652
+ "store_load_felt" ,
653
+ Signature :: new (
654
+ [ AbiParam :: new ( Type :: U32 ) , AbiParam :: new ( Type :: Felt ) ] ,
655
+ [ AbiParam :: new ( Type :: Felt ) ] ,
656
+ ) ,
657
+ )
658
+ . expect ( "unexpected symbol conflict" ) ;
659
+ let entry = fb. current_block ( ) ;
660
+ let ( ptr_u32, value) = {
661
+ let args = fb. block_params ( entry) ;
662
+ ( args[ 0 ] , args[ 1 ] )
663
+ } ;
664
+ let ptr = fb. ins ( ) . inttoptr ( ptr_u32, Type :: Ptr ( Type :: Felt . into ( ) ) , SourceSpan :: UNKNOWN ) ;
665
+ fb. ins ( ) . store ( ptr, value, SourceSpan :: UNKNOWN ) ;
666
+ let loaded_value = fb. ins ( ) . load ( ptr, SourceSpan :: UNKNOWN ) ;
667
+ fb. ins ( ) . ret ( Some ( loaded_value) , SourceSpan :: UNKNOWN ) ;
668
+ fb. build ( ) . expect ( "unexpected error building function" )
669
+ } ;
670
+
671
+ mb. build ( ) . expect ( "unexpected error constructing test module" ) ;
672
+
673
+ let program = builder. with_entrypoint ( id) . link ( ) . expect ( "failed to link program" ) ;
674
+
675
+ let ir_module = program
676
+ . modules ( )
677
+ . iter ( )
678
+ . take ( 1 )
679
+ . collect :: < Vec < & midenc_hir:: Module > > ( )
680
+ . first ( )
681
+ . expect ( "no module in IR program" )
682
+ . to_string ( ) ;
683
+
684
+ eprintln ! ( "{}" , ir_module. as_str( ) ) ;
685
+
686
+ let mut compiler = MasmCompiler :: new ( & context. session ) ;
687
+ let program = compiler
688
+ . compile ( program)
689
+ . expect ( "compilation failed" )
690
+ . unwrap_executable ( )
691
+ . freeze ( ) ;
692
+
693
+ eprintln ! ( "{}" , program) ;
694
+
695
+ fn roundtrip ( program : Arc < Program > , ptr : u32 , value : Felt ) -> Felt {
696
+ eprintln ! ( "---------------------------------" ) ;
697
+ eprintln ! ( "testing store_felt/load_felt ptr: {ptr}, value: {value}" ) ;
698
+ eprintln ! ( "---------------------------------" ) ;
699
+ let mut harness = TestByEmulationHarness :: with_emulator_config (
700
+ MEMORY_SIZE_VM_WORDS as usize ,
701
+ Emulator :: DEFAULT_HEAP_START as usize ,
702
+ Emulator :: DEFAULT_LOCALS_START as usize ,
703
+ true ,
704
+ ) ;
705
+ let mut stack = harness
706
+ . execute_program ( program. clone ( ) , & [ Felt :: new ( ptr as u64 ) , value] )
707
+ . expect ( "execution failed" ) ;
708
+ stack. pop ( ) . unwrap ( )
709
+ }
710
+
711
+ TestRunner :: new ( Config :: with_cases ( 1024 ) )
712
+ . run (
713
+ & ( 0u32 ..( MEMORY_SIZE_BYTES / MIN_ALIGN - 1 ) , ( 0u64 ..u64:: MAX ) . prop_map ( Felt :: new) ) ,
714
+ move |( word_ptr, value) | {
715
+ // a felt memory pointer must be naturally aligned, i.e. a multiple of MIN_ALIGN
716
+ let ptr = word_ptr * MIN_ALIGN ;
717
+ let out = roundtrip ( program. clone ( ) , ptr, value) ;
718
+ prop_assert_eq ! ( out, value) ;
719
+ Ok ( ( ) )
720
+ } ,
721
+ )
722
+ . unwrap ( ) ;
723
+ }
724
+
641
725
#[ allow( unused) ]
642
726
macro_rules! proptest_unary_numeric_op {
643
727
( $ty_name: ident :: $op: ident, $ty: ty => $ret: ty, $rust_op: ident) => {
0 commit comments