about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2020-01-25 02:33:52 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-02-02 13:20:57 +0100
commit3c22e51e7f6debd96af76f36aa8b090c40b8acb6 (patch)
treeafa2fe27a57705c4e3631b9b1d710d0d34161b96
parent3c069a066e50598ef230ba71ed5c5bcf596beb90 (diff)
downloadrust-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.rs26
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;