Skip to content

Commit a2b3e08

Browse files
committed
Fix nits and refactor creation of StorageLive blocks
1 parent d97a7d2 commit a2b3e08

File tree

1 file changed

+52
-75
lines changed

1 file changed

+52
-75
lines changed

src/librustc_mir/transform/generator.rs

+52-75
Original file line numberDiff line numberDiff line change
@@ -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

138137
struct 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+
743745
impl 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

Comments
 (0)