about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2016-01-29 20:42:02 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2016-02-04 15:56:04 +0200
commit65dd5e6a84aa8d9af477f21fa9797e3d0774a2c1 (patch)
tree38203cf1a91d9cef039b76f1df7d0ac380fc944d
parent02365fe753708534229ff780e80133e256f3bbe3 (diff)
downloadrust-65dd5e6a84aa8d9af477f21fa9797e3d0774a2c1.tar.gz
rust-65dd5e6a84aa8d9af477f21fa9797e3d0774a2c1.zip
Remove the CallKind
We used to have CallKind only because there was a requirement to have all successors in a
contiguous memory block. Now that the requirement is gone, remove the CallKind and instead just
have the necessary information inline.

Awesome!
-rw-r--r--src/librustc/mir/repr.rs96
-rw-r--r--src/librustc/mir/visit.rs21
-rw-r--r--src/librustc_mir/build/expr/into.rs16
-rw-r--r--src/librustc_mir/build/scope.rs20
-rw-r--r--src/librustc_mir/transform/erase_regions.rs4
-rw-r--r--src/librustc_trans/trans/mir/block.rs41
6 files changed, 53 insertions, 145 deletions
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index ed6c4e80c2d..59d00b436c8 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -268,71 +268,13 @@ pub enum Terminator<'tcx> {
         func: Operand<'tcx>,
         /// Arguments the function is called with
         args: Vec<Operand<'tcx>>,
-        /// The kind of call with associated information
-        kind: CallKind<'tcx>,
+        /// Destination for the return value. If some, the call is converging.
+        destination: Option<(Lvalue<'tcx>, BasicBlock)>,
+        /// Cleanups to be done if the call unwinds.
+        cleanup: Option<BasicBlock>
     },
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum CallKind<'tcx> {
-    /// Diverging function without associated cleanup
-    Diverging,
-    /// Diverging function with associated cleanup
-    DivergingCleanup(BasicBlock),
-    /// Converging function without associated cleanup
-    Converging {
-        /// Destination where the call result is written
-        destination: Lvalue<'tcx>,
-        /// Block to branch into on successful return
-        target: BasicBlock,
-    },
-    ConvergingCleanup {
-        /// Destination where the call result is written
-        destination: Lvalue<'tcx>,
-        /// First target is branched to on successful return.
-        /// Second block contains the cleanups to do on unwind.
-        targets: (BasicBlock, BasicBlock)
-    }
-}
-
-impl<'tcx> CallKind<'tcx> {
-    pub fn successors(&self) -> &[BasicBlock] {
-        match *self {
-            CallKind::Diverging => &[],
-            CallKind::DivergingCleanup(ref b) |
-            CallKind::Converging { target: ref b, .. } => slice::ref_slice(b),
-            CallKind::ConvergingCleanup { ref targets, .. } => targets.as_slice(),
-        }
-    }
-
-    pub fn successors_mut(&mut self) -> &mut [BasicBlock] {
-        match *self {
-            CallKind::Diverging => &mut [],
-            CallKind::DivergingCleanup(ref mut b) |
-            CallKind::Converging { target: ref mut b, .. } => slice::mut_ref_slice(b),
-            CallKind::ConvergingCleanup { ref mut targets, .. } => targets.as_mut_slice(),
-        }
-    }
-
-    pub fn destination(&self) -> Option<&Lvalue<'tcx>> {
-        match *self {
-            CallKind::Converging { ref destination, .. } |
-            CallKind::ConvergingCleanup { ref destination, .. } => Some(destination),
-            CallKind::Diverging |
-            CallKind::DivergingCleanup(_) => None
-        }
-    }
-
-    pub fn destination_mut(&mut self) -> Option<&mut Lvalue<'tcx>> {
-        match *self {
-            CallKind::Converging { ref mut destination, .. } |
-            CallKind::ConvergingCleanup { ref mut destination, .. } => Some(destination),
-            CallKind::Diverging |
-            CallKind::DivergingCleanup(_) => None
-        }
-    }
-}
-
 impl<'tcx> Terminator<'tcx> {
     pub fn successors(&self) -> Cow<[BasicBlock]> {
         use self::Terminator::*;
@@ -343,7 +285,11 @@ impl<'tcx> Terminator<'tcx> {
             SwitchInt { targets: ref b, .. } => b[..].into_cow(),
             Resume => (&[]).into_cow(),
             Return => (&[]).into_cow(),
-            Call { ref kind, .. } => kind.successors()[..].into_cow(),
+            Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
+            Call { destination: Some((_, ref t)), cleanup: None, .. } =>
+                slice::ref_slice(t).into_cow(),
+            Call { destination: None, cleanup: Some(ref c), .. } => slice::ref_slice(c).into_cow(),
+            Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
         }
     }
 
@@ -358,7 +304,10 @@ impl<'tcx> Terminator<'tcx> {
             SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
             Resume => Vec::new(),
             Return => Vec::new(),
-            Call { ref mut kind, .. } => kind.successors_mut().iter_mut().collect(),
+            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
+            Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
+            Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
+            Call { destination: None, cleanup: None, .. } => vec![],
         }
     }
 }
@@ -425,8 +374,8 @@ impl<'tcx> Terminator<'tcx> {
             SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
             Return => write!(fmt, "return"),
             Resume => write!(fmt, "resume"),
-            Call { ref kind, ref func, ref args } => {
-                if let Some(destination) = kind.destination() {
+            Call { ref func, ref args, ref destination, .. } => {
+                if let Some((ref destination, _)) = *destination {
                     try!(write!(fmt, "{:?} = ", destination));
                 }
                 try!(write!(fmt, "{:?}(", func));
@@ -464,16 +413,11 @@ impl<'tcx> Terminator<'tcx> {
                       .chain(iter::once(String::from("otherwise").into()))
                       .collect()
             }
-            Call { ref kind, .. } => match *kind {
-                CallKind::Diverging =>
-                    vec![],
-                CallKind::DivergingCleanup(..) =>
-                    vec!["unwind".into_cow()],
-                CallKind::Converging { .. } =>
-                    vec!["return".into_cow()],
-                CallKind::ConvergingCleanup { .. } =>
-                    vec!["return".into_cow(), "unwind".into_cow()],
-            },
+            Call { destination: Some(_), cleanup: Some(_), .. } =>
+                vec!["return".into_cow(), "unwind".into_cow()],
+            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
+            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
+            Call { destination: None, cleanup: None, .. } => vec![],
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 494eac44b1a..73dd0de1c04 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -179,28 +179,17 @@ macro_rules! make_mir_visitor {
 
                     Terminator::Call { ref $($mutability)* func,
                                        ref $($mutability)* args,
-                                       ref $($mutability)* kind } => {
+                                       ref $($mutability)* destination,
+                                       ref $($mutability)* cleanup } => {
                         self.visit_operand(func);
                         for arg in args {
                             self.visit_operand(arg);
                         }
-                        match *kind {
-                            CallKind::Converging {
-                                ref $($mutability)* destination,
-                                ..
-                            }        |
-                            CallKind::ConvergingCleanup {
-                                ref $($mutability)* destination,
-                                ..
-                            } => {
-                                self.visit_lvalue(destination, LvalueContext::Store);
-                            }
-                            CallKind::Diverging           |
-                            CallKind::DivergingCleanup(_) => {}
-                        }
-                        for &target in kind.successors() {
+                        if let Some((ref $($mutability)* destination, target)) = *destination {
+                            self.visit_lvalue(destination, LvalueContext::Store);
                             self.visit_branch(block, target);
                         }
+                        cleanup.map(|t| self.visit_branch(block, t));
                     }
                 }
             }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 7ecd8a26507..3b453a214b6 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -253,17 +253,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 this.cfg.terminate(block, Terminator::Call {
                     func: fun,
                     args: args,
-                    kind: match (cleanup, diverges) {
-                        (None, true) => CallKind::Diverging,
-                        (Some(c), true) => CallKind::DivergingCleanup(c),
-                        (None, false) => CallKind::Converging {
-                            destination: destination.clone(),
-                            target: success
-                        },
-                        (Some(c), false) => CallKind::ConvergingCleanup {
-                            destination: destination.clone(),
-                            targets: (success, c)
-                        }
+                    cleanup: cleanup,
+                    destination: if diverges {
+                        None
+                    } else {
+                        Some ((destination.clone(), success))
                     }
                 });
                 success.unit()
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 35153bc8a90..fef6837f3f7 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -273,7 +273,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                     ));
                     let func = Constant {
                         span: item.1,
-                        ty: tcx.lookup_item_type(item.0).ty.subst(substs),
+                        ty: tcx.lookup_item_type(item.0).ty,
                         literal: Literal::Item {
                             def_id: item.0,
                             kind: ItemKind::Function,
@@ -285,10 +285,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                     self.cfg.terminate(new_block, Terminator::Call {
                         func: Operand::Constant(func),
                         args: vec![Operand::Consume(lvalue.clone())],
-                        kind: CallKind::Converging {
-                            target: old_block,
-                            destination: unit_tmp.clone()
-                        }
+                        destination: Some((unit_tmp.clone(), old_block)),
+                        cleanup: None // we’re already doing divergence cleanups
                     });
                     terminator = Terminator::Goto { target: new_block };
                 }
@@ -383,10 +381,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         self.cfg.terminate(block, Terminator::Call {
             func: Operand::Constant(func),
             args: vec![Operand::Consume(tuple_ref), index, len],
-            kind: match cleanup {
-                None => CallKind::Diverging,
-                Some(c) => CallKind::DivergingCleanup(c)
-            }
+            destination: None,
+            cleanup: cleanup,
         });
     }
 
@@ -423,10 +419,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         self.cfg.terminate(block, Terminator::Call {
             func: Operand::Constant(func),
             args: vec![Operand::Consume(tuple_ref)],
-            kind: match cleanup {
-                None => CallKind::Diverging,
-                Some(c) => CallKind::DivergingCleanup(c)
-            }
+            cleanup: cleanup,
+            destination: None,
         });
     }
 
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 3cd1bd76c54..00162be816b 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -93,8 +93,8 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
                 self.erase_regions_lvalue(discr);
                 *switch_ty = self.tcx.erase_regions(switch_ty);
             },
-            Terminator::Call { ref mut func, ref mut args, ref mut kind } => {
-                if let Some(destination) = kind.destination_mut() {
+            Terminator::Call { ref mut func, ref mut args, ref mut destination, .. } => {
+                if let Some((ref mut destination, _)) = *destination {
                     self.erase_regions_lvalue(destination);
                 }
                 self.erase_regions_operand(func);
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index 5651710aa80..c1ab55f9f53 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -94,7 +94,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
             }
 
-            mir::Terminator::Call { ref func, ref args, ref kind } => {
+            mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
                 // Create the callee. This will always be a fn ptr and hence a kind of scalar.
                 let callee = self.trans_operand(bcx, func);
                 let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
@@ -115,7 +115,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 };
 
                 // Prepare the return value destination
-                let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
+                let (ret_dest_ty, must_copy_dest) = if let Some((ref d, _)) = *destination {
                     let dest = self.trans_lvalue(bcx, d);
                     let ret_ty = dest.ty.to_ty(bcx.tcx());
                     if !is_foreign && type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
@@ -144,9 +144,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 }
 
                 // Many different ways to call a function handled here
-                match (is_foreign, base::avoid_invoke(bcx), kind) {
+                match (is_foreign, base::avoid_invoke(bcx), cleanup, destination) {
                     // The two cases below are the only ones to use LLVM’s `invoke`.
-                    (false, false, &mir::CallKind::DivergingCleanup(cleanup)) => {
+                    (false, false, &Some(cleanup), &None) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let unreachable_blk = self.unreachable_block();
@@ -158,14 +158,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                       Some(attrs),
                                       debugloc);
                     },
-                    (false, false, &mir::CallKind::ConvergingCleanup { ref targets, .. }) => {
-                        let cleanup = self.bcx(targets.1);
+                    (false, false, &Some(cleanup), &Some((_, success))) => {
+                        let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let (target, postinvoke) = if must_copy_dest {
-                            (bcx.fcx.new_block("", None),
-                             Some(self.bcx(targets.0)))
+                            (bcx.fcx.new_block("", None), Some(self.bcx(success)))
                         } else {
-                            (self.bcx(targets.0), None)
+                            (self.bcx(success), None)
                         };
                         let invokeret = build::Invoke(bcx,
                                                       callee.immediate(),
@@ -205,19 +204,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             build::Br(target, postinvoketarget.llbb, debugloc);
                         }
                     },
-                    (false, _, &mir::CallKind::DivergingCleanup(_)) |
-                    (false, _, &mir::CallKind::Diverging) => {
+                    (false, _, _, &None) => {
                         build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
                         build::Unreachable(bcx);
                     }
-                    (false, _, k@&mir::CallKind::ConvergingCleanup { .. }) |
-                    (false, _, k@&mir::CallKind::Converging { .. }) => {
-                        // FIXME: Bug #20046
-                        let target = match *k {
-                            mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
-                            mir::CallKind::Converging { target, .. } => target,
-                            _ => unreachable!()
-                        };
+                    (false, _, _, &Some((_, target))) => {
                         let llret = build::Call(bcx,
                                                 callee.immediate(),
                                                 &llargs[..],
@@ -231,7 +222,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         build::Br(bcx, self.llblock(target), debugloc);
                     }
                     // Foreign functions
-                    (true, _, k) => {
+                    (true, _, _, destination) => {
                         let (dest, _) = ret_dest_ty
                             .expect("return destination is not set");
                         bcx = foreign::trans_native_call(bcx,
@@ -241,13 +232,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                                    &llargs[..],
                                                    arg_tys,
                                                    debugloc);
-                        match *k {
-                            mir::CallKind::ConvergingCleanup { targets, .. } =>
-                                build::Br(bcx, self.llblock(targets.0), debugloc),
-                            mir::CallKind::Converging { target, .. } =>
-                                build::Br(bcx, self.llblock(target), debugloc),
-                            _ => ()
-                        };
+                        if let Some((_, target)) = *destination {
+                            build::Br(bcx, self.llblock(target), debugloc);
+                        }
                     },
                 }
             }