@@ -32,7 +32,6 @@ struct CallSite<'tcx> {
3232 callee : Instance < ' tcx > ,
3333 fn_sig : ty:: PolyFnSig < ' tcx > ,
3434 block : BasicBlock ,
35- target : Option < BasicBlock > ,
3635 source_info : SourceInfo ,
3736}
3837
@@ -367,7 +366,7 @@ impl<'tcx> Inliner<'tcx> {
367366 ) -> Option < CallSite < ' tcx > > {
368367 // Only consider direct calls to functions
369368 let terminator = bb_data. terminator ( ) ;
370- if let TerminatorKind :: Call { ref func, target , fn_span, .. } = terminator. kind {
369+ if let TerminatorKind :: Call { ref func, fn_span, .. } = terminator. kind {
371370 let func_ty = func. ty ( caller_body, self . tcx ) ;
372371 if let ty:: FnDef ( def_id, args) = * func_ty. kind ( ) {
373372 // To resolve an instance its args have to be fully normalized.
@@ -386,7 +385,7 @@ impl<'tcx> Inliner<'tcx> {
386385 let fn_sig = self . tcx . fn_sig ( def_id) . instantiate ( self . tcx , args) ;
387386 let source_info = SourceInfo { span : fn_span, ..terminator. source_info } ;
388387
389- return Some ( CallSite { callee, fn_sig, block : bb, target , source_info } ) ;
388+ return Some ( CallSite { callee, fn_sig, block : bb, source_info } ) ;
390389 }
391390 }
392391
@@ -541,10 +540,23 @@ impl<'tcx> Inliner<'tcx> {
541540 mut callee_body : Body < ' tcx > ,
542541 ) {
543542 let terminator = caller_body[ callsite. block ] . terminator . take ( ) . unwrap ( ) ;
544- let TerminatorKind :: Call { args, destination, unwind, .. } = terminator. kind else {
543+ let TerminatorKind :: Call { args, destination, unwind, target , .. } = terminator. kind else {
545544 bug ! ( "unexpected terminator kind {:?}" , terminator. kind) ;
546545 } ;
547546
547+ let return_block = if let Some ( block) = target {
548+ // Prepare a new block for code that should execute when call returns. We don't use
549+ // target block directly since it might have other predecessors.
550+ let mut data = BasicBlockData :: new ( Some ( Terminator {
551+ source_info : terminator. source_info ,
552+ kind : TerminatorKind :: Goto { target : block } ,
553+ } ) ) ;
554+ data. is_cleanup = caller_body[ block] . is_cleanup ;
555+ Some ( caller_body. basic_blocks_mut ( ) . push ( data) )
556+ } else {
557+ None
558+ } ;
559+
548560 // If the call is something like `a[*i] = f(i)`, where
549561 // `i : &mut usize`, then just duplicating the `a[*i]`
550562 // Place could result in two different locations if `f`
@@ -569,7 +581,8 @@ impl<'tcx> Inliner<'tcx> {
569581 destination,
570582 ) ;
571583 let dest_ty = dest. ty ( caller_body, self . tcx ) ;
572- let temp = Place :: from ( self . new_call_temp ( caller_body, & callsite, dest_ty) ) ;
584+ let temp =
585+ Place :: from ( self . new_call_temp ( caller_body, & callsite, dest_ty, return_block) ) ;
573586 caller_body[ callsite. block ] . statements . push ( Statement {
574587 source_info : callsite. source_info ,
575588 kind : StatementKind :: Assign ( Box :: new ( ( temp, dest) ) ) ,
@@ -590,12 +603,14 @@ impl<'tcx> Inliner<'tcx> {
590603 caller_body,
591604 & callsite,
592605 destination. ty ( caller_body, self . tcx ) . ty ,
606+ return_block,
593607 ) ,
594608 )
595609 } ;
596610
597611 // Copy the arguments if needed.
598- let args: Vec < _ > = self . make_call_args ( args, & callsite, caller_body, & callee_body) ;
612+ let args: Vec < _ > =
613+ self . make_call_args ( args, & callsite, caller_body, & callee_body, return_block) ;
599614
600615 let mut integrator = Integrator {
601616 args : & args,
@@ -607,6 +622,7 @@ impl<'tcx> Inliner<'tcx> {
607622 callsite,
608623 cleanup_block : unwind,
609624 in_cleanup_block : false ,
625+ return_block,
610626 tcx : self . tcx ,
611627 always_live_locals : BitSet :: new_filled ( callee_body. local_decls . len ( ) ) ,
612628 } ;
@@ -626,7 +642,7 @@ impl<'tcx> Inliner<'tcx> {
626642 } ) ;
627643 }
628644 }
629- if let Some ( block) = callsite . target {
645+ if let Some ( block) = return_block {
630646 // To avoid repeated O(n) insert, push any new statements to the end and rotate
631647 // the slice once.
632648 let mut n = 0 ;
@@ -684,6 +700,7 @@ impl<'tcx> Inliner<'tcx> {
684700 callsite : & CallSite < ' tcx > ,
685701 caller_body : & mut Body < ' tcx > ,
686702 callee_body : & Body < ' tcx > ,
703+ return_block : Option < BasicBlock > ,
687704 ) -> Vec < Local > {
688705 let tcx = self . tcx ;
689706
@@ -712,8 +729,18 @@ impl<'tcx> Inliner<'tcx> {
712729 // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
713730 if callsite. fn_sig . abi ( ) == Abi :: RustCall && callee_body. spread_arg . is_none ( ) {
714731 let mut args = args. into_iter ( ) ;
715- let self_ = self . create_temp_if_necessary ( args. next ( ) . unwrap ( ) , callsite, caller_body) ;
716- let tuple = self . create_temp_if_necessary ( args. next ( ) . unwrap ( ) , callsite, caller_body) ;
732+ let self_ = self . create_temp_if_necessary (
733+ args. next ( ) . unwrap ( ) ,
734+ callsite,
735+ caller_body,
736+ return_block,
737+ ) ;
738+ let tuple = self . create_temp_if_necessary (
739+ args. next ( ) . unwrap ( ) ,
740+ callsite,
741+ caller_body,
742+ return_block,
743+ ) ;
717744 assert ! ( args. next( ) . is_none( ) ) ;
718745
719746 let tuple = Place :: from ( tuple) ;
@@ -730,13 +757,13 @@ impl<'tcx> Inliner<'tcx> {
730757 let tuple_field = Operand :: Move ( tcx. mk_place_field ( tuple, FieldIdx :: new ( i) , ty) ) ;
731758
732759 // Spill to a local to make e.g., `tmp0`.
733- self . create_temp_if_necessary ( tuple_field, callsite, caller_body)
760+ self . create_temp_if_necessary ( tuple_field, callsite, caller_body, return_block )
734761 } ) ;
735762
736763 closure_ref_arg. chain ( tuple_tmp_args) . collect ( )
737764 } else {
738765 args. into_iter ( )
739- . map ( |a| self . create_temp_if_necessary ( a, callsite, caller_body) )
766+ . map ( |a| self . create_temp_if_necessary ( a, callsite, caller_body, return_block ) )
740767 . collect ( )
741768 }
742769 }
@@ -748,6 +775,7 @@ impl<'tcx> Inliner<'tcx> {
748775 arg : Operand < ' tcx > ,
749776 callsite : & CallSite < ' tcx > ,
750777 caller_body : & mut Body < ' tcx > ,
778+ return_block : Option < BasicBlock > ,
751779 ) -> Local {
752780 // Reuse the operand if it is a moved temporary.
753781 if let Operand :: Move ( place) = & arg
@@ -760,7 +788,7 @@ impl<'tcx> Inliner<'tcx> {
760788 // Otherwise, create a temporary for the argument.
761789 trace ! ( "creating temp for argument {:?}" , arg) ;
762790 let arg_ty = arg. ty ( caller_body, self . tcx ) ;
763- let local = self . new_call_temp ( caller_body, callsite, arg_ty) ;
791+ let local = self . new_call_temp ( caller_body, callsite, arg_ty, return_block ) ;
764792 caller_body[ callsite. block ] . statements . push ( Statement {
765793 source_info : callsite. source_info ,
766794 kind : StatementKind :: Assign ( Box :: new ( ( Place :: from ( local) , Rvalue :: Use ( arg) ) ) ) ,
@@ -774,6 +802,7 @@ impl<'tcx> Inliner<'tcx> {
774802 caller_body : & mut Body < ' tcx > ,
775803 callsite : & CallSite < ' tcx > ,
776804 ty : Ty < ' tcx > ,
805+ return_block : Option < BasicBlock > ,
777806 ) -> Local {
778807 let local = caller_body. local_decls . push ( LocalDecl :: new ( ty, callsite. source_info . span ) ) ;
779808
@@ -782,7 +811,7 @@ impl<'tcx> Inliner<'tcx> {
782811 kind : StatementKind :: StorageLive ( local) ,
783812 } ) ;
784813
785- if let Some ( block) = callsite . target {
814+ if let Some ( block) = return_block {
786815 caller_body[ block] . statements . insert (
787816 0 ,
788817 Statement {
@@ -813,6 +842,7 @@ struct Integrator<'a, 'tcx> {
813842 callsite : & ' a CallSite < ' tcx > ,
814843 cleanup_block : UnwindAction ,
815844 in_cleanup_block : bool ,
845+ return_block : Option < BasicBlock > ,
816846 tcx : TyCtxt < ' tcx > ,
817847 always_live_locals : BitSet < Local > ,
818848}
@@ -956,7 +986,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
956986 * unwind = self . map_unwind ( * unwind) ;
957987 }
958988 TerminatorKind :: Return => {
959- terminator. kind = if let Some ( tgt) = self . callsite . target {
989+ terminator. kind = if let Some ( tgt) = self . return_block {
960990 TerminatorKind :: Goto { target : tgt }
961991 } else {
962992 TerminatorKind :: Unreachable
0 commit comments