diff options
| author | Simonas Kazlauskas <git@kazlauskas.me> | 2016-01-29 20:42:02 +0200 |
|---|---|---|
| committer | Simonas Kazlauskas <git@kazlauskas.me> | 2016-02-04 15:56:04 +0200 |
| commit | 65dd5e6a84aa8d9af477f21fa9797e3d0774a2c1 (patch) | |
| tree | 38203cf1a91d9cef039b76f1df7d0ac380fc944d | |
| parent | 02365fe753708534229ff780e80133e256f3bbe3 (diff) | |
| download | rust-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.rs | 96 | ||||
| -rw-r--r-- | src/librustc/mir/visit.rs | 21 | ||||
| -rw-r--r-- | src/librustc_mir/build/expr/into.rs | 16 | ||||
| -rw-r--r-- | src/librustc_mir/build/scope.rs | 20 | ||||
| -rw-r--r-- | src/librustc_mir/transform/erase_regions.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/trans/mir/block.rs | 41 |
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); + } }, } } |
