2
2
3
3
use rustc_attr as attr;
4
4
use rustc_index:: bit_set:: BitSet ;
5
- use rustc_index:: vec:: { Idx , IndexVec } ;
5
+ use rustc_index:: vec:: Idx ;
6
6
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
7
7
use rustc_middle:: mir:: visit:: * ;
8
8
use rustc_middle:: mir:: * ;
@@ -14,6 +14,7 @@ use super::simplify::{remove_dead_blocks, CfgSimplifier};
14
14
use crate :: transform:: MirPass ;
15
15
use std:: collections:: VecDeque ;
16
16
use std:: iter;
17
+ use std:: ops:: RangeFrom ;
17
18
18
19
const DEFAULT_THRESHOLD : usize = 50 ;
19
20
const HINT_THRESHOLD : usize = 100 ;
@@ -477,26 +478,24 @@ impl Inliner<'tcx> {
477
478
// Copy the arguments if needed.
478
479
let args: Vec < _ > = self . make_call_args ( args, & callsite, caller_body, return_block) ;
479
480
480
- let bb_len = caller_body. basic_blocks ( ) . len ( ) ;
481
481
let mut integrator = Integrator {
482
- block_idx : bb_len,
483
482
args : & args,
484
- local_map : IndexVec :: with_capacity ( callee_body. local_decls . len ( ) ) ,
485
- scope_map : IndexVec :: with_capacity ( callee_body. source_scopes . len ( ) ) ,
483
+ new_locals : Local :: new ( caller_body. local_decls . len ( ) ) ..,
484
+ new_scopes : SourceScope :: new ( caller_body. source_scopes . len ( ) ) ..,
485
+ new_blocks : BasicBlock :: new ( caller_body. basic_blocks ( ) . len ( ) ) ..,
486
486
destination : dest,
487
487
return_block,
488
488
cleanup_block : cleanup,
489
489
in_cleanup_block : false ,
490
490
tcx : self . tcx ,
491
491
} ;
492
492
493
- for mut scope in callee_body. source_scopes . iter ( ) . cloned ( ) {
494
- // Map the callee scopes into the caller.
495
- // FIXME(eddyb) this may ICE if the scopes are out of order.
496
- scope. parent_scope = scope. parent_scope . map ( |s| integrator. scope_map [ s] ) ;
497
- scope. inlined_parent_scope =
498
- scope. inlined_parent_scope . map ( |s| integrator. scope_map [ s] ) ;
493
+ // Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
494
+ // (or existing ones, in a few special cases) in the caller.
495
+ integrator. visit_body ( & mut callee_body) ;
499
496
497
+ for scope in & mut callee_body. source_scopes {
498
+ // FIXME(eddyb) move this into a `fn visit_scope_data` in `Integrator`.
500
499
if scope. parent_scope . is_none ( ) {
501
500
let callsite_scope = & caller_body. source_scopes [ callsite. source_info . scope ] ;
502
501
@@ -516,38 +515,26 @@ impl Inliner<'tcx> {
516
515
} else if scope. inlined_parent_scope . is_none ( ) {
517
516
// Make it easy to find the scope with `inlined` set above.
518
517
scope. inlined_parent_scope =
519
- Some ( integrator. scope_map [ OUTERMOST_SOURCE_SCOPE ] ) ;
518
+ Some ( integrator. map_scope ( OUTERMOST_SOURCE_SCOPE ) ) ;
520
519
}
521
-
522
- let idx = caller_body. source_scopes . push ( scope) ;
523
- integrator. scope_map . push ( idx) ;
524
- }
525
-
526
- for loc in callee_body. vars_and_temps_iter ( ) {
527
- let mut local = callee_body. local_decls [ loc] . clone ( ) ;
528
-
529
- local. source_info . scope = integrator. scope_map [ local. source_info . scope ] ;
530
-
531
- let idx = caller_body. local_decls . push ( local) ;
532
- integrator. local_map . push ( idx) ;
533
- }
534
-
535
- for mut var_debug_info in callee_body. var_debug_info . drain ( ..) {
536
- integrator. visit_var_debug_info ( & mut var_debug_info) ;
537
- caller_body. var_debug_info . push ( var_debug_info) ;
538
520
}
539
521
540
- for ( bb, mut block) in callee_body. basic_blocks_mut ( ) . drain_enumerated ( ..) {
541
- integrator. visit_basic_block_data ( bb, & mut block) ;
542
- caller_body. basic_blocks_mut ( ) . push ( block) ;
543
- }
522
+ // Insert all of the (mapped) parts of the callee body into the caller.
523
+ caller_body. local_decls . extend (
524
+ // FIXME(eddyb) make `Range<Local>` iterable so that we can use
525
+ // `callee_body.local_decls.drain(callee_body.vars_and_temps())`
526
+ callee_body
527
+ . vars_and_temps_iter ( )
528
+ . map ( |local| callee_body. local_decls [ local] . clone ( ) ) ,
529
+ ) ;
530
+ caller_body. source_scopes . extend ( callee_body. source_scopes . drain ( ..) ) ;
531
+ caller_body. var_debug_info . extend ( callee_body. var_debug_info . drain ( ..) ) ;
532
+ caller_body. basic_blocks_mut ( ) . extend ( callee_body. basic_blocks_mut ( ) . drain ( ..) ) ;
544
533
545
- let terminator = Terminator {
534
+ caller_body [ callsite . bb ] . terminator = Some ( Terminator {
546
535
source_info : callsite. source_info ,
547
- kind : TerminatorKind :: Goto { target : BasicBlock :: new ( bb_len) } ,
548
- } ;
549
-
550
- caller_body[ callsite. bb ] . terminator = Some ( terminator) ;
536
+ kind : TerminatorKind :: Goto { target : integrator. map_block ( START_BLOCK ) } ,
537
+ } ) ;
551
538
552
539
true
553
540
}
@@ -703,10 +690,10 @@ fn type_size_of<'tcx>(
703
690
* stuff.
704
691
*/
705
692
struct Integrator < ' a , ' tcx > {
706
- block_idx : usize ,
707
693
args : & ' a [ Local ] ,
708
- local_map : IndexVec < Local , Local > ,
709
- scope_map : IndexVec < SourceScope , SourceScope > ,
694
+ new_locals : RangeFrom < Local > ,
695
+ new_scopes : RangeFrom < SourceScope > ,
696
+ new_blocks : RangeFrom < BasicBlock > ,
710
697
destination : Place < ' tcx > ,
711
698
return_block : BasicBlock ,
712
699
cleanup_block : Option < BasicBlock > ,
@@ -715,23 +702,31 @@ struct Integrator<'a, 'tcx> {
715
702
}
716
703
717
704
impl < ' a , ' tcx > Integrator < ' a , ' tcx > {
718
- fn update_target ( & self , tgt : BasicBlock ) -> BasicBlock {
719
- let new = BasicBlock :: new ( tgt. index ( ) + self . block_idx ) ;
720
- debug ! ( "updating target `{:?}`, new: `{:?}`" , tgt, new) ;
705
+ fn map_local ( & self , local : Local ) -> Local {
706
+ let new = if local == RETURN_PLACE {
707
+ self . destination . local
708
+ } else {
709
+ let idx = local. index ( ) - 1 ;
710
+ if idx < self . args . len ( ) {
711
+ self . args [ idx]
712
+ } else {
713
+ Local :: new ( self . new_locals . start . index ( ) + ( idx - self . args . len ( ) ) )
714
+ }
715
+ } ;
716
+ debug ! ( "mapping local `{:?}` to `{:?}`" , local, new) ;
721
717
new
722
718
}
723
719
724
- fn make_integrate_local ( & self , local : Local ) -> Local {
725
- if local == RETURN_PLACE {
726
- return self . destination . local ;
727
- }
728
-
729
- let idx = local. index ( ) - 1 ;
730
- if idx < self . args . len ( ) {
731
- return self . args [ idx] ;
732
- }
720
+ fn map_scope ( & self , scope : SourceScope ) -> SourceScope {
721
+ let new = SourceScope :: new ( self . new_scopes . start . index ( ) + scope. index ( ) ) ;
722
+ debug ! ( "mapping scope `{:?}` to `{:?}`" , scope, new) ;
723
+ new
724
+ }
733
725
734
- self . local_map [ Local :: new ( idx - self . args . len ( ) ) ]
726
+ fn map_block ( & self , block : BasicBlock ) -> BasicBlock {
727
+ let new = BasicBlock :: new ( self . new_blocks . start . index ( ) + block. index ( ) ) ;
728
+ debug ! ( "mapping block `{:?}` to `{:?}`" , block, new) ;
729
+ new
735
730
}
736
731
}
737
732
@@ -741,7 +736,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
741
736
}
742
737
743
738
fn visit_local ( & mut self , local : & mut Local , _ctxt : PlaceContext , _location : Location ) {
744
- * local = self . make_integrate_local ( * local) ;
739
+ * local = self . map_local ( * local) ;
740
+ }
741
+
742
+ fn visit_source_scope ( & mut self , scope : & mut SourceScope ) {
743
+ * scope = self . map_scope ( * scope) ;
745
744
}
746
745
747
746
fn visit_place ( & mut self , place : & mut Place < ' tcx > , context : PlaceContext , location : Location ) {
@@ -785,18 +784,18 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
785
784
match terminator. kind {
786
785
TerminatorKind :: GeneratorDrop | TerminatorKind :: Yield { .. } => bug ! ( ) ,
787
786
TerminatorKind :: Goto { ref mut target } => {
788
- * target = self . update_target ( * target) ;
787
+ * target = self . map_block ( * target) ;
789
788
}
790
789
TerminatorKind :: SwitchInt { ref mut targets, .. } => {
791
790
for tgt in targets. all_targets_mut ( ) {
792
- * tgt = self . update_target ( * tgt) ;
791
+ * tgt = self . map_block ( * tgt) ;
793
792
}
794
793
}
795
794
TerminatorKind :: Drop { ref mut target, ref mut unwind, .. }
796
795
| TerminatorKind :: DropAndReplace { ref mut target, ref mut unwind, .. } => {
797
- * target = self . update_target ( * target) ;
796
+ * target = self . map_block ( * target) ;
798
797
if let Some ( tgt) = * unwind {
799
- * unwind = Some ( self . update_target ( tgt) ) ;
798
+ * unwind = Some ( self . map_block ( tgt) ) ;
800
799
} else if !self . in_cleanup_block {
801
800
// Unless this drop is in a cleanup block, add an unwind edge to
802
801
// the original call's cleanup block
@@ -805,20 +804,20 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
805
804
}
806
805
TerminatorKind :: Call { ref mut destination, ref mut cleanup, .. } => {
807
806
if let Some ( ( _, ref mut tgt) ) = * destination {
808
- * tgt = self . update_target ( * tgt) ;
807
+ * tgt = self . map_block ( * tgt) ;
809
808
}
810
809
if let Some ( tgt) = * cleanup {
811
- * cleanup = Some ( self . update_target ( tgt) ) ;
810
+ * cleanup = Some ( self . map_block ( tgt) ) ;
812
811
} else if !self . in_cleanup_block {
813
812
// Unless this call is in a cleanup block, add an unwind edge to
814
813
// the original call's cleanup block
815
814
* cleanup = self . cleanup_block ;
816
815
}
817
816
}
818
817
TerminatorKind :: Assert { ref mut target, ref mut cleanup, .. } => {
819
- * target = self . update_target ( * target) ;
818
+ * target = self . map_block ( * target) ;
820
819
if let Some ( tgt) = * cleanup {
821
- * cleanup = Some ( self . update_target ( tgt) ) ;
820
+ * cleanup = Some ( self . map_block ( tgt) ) ;
822
821
} else if !self . in_cleanup_block {
823
822
// Unless this assert is in a cleanup block, add an unwind edge to
824
823
// the original call's cleanup block
@@ -836,8 +835,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
836
835
TerminatorKind :: Abort => { }
837
836
TerminatorKind :: Unreachable => { }
838
837
TerminatorKind :: FalseEdge { ref mut real_target, ref mut imaginary_target } => {
839
- * real_target = self . update_target ( * real_target) ;
840
- * imaginary_target = self . update_target ( * imaginary_target) ;
838
+ * real_target = self . map_block ( * real_target) ;
839
+ * imaginary_target = self . map_block ( * imaginary_target) ;
841
840
}
842
841
TerminatorKind :: FalseUnwind { real_target : _, unwind : _ } =>
843
842
// see the ordering of passes in the optimized_mir query.
@@ -846,13 +845,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
846
845
}
847
846
TerminatorKind :: InlineAsm { ref mut destination, .. } => {
848
847
if let Some ( ref mut tgt) = * destination {
849
- * tgt = self . update_target ( * tgt) ;
848
+ * tgt = self . map_block ( * tgt) ;
850
849
}
851
850
}
852
851
}
853
852
}
854
-
855
- fn visit_source_scope ( & mut self , scope : & mut SourceScope ) {
856
- * scope = self . scope_map [ * scope] ;
857
- }
858
853
}
0 commit comments