@@ -132,7 +132,6 @@ struct SuspensionPoint {
132
132
resume : BasicBlock ,
133
133
drop : Option < BasicBlock > ,
134
134
storage_liveness : liveness:: LocalSet ,
135
- storage_live : Option < BasicBlock > ,
136
135
}
137
136
138
137
struct TransformVisitor < ' a , ' tcx : ' a > {
@@ -146,8 +145,6 @@ struct TransformVisitor<'a, 'tcx: 'a> {
146
145
// Mapping from Local to (type of local, generator struct index)
147
146
remap : HashMap < Local , ( Ty < ' tcx > , usize ) > ,
148
147
149
- mir_local_count : usize ,
150
-
151
148
// A map from a suspension point in a block to the locals which have live storage at that point
152
149
storage_liveness : HashMap < BasicBlock , liveness:: LocalSet > ,
153
150
@@ -253,24 +250,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
253
250
let state = if let Some ( resume) = resume { // Yield
254
251
let state = 3 + self . suspension_points . len ( ) as u32 ;
255
252
256
- let liveness = self . storage_liveness . get ( & block) . unwrap ( ) ;
257
-
258
- for i in 0 ..( self . mir_local_count ) {
259
- let l = Local :: new ( i) ;
260
- if liveness. contains ( & l) && !self . remap . contains_key ( & l) {
261
- data. statements . push ( Statement {
262
- source_info,
263
- kind : StatementKind :: StorageDead ( l) ,
264
- } ) ;
265
- }
266
- }
267
-
268
253
self . suspension_points . push ( SuspensionPoint {
269
254
state,
270
255
resume,
271
256
drop,
272
- storage_liveness : liveness. clone ( ) ,
273
- storage_live : None ,
257
+ storage_liveness : self . storage_liveness . get ( & block) . unwrap ( ) . clone ( ) ,
274
258
} ) ;
275
259
276
260
state
@@ -363,8 +347,8 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
363
347
ignored. visit_mir ( mir) ;
364
348
365
349
let mut set = liveness:: LocalSet :: new_empty ( mir. local_decls . len ( ) ) ;
366
- let result = liveness:: liveness_of_locals ( mir) ;
367
- liveness:: dump_mir ( tcx, "generator_liveness" , source, mir, & result ) ;
350
+ let liveness = liveness:: liveness_of_locals ( mir) ;
351
+ liveness:: dump_mir ( tcx, "generator_liveness" , source, mir, & liveness ) ;
368
352
369
353
let mut storage_liveness_map = HashMap :: new ( ) ;
370
354
@@ -375,20 +359,22 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
375
359
statement_index : data. statements . len ( ) ,
376
360
} ;
377
361
378
- let mut storage_liveness = state_for_location ( loc, & analysis, & storage_live) ;
362
+ let storage_liveness = state_for_location ( loc, & analysis, & storage_live) ;
379
363
380
364
storage_liveness_map. insert ( block, storage_liveness. clone ( ) ) ;
381
365
366
+ let mut live_locals = storage_liveness;
367
+
382
368
// Mark locals without storage statements as always live
383
- storage_liveness . union ( & ignored. 0 ) ;
369
+ live_locals . union ( & ignored. 0 ) ;
384
370
385
371
// Locals live are live at this point only if they are used across suspension points
386
372
// and their storage is live
387
- storage_liveness . intersect ( & result . outs [ block] ) ;
373
+ live_locals . intersect ( & liveness . outs [ block] ) ;
388
374
389
375
// Add the locals life at this suspension point to the set of locals which live across
390
376
// any suspension points
391
- set. union ( & storage_liveness ) ;
377
+ set. union ( & live_locals ) ;
392
378
}
393
379
}
394
380
@@ -549,24 +535,11 @@ fn create_generator_drop_shim<'a, 'tcx>(
549
535
550
536
let source_info = source_info ( & mir) ;
551
537
552
- let mut cases: Vec < _ > = transform. suspension_points . iter ( ) . filter_map ( |point| {
553
- point. drop . map ( |drop| {
554
- // Make the point's storage live block goto the drop block
555
- let block = point. storage_live . unwrap ( ) ;
556
- let term = Terminator {
557
- source_info,
558
- kind : TerminatorKind :: Goto {
559
- target : drop,
560
- } ,
561
- } ;
562
- mir. basic_blocks_mut ( ) [ block] . terminator = Some ( term) ;
563
- ( point. state , block)
564
- } )
565
- } ) . collect ( ) ;
538
+ let mut cases = create_cases ( & mut mir, transform, |point| point. drop ) ;
566
539
567
540
cases. insert ( 0 , ( 0 , drop_clean) ) ;
568
541
569
- // The returned state 1 and the poisoned state 2 falls through to
542
+ // The returned state (1) and the poisoned state (2) falls through to
570
543
// the default case which is just to return
571
544
572
545
insert_switch ( tcx, & mut mir, cases, & transform) ;
@@ -677,18 +650,7 @@ fn create_generator_resume_function<'a, 'tcx>(
677
650
}
678
651
}
679
652
680
- let mut cases: Vec < _ > = transform. suspension_points . iter ( ) . map ( |point| {
681
- // Make the point's storage live block goto the resume block
682
- let block = point. storage_live . unwrap ( ) ;
683
- let term = Terminator {
684
- source_info : source_info ( mir) ,
685
- kind : TerminatorKind :: Goto {
686
- target : point. resume ,
687
- } ,
688
- } ;
689
- mir. basic_blocks_mut ( ) [ block] . terminator = Some ( term) ;
690
- ( point. state , block)
691
- } ) . collect ( ) ;
653
+ let mut cases = create_cases ( mir, & transform, |point| Some ( point. resume ) ) ;
692
654
693
655
// Jump to the entry point on the 0 state
694
656
cases. insert ( 0 , ( 0 , BasicBlock :: new ( 0 ) ) ) ;
@@ -740,6 +702,46 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
740
702
drop_clean
741
703
}
742
704
705
+ fn create_cases < ' a , ' tcx , F > ( mir : & mut Mir < ' tcx > ,
706
+ transform : & TransformVisitor < ' a , ' tcx > ,
707
+ target : F ) -> Vec < ( u32 , BasicBlock ) >
708
+ where F : Fn ( & SuspensionPoint ) -> Option < BasicBlock > {
709
+ let source_info = source_info ( mir) ;
710
+
711
+ transform. suspension_points . iter ( ) . filter_map ( |point| {
712
+ // Find the target for this suspension point, if applicable
713
+ target ( point) . map ( |target| {
714
+ let block = BasicBlock :: new ( mir. basic_blocks ( ) . len ( ) ) ;
715
+ let mut statements = Vec :: new ( ) ;
716
+
717
+ // Create StorageLive instructions for locals with live storage
718
+ for i in 0 ..( mir. local_decls . len ( ) ) {
719
+ let l = Local :: new ( i) ;
720
+ if point. storage_liveness . contains ( & l) && !transform. remap . contains_key ( & l) {
721
+ statements. push ( Statement {
722
+ source_info,
723
+ kind : StatementKind :: StorageLive ( l) ,
724
+ } ) ;
725
+ }
726
+ }
727
+
728
+ // Then jump to the real target
729
+ mir. basic_blocks_mut ( ) . push ( BasicBlockData {
730
+ statements,
731
+ terminator : Some ( Terminator {
732
+ source_info,
733
+ kind : TerminatorKind :: Goto {
734
+ target,
735
+ } ,
736
+ } ) ,
737
+ is_cleanup : false ,
738
+ } ) ;
739
+
740
+ ( point. state , block)
741
+ } )
742
+ } ) . collect ( )
743
+ }
744
+
743
745
impl MirPass for StateTransform {
744
746
fn run_pass < ' a , ' tcx > ( & self ,
745
747
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -792,7 +794,6 @@ impl MirPass for StateTransform {
792
794
state_substs,
793
795
remap,
794
796
storage_liveness,
795
- mir_local_count : mir. local_decls . len ( ) ,
796
797
suspension_points : Vec :: new ( ) ,
797
798
new_ret_local,
798
799
state_field,
@@ -820,30 +821,6 @@ impl MirPass for StateTransform {
820
821
821
822
dump_mir ( tcx, None , "generator_post-transform" , & 0 , source, mir) ;
822
823
823
- // Create StorageLive instruction blocks for suspension points
824
- for point in & mut transform. suspension_points {
825
- point. storage_live = Some ( BasicBlock :: new ( mir. basic_blocks ( ) . len ( ) ) ) ;
826
- let source_info = source_info ( mir) ;
827
- let mut statements = Vec :: new ( ) ;
828
- for i in 0 ..( transform. mir_local_count ) {
829
- let l = Local :: new ( i) ;
830
- if point. storage_liveness . contains ( & l) && !transform. remap . contains_key ( & l) {
831
- statements. push ( Statement {
832
- source_info,
833
- kind : StatementKind :: StorageLive ( l) ,
834
- } ) ;
835
- }
836
- }
837
- mir. basic_blocks_mut ( ) . push ( BasicBlockData {
838
- statements,
839
- terminator : Some ( Terminator {
840
- source_info,
841
- kind : TerminatorKind :: Unreachable ,
842
- } ) ,
843
- is_cleanup : false ,
844
- } ) ;
845
- }
846
-
847
824
// Create a copy of our MIR and use it to create the drop shim for the generator
848
825
let drop_shim = create_generator_drop_shim ( tcx,
849
826
& transform,
0 commit comments