diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2020-01-25 02:33:52 +0100 |
|---|---|---|
| committer | Jonas Schievink <jonasschievink@gmail.com> | 2020-02-02 13:20:57 +0100 |
| commit | 3c22e51e7f6debd96af76f36aa8b090c40b8acb6 (patch) | |
| tree | afa2fe27a57705c4e3631b9b1d710d0d34161b96 | |
| parent | 3c069a066e50598ef230ba71ed5c5bcf596beb90 (diff) | |
| download | rust-3c22e51e7f6debd96af76f36aa8b090c40b8acb6.tar.gz rust-3c22e51e7f6debd96af76f36aa8b090c40b8acb6.zip | |
Make generator transform move resume arg around
The resume arg is passed as argument `_2` and needs to be moved to the `Yield`s target `Place`
| -rw-r--r-- | src/librustc_mir/transform/generator.rs | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a8defd03f71..c0fefd60f83 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -192,9 +192,10 @@ const RETURNED: usize = GeneratorSubsts::RETURNED; /// Generator has been poisoned const POISONED: usize = GeneratorSubsts::POISONED; -struct SuspensionPoint { +struct SuspensionPoint<'tcx> { state: usize, resume: BasicBlock, + resume_arg: Place<'tcx>, drop: Option<BasicBlock>, storage_liveness: liveness::LiveVarSet, } @@ -216,7 +217,7 @@ struct TransformVisitor<'tcx> { storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>, // A list of suspension points, generated during the transform - suspension_points: Vec<SuspensionPoint>, + suspension_points: Vec<SuspensionPoint<'tcx>>, // The original RETURN_PLACE local new_ret_local: Local, @@ -303,8 +304,8 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { Operand::Move(Place::from(self.new_ret_local)), None, )), - TerminatorKind::Yield { ref value, resume, drop } => { - Some((VariantIdx::new(0), Some(resume), value.clone(), drop)) + TerminatorKind::Yield { ref value, resume, resume_arg, drop } => { + Some((VariantIdx::new(0), Some((resume, resume_arg)), value.clone(), drop)) } _ => None, }; @@ -319,13 +320,14 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { self.make_state(state_idx, v), )), }); - let state = if let Some(resume) = resume { + let state = if let Some((resume, resume_arg)) = resume { // Yield let state = 3 + self.suspension_points.len(); self.suspension_points.push(SuspensionPoint { state, resume, + resume_arg, drop, storage_liveness: self.storage_liveness.get(&block).unwrap().clone(), }); @@ -1063,7 +1065,7 @@ fn create_cases<'tcx, F>( target: F, ) -> Vec<(usize, BasicBlock)> where - F: Fn(&SuspensionPoint) -> Option<BasicBlock>, + F: Fn(&SuspensionPoint<'tcx>) -> Option<BasicBlock>, { let source_info = source_info(body); @@ -1085,6 +1087,16 @@ where } } + // Move the resume argument to the destination place of the `Yield` terminator + let resume_arg = Local::new(2); // 0 = return, 1 = self + statements.push(Statement { + source_info, + kind: StatementKind::Assign(box ( + point.resume_arg, + Rvalue::Use(Operand::Move(resume_arg.into())), + )), + }); + // Then jump to the real target body.basic_blocks_mut().push(BasicBlockData { statements, @@ -1163,7 +1175,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { }; transform.visit_body(body); - // Update our MIR struct to reflect the changed we've made + // Update our MIR struct to reflect the changes we've made body.yield_ty = None; body.arg_count = 2; // self, resume arg body.spread_arg = None; |
