@@ -227,6 +227,14 @@ fn try_compile_ssa_trace(
227227 ) ;
228228 b. ins ( )
229229 . store ( MemFlags :: new ( ) , root_ip, vm_ptr, offsets. vm_ip ) ;
230+ emit_entry_stack_depth_guard (
231+ & mut b,
232+ vm_ptr,
233+ exit_block,
234+ pointer_type,
235+ offsets,
236+ ssa. entry_stack_depth ,
237+ ) ?;
230238
231239 let entry_ssa_block = ssa
232240 . blocks
@@ -241,7 +249,16 @@ fn try_compile_ssa_trace(
241249 pointer_type,
242250 layout,
243251 offsets,
244- entry_ssa_block. params . len ( ) ,
252+ ssa. entry_stack_depth ,
253+ entry_ssa_block
254+ . params
255+ . len ( )
256+ . checked_sub ( ssa. entry_stack_depth )
257+ . ok_or_else ( || {
258+ VmError :: JitNative (
259+ "SSA entry stack depth exceeds entry parameter count" . to_string ( ) ,
260+ )
261+ } ) ?,
245262 ) ?;
246263 init_owned_value_temps (
247264 & mut b,
@@ -743,12 +760,30 @@ fn build_entry_args(
743760 pointer_type : cranelift_codegen:: ir:: Type ,
744761 layout : crate :: vm:: native:: NativeStackLayout ,
745762 offsets : ResolvedOffsets ,
763+ stack_depth : usize ,
746764 local_count : usize ,
747765) -> VmResult < Vec < cranelift_codegen:: ir:: Value > > {
766+ let stack_ptr = b
767+ . ins ( )
768+ . load ( pointer_type, MemFlags :: new ( ) , vm_ptr, offsets. stack_ptr ) ;
748769 let locals_ptr = b
749770 . ins ( )
750771 . load ( pointer_type, MemFlags :: new ( ) , vm_ptr, offsets. locals_ptr ) ;
751- let mut args = Vec :: with_capacity ( local_count) ;
772+ let mut args = Vec :: with_capacity ( stack_depth + local_count) ;
773+ for stack_index in 0 ..stack_depth {
774+ let index = b. ins ( ) . iconst (
775+ pointer_type,
776+ i64:: try_from ( stack_index)
777+ . map_err ( |_| VmError :: JitNative ( "SSA stack index out of range" . to_string ( ) ) ) ?,
778+ ) ;
779+ args. push ( ssa_value_addr (
780+ b,
781+ pointer_type,
782+ stack_ptr,
783+ index,
784+ layout. value . size ,
785+ ) ) ;
786+ }
752787 for local in 0 ..local_count {
753788 let index = b. ins ( ) . iconst (
754789 pointer_type,
@@ -766,6 +801,35 @@ fn build_entry_args(
766801 Ok ( args)
767802}
768803
804+ fn emit_entry_stack_depth_guard (
805+ b : & mut FunctionBuilder ,
806+ vm_ptr : cranelift_codegen:: ir:: Value ,
807+ exit_block : Block ,
808+ pointer_type : cranelift_codegen:: ir:: Type ,
809+ offsets : ResolvedOffsets ,
810+ expected_depth : usize ,
811+ ) -> VmResult < ( ) > {
812+ let actual_depth = b
813+ . ins ( )
814+ . load ( pointer_type, MemFlags :: new ( ) , vm_ptr, offsets. stack_len ) ;
815+ let expected_depth = b. ins ( ) . iconst (
816+ pointer_type,
817+ i64:: try_from ( expected_depth)
818+ . map_err ( |_| VmError :: JitNative ( "SSA entry stack depth out of range" . to_string ( ) ) ) ?,
819+ ) ;
820+ let matches = b. ins ( ) . icmp ( IntCC :: Equal , actual_depth, expected_depth) ;
821+ let matched = b. create_block ( ) ;
822+ let mismatch = b. create_block ( ) ;
823+ b. ins ( ) . brif ( matches, matched, & [ ] , mismatch, & [ ] ) ;
824+
825+ b. switch_to_block ( mismatch) ;
826+ let status = b. ins ( ) . iconst ( types:: I32 , STATUS_CONTINUE as i64 ) ;
827+ jump_with_status ( b, exit_block, status) ;
828+
829+ b. switch_to_block ( matched) ;
830+ Ok ( ( ) )
831+ }
832+
769833fn ssa_block_args ( values : impl IntoIterator < Item = cranelift_codegen:: ir:: Value > ) -> Vec < BlockArg > {
770834 values. into_iter ( ) . map ( BlockArg :: Value ) . collect ( )
771835}
@@ -2989,6 +3053,8 @@ fn ssa_emit_trace_exit_status(
29893053
29903054#[ derive( Clone , Copy ) ]
29913055struct ResolvedOffsets {
3056+ stack_ptr : i32 ,
3057+ stack_len : i32 ,
29923058 locals_ptr : i32 ,
29933059 vm_ip : i32 ,
29943060 fuel_remaining : i32 ,
@@ -3186,13 +3252,25 @@ fn emit_epoch_tick_inline_core(
31863252}
31873253
31883254fn resolve_offsets ( layout : NativeStackLayout ) -> VmResult < ResolvedOffsets > {
3255+ let stack_ptr = checked_add_i32 (
3256+ layout. vm_stack_offset ,
3257+ layout. stack_vec . ptr_offset ,
3258+ "stack ptr offset overflow" ,
3259+ ) ?;
3260+ let stack_len = checked_add_i32 (
3261+ layout. vm_stack_offset ,
3262+ layout. stack_vec . len_offset ,
3263+ "stack len offset overflow" ,
3264+ ) ?;
31893265 let locals_ptr = checked_add_i32 (
31903266 layout. vm_locals_offset ,
31913267 layout. stack_vec . ptr_offset ,
31923268 "locals ptr offset overflow" ,
31933269 ) ?;
31943270
31953271 Ok ( ResolvedOffsets {
3272+ stack_ptr,
3273+ stack_len,
31963274 locals_ptr,
31973275 vm_ip : layout. vm_ip_offset ,
31983276 fuel_remaining : layout. vm_fuel_remaining_offset ,
0 commit comments