From: Matthew Jasper Date: Mon, 29 Apr 2019 19:38:08 +0000 (+0100) Subject: Slightly simplify the MIR for slice drop shims X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=6fff547828c13d311bc3e3034f190747b9367816;p=rust.git Slightly simplify the MIR for slice drop shims --- diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 856783bcbaa..98ca7c32675 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -10,7 +10,7 @@ use rustc_data_structures::indexed_vec::Idx; use crate::util::patch::MirPatch; -use std::u32; +use std::convert::TryInto; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum DropFlagState { @@ -545,10 +545,9 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind)) self.elaborator.patch().new_block(result) } - /// create a loop that drops an array: - /// - + /// Create a loop that drops an array: /// + /// ```text /// loop-block: /// can_go = cur == length_or_end /// if can_go then succ else drop-block @@ -561,15 +560,16 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind)) /// cur = cur + 1 /// } /// drop(ptr) - fn drop_loop(&mut self, - succ: BasicBlock, - cur: Local, - length_or_end: &Place<'tcx>, - ety: Ty<'tcx>, - unwind: Unwind, - ptr_based: bool) - -> BasicBlock - { + /// ``` + fn drop_loop( + &mut self, + succ: BasicBlock, + cur: Local, + length_or_end: &Place<'tcx>, + ety: Ty<'tcx>, + unwind: Unwind, + ptr_based: bool, + ) -> BasicBlock { let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); @@ -591,13 +591,13 @@ fn drop_loop(&mut self, elem: ProjectionElem::Deref, })) ), - Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Offset, move_(&Place::Base(PlaceBase::Local(cur))), one)) } else { (Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Mut { allow_two_phase_borrow: false }, self.place.clone().index(cur)), - Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one)) + Rvalue::BinaryOp(BinOp::Add, move_(&Place::Base(PlaceBase::Local(cur))), one)) }; let drop_block = BasicBlockData { @@ -647,9 +647,9 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option) -> Basic // } if let Some(size) = opt_size { - assert!(size <= (u32::MAX as u64), - "move out check doesn't implemented for array bigger then u32"); - let size = size as u32; + let size: u32 = size.try_into().unwrap_or_else(|_| { + bug!("move out check isn't implemented for array sizes bigger than u32::MAX"); + }); let fields: Vec<(Place<'tcx>, Option)> = (0..size).map(|i| { (self.place.clone().elem(ProjectionElem::ConstantIndex{ offset: i, @@ -667,33 +667,42 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option) -> Basic let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); let tcx = self.tcx(); - let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); - let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool))); + let elem_size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + let len = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); + + static USIZE_SWITCH_ZERO: &[u128] = &[0]; + let base_block = BasicBlockData { statements: vec![ - self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), - self.assign(size_is_zero, Rvalue::BinaryOp(BinOp::Eq, - move_(size), - self.constant_usize(0))) + self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), + self.assign(len, Rvalue::Len(self.place.clone())), ], is_cleanup: self.unwind.is_cleanup(), terminator: Some(Terminator { source_info: self.source_info, - kind: TerminatorKind::if_( - tcx, - move_(size_is_zero), - self.drop_loop_pair(ety, false), - self.drop_loop_pair(ety, true) - ) + kind: TerminatorKind::SwitchInt { + discr: move_(elem_size), + switch_ty: tcx.types.usize, + values: From::from(USIZE_SWITCH_ZERO), + targets: vec![ + self.drop_loop_pair(ety, false, len.clone()), + self.drop_loop_pair(ety, true, len.clone()), + ], + }, }) }; self.elaborator.patch().new_block(base_block) } - // create a pair of drop-loops of `place`, which drops its contents - // even in the case of 1 panic. If `ptr_based`, create a pointer loop, - // otherwise create an index loop. - fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { + /// Ceates a pair of drop-loops of `place`, which drops its contents, even + /// in the case of 1 panic. If `ptr_based`, creates a pointer loop, + /// otherwise create an index loop. + fn drop_loop_pair( + &mut self, + ety: Ty<'tcx>, + ptr_based: bool, + length: Place<'tcx>, + ) -> BasicBlock { debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based); let tcx = self.tcx(); let iter_ty = if ptr_based { @@ -703,7 +712,6 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { }; let cur = self.new_temp(iter_ty); - let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize))); let length_or_end = if ptr_based { // FIXME check if we want to make it return a `Place` directly // if all use sites want a `Place::Base` anyway. @@ -722,9 +730,8 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { ptr_based) }); - let succ = self.succ; // FIXME(#43234) let loop_block = self.drop_loop( - succ, + self.succ, cur, &length_or_end, ety, @@ -732,31 +739,32 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { ptr_based); let cur = Place::Base(PlaceBase::Local(cur)); - let zero = self.constant_usize(0); - let mut drop_block_stmts = vec![]; - drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone()))); - if ptr_based { + let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty))); // tmp = &mut P; // cur = tmp as *mut T; // end = Offset(cur, len); - drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - ))); - drop_block_stmts.push(self.assign(&cur, Rvalue::Cast( - CastKind::Misc, Operand::Move(tmp), iter_ty - ))); - drop_block_stmts.push(self.assign(&length_or_end, - Rvalue::BinaryOp(BinOp::Offset, - Operand::Copy(cur), Operand::Move(length) - ))); + vec![ + self.assign(&tmp, Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone() + )), + self.assign( + &cur, + Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), + ), + self.assign( + &length_or_end, + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) + )), + ] } else { - // index = 0 (length already pushed) - drop_block_stmts.push(self.assign(&cur, Rvalue::Use(zero))); - } + // cur = 0 (length already pushed) + let zero = self.constant_usize(0); + vec![self.assign(&cur, Rvalue::Use(zero))] + }; let drop_block = self.elaborator.patch().new_block(BasicBlockData { statements: drop_block_stmts, is_cleanup: unwind.is_cleanup(), @@ -768,7 +776,7 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock { // FIXME(#34708): handle partially-dropped array/slice elements. let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind); - self.drop_flag_test_block(reset_block, succ, unwind) + self.drop_flag_test_block(reset_block, self.succ, unwind) } /// The slow-path - create an "open", elaborated drop for a type diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f558ec18ba9..754fad51b21 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -6,21 +6,19 @@ fn main() { // START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir // let mut _2: usize; -// let mut _3: bool; +// let mut _3: usize; // let mut _4: usize; -// let mut _5: usize; -// let mut _6: &mut std::string::String; -// let mut _7: bool; -// let mut _8: &mut std::string::String; -// let mut _9: bool; +// let mut _5: &mut std::string::String; +// let mut _6: bool; +// let mut _7: &mut std::string::String; +// let mut _8: bool; +// let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: usize; -// let mut _12: *mut std::string::String; +// let mut _11: &mut std::string::String; +// let mut _12: bool; // let mut _13: &mut std::string::String; // let mut _14: bool; -// let mut _15: &mut std::string::String; -// let mut _16: bool; -// let mut _17: *mut [std::string::String]; +// let mut _15: *mut [std::string::String]; // bb0: { // goto -> bb15; // } @@ -31,25 +29,24 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _6 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_6)) -> bb4; +// _5 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_5)) -> bb4; // } // bb4 (cleanup): { -// _7 = Eq(_4, _5); -// switchInt(move _7) -> [false: bb3, otherwise: bb2]; +// _6 = Eq(_4, _3); +// switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _8 = &mut (*_1)[_4]; -// _4 = Add(_4, const 1usize); -// drop((*_8)) -> [return: bb6, unwind: bb4]; +// _7 = &mut (*_1)[_4]; +// _4 = Add(move _4, const 1usize); +// drop((*_7)) -> [return: bb6, unwind: bb4]; // } // bb6: { -// _9 = Eq(_4, _5); -// switchInt(move _9) -> [false: bb5, otherwise: bb1]; +// _8 = Eq(_4, _3); +// switchInt(move _8) -> [false: bb5, otherwise: bb1]; // } // bb7: { -// _5 = Len((*_1)); // _4 = const 0usize; // goto -> bb6; // } @@ -57,28 +54,27 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _13 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_13)) -> bb10; +// _11 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_11)) -> bb10; // } // bb10 (cleanup): { -// _14 = Eq(_10, _12); -// switchInt(move _14) -> [false: bb9, otherwise: bb2]; +// _12 = Eq(_9, _10); +// switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _15 = &mut (*_10); -// _10 = Offset(_10, const 1usize); -// drop((*_15)) -> [return: bb12, unwind: bb10]; +// _13 = &mut (*_9); +// _9 = Offset(move _9, const 1usize); +// drop((*_13)) -> [return: bb12, unwind: bb10]; // } // bb12: { -// _16 = Eq(_10, _12); -// switchInt(move _16) -> [false: bb11, otherwise: bb1]; +// _14 = Eq(_9, _10); +// switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _11 = Len((*_1)); -// _17 = &mut (*_1); -// _10 = move _17 as *mut std::string::String (Misc); -// _12 = Offset(_10, move _11); +// _15 = &mut (*_1); +// _9 = move _15 as *mut std::string::String (Misc); +// _10 = Offset(_9, move _3); // goto -> bb12; // } // bb14: { @@ -86,7 +82,7 @@ fn main() { // } // bb15: { // _2 = SizeOf(std::string::String); -// _3 = Eq(move _2, const 0usize); -// switchInt(move _3) -> [false: bb14, otherwise: bb8]; +// _3 = Len((*_1)); +// switchInt(move _2) -> [0usize: bb8, otherwise: bb14]; // } // END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir