@@ -6,6 +6,7 @@ use midenc_hir::{
66 AbiParam , CallConv , Felt , FieldElement , FunctionIdent , Immediate , InstBuilder , Linkage ,
77 OperandStack , ProgramBuilder , Signature , SourceSpan , Stack , Type ,
88} ;
9+ use prop:: test_runner:: { Config , TestRunner } ;
910use proptest:: prelude:: * ;
1011use smallvec:: { smallvec, SmallVec } ;
1112
@@ -208,6 +209,10 @@ impl TestByEmulationHarness {
208209 pub fn step_over ( & mut self ) -> Result < EmulatorEvent , EmulationError > {
209210 self . emulator . step_over ( )
210211 }
212+
213+ fn reset ( & mut self ) {
214+ self . emulator . reset ( ) ;
215+ }
211216}
212217
213218#[ test]
@@ -453,6 +458,69 @@ fn i32_checked_neg() {
453458 harness. invoke ( neg, & [ min] ) . expect ( "execution failed" ) ;
454459}
455460
461+ #[ test]
462+ fn codegen_mem_store_sw_load_sw ( ) {
463+ const MEMORY_SIZE_BYTES : u32 = 1048576 * 2 ; // Twice the size of the default Rust shadow stack size
464+ const MEMORY_SIZE_VM_WORDS : u32 = MEMORY_SIZE_BYTES / 16 ;
465+ let context = TestContext :: default ( ) ;
466+ let mut builder = ProgramBuilder :: new ( & context. session . diagnostics ) ;
467+ let mut mb = builder. module ( "test" ) ;
468+ let id = {
469+ let mut fb = mb
470+ . function (
471+ "store_load_sw" ,
472+ Signature :: new (
473+ [ AbiParam :: new ( Type :: U32 ) , AbiParam :: new ( Type :: U32 ) ] ,
474+ [ AbiParam :: new ( Type :: U32 ) ] ,
475+ ) ,
476+ )
477+ . expect ( "unexpected symbol conflict" ) ;
478+ let entry = fb. current_block ( ) ;
479+ let ( ptr_u32, value) = {
480+ let args = fb. block_params ( entry) ;
481+ ( args[ 0 ] , args[ 1 ] )
482+ } ;
483+ let ptr = fb. ins ( ) . inttoptr ( ptr_u32, Type :: Ptr ( Type :: U32 . into ( ) ) , SourceSpan :: UNKNOWN ) ;
484+ fb. ins ( ) . store ( ptr, value, SourceSpan :: UNKNOWN ) ;
485+ let loaded_value = fb. ins ( ) . load ( ptr, SourceSpan :: UNKNOWN ) ;
486+ fb. ins ( ) . ret ( Some ( loaded_value) , SourceSpan :: UNKNOWN ) ;
487+ fb. build ( ) . expect ( "unexpected error building function" )
488+ } ;
489+
490+ mb. build ( ) . expect ( "unexpected error constructing test module" ) ;
491+
492+ let program = builder. with_entrypoint ( id) . link ( ) . expect ( "failed to link program" ) ;
493+
494+ let mut compiler = MasmCompiler :: new ( & context. session ) ;
495+ let program = compiler. compile ( program) . expect ( "compilation failed" ) . freeze ( ) ;
496+
497+ // eprintln!("{}", program);
498+
499+ fn test ( program : Arc < Program > , ptr : u32 , value : u32 ) -> u32 {
500+ eprintln ! ( "---------------------------------" ) ;
501+ eprintln ! ( "testing store_sw/load_sw ptr: {ptr}, value: {value}" ) ;
502+ eprintln ! ( "---------------------------------" ) ;
503+ let mut harness = TestByEmulationHarness :: with_emulator_config (
504+ MEMORY_SIZE_VM_WORDS as usize ,
505+ Emulator :: DEFAULT_HEAP_START as usize ,
506+ Emulator :: DEFAULT_LOCALS_START as usize ,
507+ true ,
508+ ) ;
509+ let mut stack = harness
510+ . execute_program ( program. clone ( ) , & [ Felt :: new ( ptr as u64 ) , Felt :: new ( value as u64 ) ] )
511+ . expect ( "execution failed" ) ;
512+ stack. pop ( ) . unwrap ( ) . as_int ( ) as u32
513+ }
514+
515+ TestRunner :: new ( Config :: with_cases ( 1024 ) )
516+ . run ( & ( 0u32 ..MEMORY_SIZE_BYTES - 4 , any :: < u32 > ( ) ) , move |( ptr, value) | {
517+ let out = test ( program. clone ( ) , ptr, value) ;
518+ prop_assert_eq ! ( out, value) ;
519+ Ok ( ( ) )
520+ } )
521+ . unwrap ( ) ;
522+ }
523+
456524macro_rules! proptest_unary_numeric_op {
457525 ( $ty_name: ident :: $op: ident, $ty: ty => $ret: ty, $rust_op: ident) => {
458526 proptest_unary_numeric_op_impl!( $ty_name :: $op, $ty => $ret, $rust_op, 0 ..$ty_name:: MAX ) ;
0 commit comments