@@ -32,7 +32,6 @@ struct CallSite<'tcx> {
32
32
callee : Instance < ' tcx > ,
33
33
fn_sig : ty:: PolyFnSig < ' tcx > ,
34
34
block : BasicBlock ,
35
- target : Option < BasicBlock > ,
36
35
source_info : SourceInfo ,
37
36
}
38
37
@@ -367,7 +366,7 @@ impl<'tcx> Inliner<'tcx> {
367
366
) -> Option < CallSite < ' tcx > > {
368
367
// Only consider direct calls to functions
369
368
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 {
371
370
let func_ty = func. ty ( caller_body, self . tcx ) ;
372
371
if let ty:: FnDef ( def_id, args) = * func_ty. kind ( ) {
373
372
// To resolve an instance its args have to be fully normalized.
@@ -386,7 +385,7 @@ impl<'tcx> Inliner<'tcx> {
386
385
let fn_sig = self . tcx . fn_sig ( def_id) . instantiate ( self . tcx , args) ;
387
386
let source_info = SourceInfo { span : fn_span, ..terminator. source_info } ;
388
387
389
- return Some ( CallSite { callee, fn_sig, block : bb, target , source_info } ) ;
388
+ return Some ( CallSite { callee, fn_sig, block : bb, source_info } ) ;
390
389
}
391
390
}
392
391
@@ -541,10 +540,23 @@ impl<'tcx> Inliner<'tcx> {
541
540
mut callee_body : Body < ' tcx > ,
542
541
) {
543
542
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 {
545
544
bug ! ( "unexpected terminator kind {:?}" , terminator. kind) ;
546
545
} ;
547
546
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
+
548
560
// If the call is something like `a[*i] = f(i)`, where
549
561
// `i : &mut usize`, then just duplicating the `a[*i]`
550
562
// Place could result in two different locations if `f`
@@ -569,7 +581,8 @@ impl<'tcx> Inliner<'tcx> {
569
581
destination,
570
582
) ;
571
583
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) ) ;
573
586
caller_body[ callsite. block ] . statements . push ( Statement {
574
587
source_info : callsite. source_info ,
575
588
kind : StatementKind :: Assign ( Box :: new ( ( temp, dest) ) ) ,
@@ -590,12 +603,14 @@ impl<'tcx> Inliner<'tcx> {
590
603
caller_body,
591
604
& callsite,
592
605
destination. ty ( caller_body, self . tcx ) . ty ,
606
+ return_block,
593
607
) ,
594
608
)
595
609
} ;
596
610
597
611
// 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) ;
599
614
600
615
let mut integrator = Integrator {
601
616
args : & args,
@@ -607,6 +622,7 @@ impl<'tcx> Inliner<'tcx> {
607
622
callsite,
608
623
cleanup_block : unwind,
609
624
in_cleanup_block : false ,
625
+ return_block,
610
626
tcx : self . tcx ,
611
627
always_live_locals : BitSet :: new_filled ( callee_body. local_decls . len ( ) ) ,
612
628
} ;
@@ -626,7 +642,7 @@ impl<'tcx> Inliner<'tcx> {
626
642
} ) ;
627
643
}
628
644
}
629
- if let Some ( block) = callsite . target {
645
+ if let Some ( block) = return_block {
630
646
// To avoid repeated O(n) insert, push any new statements to the end and rotate
631
647
// the slice once.
632
648
let mut n = 0 ;
@@ -684,6 +700,7 @@ impl<'tcx> Inliner<'tcx> {
684
700
callsite : & CallSite < ' tcx > ,
685
701
caller_body : & mut Body < ' tcx > ,
686
702
callee_body : & Body < ' tcx > ,
703
+ return_block : Option < BasicBlock > ,
687
704
) -> Vec < Local > {
688
705
let tcx = self . tcx ;
689
706
@@ -712,8 +729,18 @@ impl<'tcx> Inliner<'tcx> {
712
729
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
713
730
if callsite. fn_sig . abi ( ) == Abi :: RustCall && callee_body. spread_arg . is_none ( ) {
714
731
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
+ ) ;
717
744
assert ! ( args. next( ) . is_none( ) ) ;
718
745
719
746
let tuple = Place :: from ( tuple) ;
@@ -730,13 +757,13 @@ impl<'tcx> Inliner<'tcx> {
730
757
let tuple_field = Operand :: Move ( tcx. mk_place_field ( tuple, FieldIdx :: new ( i) , ty) ) ;
731
758
732
759
// 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 )
734
761
} ) ;
735
762
736
763
closure_ref_arg. chain ( tuple_tmp_args) . collect ( )
737
764
} else {
738
765
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 ) )
740
767
. collect ( )
741
768
}
742
769
}
@@ -748,6 +775,7 @@ impl<'tcx> Inliner<'tcx> {
748
775
arg : Operand < ' tcx > ,
749
776
callsite : & CallSite < ' tcx > ,
750
777
caller_body : & mut Body < ' tcx > ,
778
+ return_block : Option < BasicBlock > ,
751
779
) -> Local {
752
780
// Reuse the operand if it is a moved temporary.
753
781
if let Operand :: Move ( place) = & arg
@@ -760,7 +788,7 @@ impl<'tcx> Inliner<'tcx> {
760
788
// Otherwise, create a temporary for the argument.
761
789
trace ! ( "creating temp for argument {:?}" , arg) ;
762
790
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 ) ;
764
792
caller_body[ callsite. block ] . statements . push ( Statement {
765
793
source_info : callsite. source_info ,
766
794
kind : StatementKind :: Assign ( Box :: new ( ( Place :: from ( local) , Rvalue :: Use ( arg) ) ) ) ,
@@ -774,6 +802,7 @@ impl<'tcx> Inliner<'tcx> {
774
802
caller_body : & mut Body < ' tcx > ,
775
803
callsite : & CallSite < ' tcx > ,
776
804
ty : Ty < ' tcx > ,
805
+ return_block : Option < BasicBlock > ,
777
806
) -> Local {
778
807
let local = caller_body. local_decls . push ( LocalDecl :: new ( ty, callsite. source_info . span ) ) ;
779
808
@@ -782,7 +811,7 @@ impl<'tcx> Inliner<'tcx> {
782
811
kind : StatementKind :: StorageLive ( local) ,
783
812
} ) ;
784
813
785
- if let Some ( block) = callsite . target {
814
+ if let Some ( block) = return_block {
786
815
caller_body[ block] . statements . insert (
787
816
0 ,
788
817
Statement {
@@ -813,6 +842,7 @@ struct Integrator<'a, 'tcx> {
813
842
callsite : & ' a CallSite < ' tcx > ,
814
843
cleanup_block : UnwindAction ,
815
844
in_cleanup_block : bool ,
845
+ return_block : Option < BasicBlock > ,
816
846
tcx : TyCtxt < ' tcx > ,
817
847
always_live_locals : BitSet < Local > ,
818
848
}
@@ -956,7 +986,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
956
986
* unwind = self . map_unwind ( * unwind) ;
957
987
}
958
988
TerminatorKind :: Return => {
959
- terminator. kind = if let Some ( tgt) = self . callsite . target {
989
+ terminator. kind = if let Some ( tgt) = self . return_block {
960
990
TerminatorKind :: Goto { target : tgt }
961
991
} else {
962
992
TerminatorKind :: Unreachable
0 commit comments