@@ -628,35 +628,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
628
628
let frame = M :: init_frame_extra ( self , pre_frame) ?;
629
629
self . stack_mut ( ) . push ( frame) ;
630
630
631
- // don't allocate at all for trivial constants
632
- if body. local_decls . len ( ) > 1 {
633
- // Locals are initially uninitialized.
634
- let dummy = LocalState { value : LocalValue :: Uninitialized , layout : Cell :: new ( None ) } ;
635
- let mut locals = IndexVec :: from_elem ( dummy, & body. local_decls ) ;
636
- // Return place is handled specially by the `eval_place` functions, and the
637
- // entry in `locals` should never be used. Make it dead, to be sure.
638
- locals[ mir:: RETURN_PLACE ] . value = LocalValue :: Dead ;
639
- // Now mark those locals as dead that we do not want to initialize
640
- match self . tcx . def_kind ( instance. def_id ( ) ) {
641
- // statics and constants don't have `Storage*` statements, no need to look for them
642
- //
643
- // FIXME: The above is likely untrue. See
644
- // <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
645
- // okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
646
- Some ( DefKind :: Static | DefKind :: Const | DefKind :: AssocConst ) => { }
647
- _ => {
648
- // Mark locals that use `Storage*` annotations as dead on function entry.
649
- let always_live = AlwaysLiveLocals :: new ( self . body ( ) ) ;
650
- for local in locals. indices ( ) {
651
- if !always_live. contains ( local) {
652
- locals[ local] . value = LocalValue :: Dead ;
653
- }
631
+ // Locals are initially uninitialized.
632
+ let dummy = LocalState { value : LocalValue :: Uninitialized , layout : Cell :: new ( None ) } ;
633
+ let mut locals = IndexVec :: from_elem ( dummy, & body. local_decls ) ;
634
+
635
+ // Now mark those locals as dead that we do not want to initialize
636
+ match self . tcx . def_kind ( instance. def_id ( ) ) {
637
+ // statics and constants don't have `Storage*` statements, no need to look for them
638
+ //
639
+ // FIXME: The above is likely untrue. See
640
+ // <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
641
+ // okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
642
+ Some ( DefKind :: Static | DefKind :: Const | DefKind :: AssocConst ) => { }
643
+ _ => {
644
+ // Mark locals that use `Storage*` annotations as dead on function entry.
645
+ let always_live = AlwaysLiveLocals :: new ( self . body ( ) ) ;
646
+ for local in locals. indices ( ) {
647
+ if !always_live. contains ( local) {
648
+ locals[ local] . value = LocalValue :: Dead ;
654
649
}
655
650
}
656
651
}
657
- // done
658
- self . frame_mut ( ) . locals = locals;
659
652
}
653
+ // done
654
+ self . frame_mut ( ) . locals = locals;
660
655
661
656
M :: after_stack_push ( self ) ?;
662
657
info ! ( "ENTERING({}) {}" , self . frame_idx( ) , self . frame( ) . instance) ;
@@ -734,6 +729,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
734
729
let frame =
735
730
self . stack_mut ( ) . pop ( ) . expect ( "tried to pop a stack frame, but there were none" ) ;
736
731
732
+ if !unwinding {
733
+ // Copy the return value to the caller's stack frame.
734
+ if let Some ( return_place) = frame. return_place {
735
+ let op = self . access_local ( & frame, mir:: RETURN_PLACE , None ) ?;
736
+ self . copy_op_transmute ( op, return_place) ?;
737
+ self . dump_place ( * return_place) ;
738
+ } else {
739
+ throw_ub ! ( Unreachable ) ;
740
+ }
741
+ }
742
+
737
743
// Now where do we jump next?
738
744
739
745
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
@@ -759,7 +765,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
759
765
self . deallocate_local ( local. value ) ?;
760
766
}
761
767
762
- let return_place = frame. return_place ;
763
768
if M :: after_stack_pop ( self , frame, unwinding) ? == StackPopJump :: NoJump {
764
769
// The hook already did everything.
765
770
// We want to skip the `info!` below, hence early return.
@@ -772,25 +777,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
772
777
self . unwind_to_block ( unwind) ;
773
778
} else {
774
779
// Follow the normal return edge.
775
- // Validate the return value. Do this after deallocating so that we catch dangling
776
- // references.
777
- if let Some ( return_place) = return_place {
778
- if M :: enforce_validity ( self ) {
779
- // Data got changed, better make sure it matches the type!
780
- // It is still possible that the return place held invalid data while
781
- // the function is running, but that's okay because nobody could have
782
- // accessed that same data from the "outside" to observe any broken
783
- // invariant -- that is, unless a function somehow has a ptr to
784
- // its return place... but the way MIR is currently generated, the
785
- // return place is always a local and then this cannot happen.
786
- self . validate_operand ( self . place_to_op ( return_place) ?) ?;
787
- }
788
- } else {
789
- // Uh, that shouldn't happen... the function did not intend to return
790
- throw_ub ! ( Unreachable ) ;
791
- }
792
-
793
- // Jump to new block -- *after* validation so that the spans make more sense.
794
780
if let Some ( ret) = next_block {
795
781
self . return_to_block ( ret) ?;
796
782
}
0 commit comments