@@ -379,7 +379,8 @@ pub struct Evaluator<'tcx> {
379
379
380
380
/// Whether or not we are currently unwinding from
381
381
/// a panic
382
- pub ( crate ) unwinding : bool
382
+ pub ( crate ) unwinding : bool ,
383
+ pub ( crate ) box_me_up_tmp_ptr : Option < MPlaceTy < ' tcx , Tag > >
383
384
}
384
385
385
386
pub struct CachedTypes < ' tcx > {
@@ -399,7 +400,8 @@ impl<'tcx> Evaluator<'tcx> {
399
400
validate,
400
401
rng : seed. map ( |s| StdRng :: seed_from_u64 ( s) ) ,
401
402
cached_data : None ,
402
- unwinding : false
403
+ unwinding : false ,
404
+ box_me_up_tmp_ptr : None
403
405
}
404
406
}
405
407
}
@@ -426,7 +428,8 @@ impl<'a, 'mir, 'tcx> MiriEvalContextExt<'a, 'mir, 'tcx> for MiriEvalContext<'a,
426
428
427
429
pub struct FrameData < ' tcx > {
428
430
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
430
433
}
431
434
432
435
/// Hold all of the relevant data for a call to
@@ -439,7 +442,7 @@ pub struct UnwindData<'tcx> {
439
442
pub data_ptr : MPlaceTy < ' tcx , Tag > ,
440
443
pub vtable_ptr : MPlaceTy < ' tcx , Tag > ,
441
444
pub dest : PlaceTy < ' tcx , Tag > ,
442
- pub ret : mir:: BasicBlock
445
+ pub ret : mir:: BasicBlock ,
443
446
}
444
447
445
448
impl < ' 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> {
467
470
args : & [ OpTy < ' tcx , Tag > ] ,
468
471
dest : Option < PlaceTy < ' tcx , Tag > > ,
469
472
ret : Option < mir:: BasicBlock > ,
473
+ unwind : Option < mir:: BasicBlock >
470
474
) -> EvalResult < ' tcx , Option < & ' mir mir:: Mir < ' tcx > > > {
471
- ecx. find_fn ( instance, args, dest, ret)
475
+ ecx. find_fn ( instance, args, dest, ret, unwind )
472
476
}
473
477
474
478
#[ inline( always) ]
@@ -633,7 +637,8 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
633
637
) -> EvalResult < ' tcx , FrameData < ' tcx > > {
634
638
Ok ( FrameData {
635
639
call_id : ecx. memory ( ) . extra . borrow_mut ( ) . new_call ( ) ,
636
- catch_panic : None
640
+ catch_panic : None ,
641
+ is_box_me_frame : false
637
642
} )
638
643
}
639
644
@@ -642,6 +647,56 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
642
647
ecx : & mut InterpretCx < ' a , ' mir , ' tcx , Self > ,
643
648
extra : FrameData ,
644
649
) -> 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
+ }
645
700
ecx. memory ( ) . extra . borrow_mut ( ) . end_call ( extra. call_id ) ;
646
701
Ok ( StackPopInfo { unwinding : ecx. machine . unwinding } )
647
702
}
0 commit comments