@@ -379,7 +379,8 @@ pub struct Evaluator<'tcx> {
379379
380380 /// Whether or not we are currently unwinding from
381381 /// a panic
382- pub ( crate ) unwinding : bool
382+ pub ( crate ) unwinding : bool ,
383+ pub ( crate ) box_me_up_tmp_ptr : Option < MPlaceTy < ' tcx , Tag > >
383384}
384385
385386pub struct CachedTypes < ' tcx > {
@@ -399,7 +400,8 @@ impl<'tcx> Evaluator<'tcx> {
399400 validate,
400401 rng : seed. map ( |s| StdRng :: seed_from_u64 ( s) ) ,
401402 cached_data : None ,
402- unwinding : false
403+ unwinding : false ,
404+ box_me_up_tmp_ptr : None
403405 }
404406 }
405407}
@@ -426,7 +428,8 @@ impl<'a, 'mir, 'tcx> MiriEvalContextExt<'a, 'mir, 'tcx> for MiriEvalContext<'a,
426428
427429pub struct FrameData < ' tcx > {
428430 pub call_id : stacked_borrows:: CallId ,
429- pub catch_panic : Option < UnwindData < ' tcx > >
431+ pub catch_panic : Option < UnwindData < ' tcx > > ,
432+ pub is_box_me_frame : bool
430433}
431434
432435/// Hold all of the relevant data for a call to
@@ -439,7 +442,7 @@ pub struct UnwindData<'tcx> {
439442 pub data_ptr : MPlaceTy < ' tcx , Tag > ,
440443 pub vtable_ptr : MPlaceTy < ' tcx , Tag > ,
441444 pub dest : PlaceTy < ' tcx , Tag > ,
442- pub ret : mir:: BasicBlock
445+ pub ret : mir:: BasicBlock ,
443446}
444447
445448impl < ' a , ' mir , ' tcx > Machine < ' a , ' mir , ' tcx > for Evaluator < ' tcx > {
@@ -467,8 +470,9 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
467470 args : & [ OpTy < ' tcx , Tag > ] ,
468471 dest : Option < PlaceTy < ' tcx , Tag > > ,
469472 ret : Option < mir:: BasicBlock > ,
473+ unwind : Option < mir:: BasicBlock >
470474 ) -> EvalResult < ' tcx , Option < & ' mir mir:: Mir < ' tcx > > > {
471- ecx. find_fn ( instance, args, dest, ret)
475+ ecx. find_fn ( instance, args, dest, ret, unwind )
472476 }
473477
474478 #[ inline( always) ]
@@ -633,7 +637,8 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
633637 ) -> EvalResult < ' tcx , FrameData < ' tcx > > {
634638 Ok ( FrameData {
635639 call_id : ecx. memory ( ) . extra . borrow_mut ( ) . new_call ( ) ,
636- catch_panic : None
640+ catch_panic : None ,
641+ is_box_me_frame : false
637642 } )
638643 }
639644
@@ -642,6 +647,56 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
642647 ecx : & mut InterpretCx < ' a , ' mir , ' tcx , Self > ,
643648 extra : FrameData ,
644649 ) -> EvalResult < ' tcx , StackPopInfo > {
650+ if extra. is_box_me_frame {
651+ trace ! ( "unwinding: found box_me_frame" ) ;
652+ ecx. machine . unwinding = true ;
653+ }
654+ if ecx. machine . unwinding {
655+ trace ! ( "Popping during unwind!" ) ;
656+ if let Some ( unwind_data) = ecx. frame_mut ( ) . extra . catch_panic . take ( ) {
657+ // We've just popped the frame that was immediately above
658+ // our target frame on the stack.
659+ //
660+ trace ! ( "unwinding: found target frame: {:?}" , ecx. frame( ) . span) ;
661+
662+ // 'box_me_up' has finished. 'temp_ptr' now holds
663+ // a '*mut (dyn Any + Send)'
664+ // We want to split this into its consituient parts -
665+ // the data and vtable pointers - and store them back
666+ // into the panic handler frame
667+ let tmp_ptr = ecx. machine . box_me_up_tmp_ptr . take ( ) . unwrap ( ) ;
668+ let real_ret = ecx. read_immediate ( tmp_ptr. into ( ) ) ?;
669+ let payload_data_ptr = real_ret. to_scalar_ptr ( ) ?;
670+ let payload_vtable_ptr = real_ret. to_meta ( ) ?. expect ( "Expected fat pointer" ) ;
671+
672+
673+ let data_ptr = unwind_data. data_ptr . clone ( ) ;
674+ let vtable_ptr = unwind_data. vtable_ptr . clone ( ) ;
675+ let dest = unwind_data. dest . clone ( ) ;
676+ let ret = unwind_data. ret . clone ( ) ;
677+ drop ( unwind_data) ;
678+
679+
680+ // Here, we write directly into the frame of the function
681+ // that called '__rust_maybe_catch_panic'.
682+ // (NOT the function that called '__rust_start_panic')
683+
684+ ecx. write_scalar ( payload_data_ptr, data_ptr. into ( ) ) ?;
685+ ecx. write_scalar ( payload_vtable_ptr, vtable_ptr. into ( ) ) ?;
686+
687+ // We 'return' the value 1 from __rust_maybe_catch_panic,
688+ // since there was a panic
689+ ecx. write_scalar ( Scalar :: from_int ( 1 , dest. layout . size ) , dest) ?;
690+ ecx. machine . unwinding = false ;
691+
692+ ecx. memory_mut ( ) . deallocate ( tmp_ptr. to_ptr ( ) ?, None , MiriMemoryKind :: UnwindHelper . into ( ) ) ?;
693+
694+ // We're done - continue execution in the frame of the function
695+ // that called '__rust_maybe_catch_panic,'
696+ //this.goto_block(Some(ret))?;
697+
698+ }
699+ }
645700 ecx. memory ( ) . extra . borrow_mut ( ) . end_call ( extra. call_id ) ;
646701 Ok ( StackPopInfo { unwinding : ecx. machine . unwinding } )
647702 }
0 commit comments