@@ -132,7 +132,6 @@ struct SuspensionPoint {
132132 resume : BasicBlock ,
133133 drop : Option < BasicBlock > ,
134134 storage_liveness : liveness:: LocalSet ,
135- storage_live : Option < BasicBlock > ,
136135}
137136
138137struct TransformVisitor < ' a , ' tcx : ' a > {
@@ -146,8 +145,6 @@ struct TransformVisitor<'a, 'tcx: 'a> {
146145 // Mapping from Local to (type of local, generator struct index)
147146 remap : HashMap < Local , ( Ty < ' tcx > , usize ) > ,
148147
149- mir_local_count : usize ,
150-
151148 // A map from a suspension point in a block to the locals which have live storage at that point
152149 storage_liveness : HashMap < BasicBlock , liveness:: LocalSet > ,
153150
@@ -253,24 +250,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
253250 let state = if let Some ( resume) = resume { // Yield
254251 let state = 3 + self . suspension_points . len ( ) as u32 ;
255252
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-
268253 self . suspension_points . push ( SuspensionPoint {
269254 state,
270255 resume,
271256 drop,
272- storage_liveness : liveness. clone ( ) ,
273- storage_live : None ,
257+ storage_liveness : self . storage_liveness . get ( & block) . unwrap ( ) . clone ( ) ,
274258 } ) ;
275259
276260 state
@@ -363,8 +347,8 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
363347 ignored. visit_mir ( mir) ;
364348
365349 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 ) ;
368352
369353 let mut storage_liveness_map = HashMap :: new ( ) ;
370354
@@ -375,20 +359,22 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
375359 statement_index : data. statements . len ( ) ,
376360 } ;
377361
378- let mut storage_liveness = state_for_location ( loc, & analysis, & storage_live) ;
362+ let storage_liveness = state_for_location ( loc, & analysis, & storage_live) ;
379363
380364 storage_liveness_map. insert ( block, storage_liveness. clone ( ) ) ;
381365
366+ let mut live_locals = storage_liveness;
367+
382368 // Mark locals without storage statements as always live
383- storage_liveness . union ( & ignored. 0 ) ;
369+ live_locals . union ( & ignored. 0 ) ;
384370
385371 // Locals live are live at this point only if they are used across suspension points
386372 // and their storage is live
387- storage_liveness . intersect ( & result . outs [ block] ) ;
373+ live_locals . intersect ( & liveness . outs [ block] ) ;
388374
389375 // Add the locals life at this suspension point to the set of locals which live across
390376 // any suspension points
391- set. union ( & storage_liveness ) ;
377+ set. union ( & live_locals ) ;
392378 }
393379 }
394380
@@ -549,24 +535,11 @@ fn create_generator_drop_shim<'a, 'tcx>(
549535
550536 let source_info = source_info ( & mir) ;
551537
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 ) ;
566539
567540 cases. insert ( 0 , ( 0 , drop_clean) ) ;
568541
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
570543 // the default case which is just to return
571544
572545 insert_switch ( tcx, & mut mir, cases, & transform) ;
@@ -677,18 +650,7 @@ fn create_generator_resume_function<'a, 'tcx>(
677650 }
678651 }
679652
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 ) ) ;
692654
693655 // Jump to the entry point on the 0 state
694656 cases. insert ( 0 , ( 0 , BasicBlock :: new ( 0 ) ) ) ;
@@ -740,6 +702,46 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
740702 drop_clean
741703}
742704
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+
743745impl MirPass for StateTransform {
744746 fn run_pass < ' a , ' tcx > ( & self ,
745747 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -792,7 +794,6 @@ impl MirPass for StateTransform {
792794 state_substs,
793795 remap,
794796 storage_liveness,
795- mir_local_count : mir. local_decls . len ( ) ,
796797 suspension_points : Vec :: new ( ) ,
797798 new_ret_local,
798799 state_field,
@@ -820,30 +821,6 @@ impl MirPass for StateTransform {
820821
821822 dump_mir ( tcx, None , "generator_post-transform" , & 0 , source, mir) ;
822823
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-
847824 // Create a copy of our MIR and use it to create the drop shim for the generator
848825 let drop_shim = create_generator_drop_shim ( tcx,
849826 & transform,
0 commit comments