Skip to content

Commit 6fff547

Browse files
committed
Slightly simplify the MIR for slice drop shims
1 parent 145add7 commit 6fff547

File tree

2 files changed

+99
-95
lines changed

2 files changed

+99
-95
lines changed

src/librustc_mir/util/elaborate_drops.rs

+65-57
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc::ty::util::IntTypeExt;
1010
use rustc_data_structures::indexed_vec::Idx;
1111
use crate::util::patch::MirPatch;
1212

13-
use std::u32;
13+
use std::convert::TryInto;
1414

1515
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1616
pub enum DropFlagState {
@@ -545,10 +545,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
545545
self.elaborator.patch().new_block(result)
546546
}
547547

548-
/// create a loop that drops an array:
549-
///
550-
548+
/// Create a loop that drops an array:
551549
///
550+
/// ```text
552551
/// loop-block:
553552
/// can_go = cur == length_or_end
554553
/// if can_go then succ else drop-block
@@ -561,15 +560,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
561560
/// cur = cur + 1
562561
/// }
563562
/// drop(ptr)
564-
fn drop_loop(&mut self,
565-
succ: BasicBlock,
566-
cur: Local,
567-
length_or_end: &Place<'tcx>,
568-
ety: Ty<'tcx>,
569-
unwind: Unwind,
570-
ptr_based: bool)
571-
-> BasicBlock
572-
{
563+
/// ```
564+
fn drop_loop(
565+
&mut self,
566+
succ: BasicBlock,
567+
cur: Local,
568+
length_or_end: &Place<'tcx>,
569+
ety: Ty<'tcx>,
570+
unwind: Unwind,
571+
ptr_based: bool,
572+
) -> BasicBlock {
573573
let copy = |place: &Place<'tcx>| Operand::Copy(place.clone());
574574
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
575575
let tcx = self.tcx();
@@ -591,13 +591,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
591591
elem: ProjectionElem::Deref,
592592
}))
593593
),
594-
Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
594+
Rvalue::BinaryOp(BinOp::Offset, move_(&Place::Base(PlaceBase::Local(cur))), one))
595595
} else {
596596
(Rvalue::Ref(
597597
tcx.lifetimes.re_erased,
598598
BorrowKind::Mut { allow_two_phase_borrow: false },
599599
self.place.clone().index(cur)),
600-
Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
600+
Rvalue::BinaryOp(BinOp::Add, move_(&Place::Base(PlaceBase::Local(cur))), one))
601601
};
602602

603603
let drop_block = BasicBlockData {
@@ -647,9 +647,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
647647
// }
648648

649649
if let Some(size) = opt_size {
650-
assert!(size <= (u32::MAX as u64),
651-
"move out check doesn't implemented for array bigger then u32");
652-
let size = size as u32;
650+
let size: u32 = size.try_into().unwrap_or_else(|_| {
651+
bug!("move out check isn't implemented for array sizes bigger than u32::MAX");
652+
});
653653
let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size).map(|i| {
654654
(self.place.clone().elem(ProjectionElem::ConstantIndex{
655655
offset: i,
@@ -667,33 +667,42 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
667667

668668
let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
669669
let tcx = self.tcx();
670-
let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
671-
let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
670+
let elem_size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
671+
let len = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
672+
673+
static USIZE_SWITCH_ZERO: &[u128] = &[0];
674+
672675
let base_block = BasicBlockData {
673676
statements: vec![
674-
self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
675-
self.assign(size_is_zero, Rvalue::BinaryOp(BinOp::Eq,
676-
move_(size),
677-
self.constant_usize(0)))
677+
self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
678+
self.assign(len, Rvalue::Len(self.place.clone())),
678679
],
679680
is_cleanup: self.unwind.is_cleanup(),
680681
terminator: Some(Terminator {
681682
source_info: self.source_info,
682-
kind: TerminatorKind::if_(
683-
tcx,
684-
move_(size_is_zero),
685-
self.drop_loop_pair(ety, false),
686-
self.drop_loop_pair(ety, true)
687-
)
683+
kind: TerminatorKind::SwitchInt {
684+
discr: move_(elem_size),
685+
switch_ty: tcx.types.usize,
686+
values: From::from(USIZE_SWITCH_ZERO),
687+
targets: vec![
688+
self.drop_loop_pair(ety, false, len.clone()),
689+
self.drop_loop_pair(ety, true, len.clone()),
690+
],
691+
},
688692
})
689693
};
690694
self.elaborator.patch().new_block(base_block)
691695
}
692696

693-
// create a pair of drop-loops of `place`, which drops its contents
694-
// even in the case of 1 panic. If `ptr_based`, create a pointer loop,
695-
// otherwise create an index loop.
696-
fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
697+
/// Ceates a pair of drop-loops of `place`, which drops its contents, even
698+
/// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
699+
/// otherwise create an index loop.
700+
fn drop_loop_pair(
701+
&mut self,
702+
ety: Ty<'tcx>,
703+
ptr_based: bool,
704+
length: Place<'tcx>,
705+
) -> BasicBlock {
697706
debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based);
698707
let tcx = self.tcx();
699708
let iter_ty = if ptr_based {
@@ -703,7 +712,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
703712
};
704713

705714
let cur = self.new_temp(iter_ty);
706-
let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
707715
let length_or_end = if ptr_based {
708716
// FIXME check if we want to make it return a `Place` directly
709717
// if all use sites want a `Place::Base` anyway.
@@ -722,41 +730,41 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
722730
ptr_based)
723731
});
724732

725-
let succ = self.succ; // FIXME(#43234)
726733
let loop_block = self.drop_loop(
727-
succ,
734+
self.succ,
728735
cur,
729736
&length_or_end,
730737
ety,
731738
unwind,
732739
ptr_based);
733740

734741
let cur = Place::Base(PlaceBase::Local(cur));
735-
let zero = self.constant_usize(0);
736-
let mut drop_block_stmts = vec![];
737-
drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
738-
if ptr_based {
742+
let drop_block_stmts = if ptr_based {
739743
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
740744
let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
741745
// tmp = &mut P;
742746
// cur = tmp as *mut T;
743747
// end = Offset(cur, len);
744-
drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
745-
tcx.lifetimes.re_erased,
746-
BorrowKind::Mut { allow_two_phase_borrow: false },
747-
self.place.clone()
748-
)));
749-
drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
750-
CastKind::Misc, Operand::Move(tmp), iter_ty
751-
)));
752-
drop_block_stmts.push(self.assign(&length_or_end,
753-
Rvalue::BinaryOp(BinOp::Offset,
754-
Operand::Copy(cur), Operand::Move(length)
755-
)));
748+
vec![
749+
self.assign(&tmp, Rvalue::Ref(
750+
tcx.lifetimes.re_erased,
751+
BorrowKind::Mut { allow_two_phase_borrow: false },
752+
self.place.clone()
753+
)),
754+
self.assign(
755+
&cur,
756+
Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty),
757+
),
758+
self.assign(
759+
&length_or_end,
760+
Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)
761+
)),
762+
]
756763
} else {
757-
// index = 0 (length already pushed)
758-
drop_block_stmts.push(self.assign(&cur, Rvalue::Use(zero)));
759-
}
764+
// cur = 0 (length already pushed)
765+
let zero = self.constant_usize(0);
766+
vec![self.assign(&cur, Rvalue::Use(zero))]
767+
};
760768
let drop_block = self.elaborator.patch().new_block(BasicBlockData {
761769
statements: drop_block_stmts,
762770
is_cleanup: unwind.is_cleanup(),
@@ -768,7 +776,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
768776

769777
// FIXME(#34708): handle partially-dropped array/slice elements.
770778
let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind);
771-
self.drop_flag_test_block(reset_block, succ, unwind)
779+
self.drop_flag_test_block(reset_block, self.succ, unwind)
772780
}
773781

774782
/// The slow-path - create an "open", elaborated drop for a type

src/test/mir-opt/slice-drop-shim.rs

+34-38
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,19 @@ fn main() {
66

77
// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
88
// let mut _2: usize;
9-
// let mut _3: bool;
9+
// let mut _3: usize;
1010
// let mut _4: usize;
11-
// let mut _5: usize;
12-
// let mut _6: &mut std::string::String;
13-
// let mut _7: bool;
14-
// let mut _8: &mut std::string::String;
15-
// let mut _9: bool;
11+
// let mut _5: &mut std::string::String;
12+
// let mut _6: bool;
13+
// let mut _7: &mut std::string::String;
14+
// let mut _8: bool;
15+
// let mut _9: *mut std::string::String;
1616
// let mut _10: *mut std::string::String;
17-
// let mut _11: usize;
18-
// let mut _12: *mut std::string::String;
17+
// let mut _11: &mut std::string::String;
18+
// let mut _12: bool;
1919
// let mut _13: &mut std::string::String;
2020
// let mut _14: bool;
21-
// let mut _15: &mut std::string::String;
22-
// let mut _16: bool;
23-
// let mut _17: *mut [std::string::String];
21+
// let mut _15: *mut [std::string::String];
2422
// bb0: {
2523
// goto -> bb15;
2624
// }
@@ -31,62 +29,60 @@ fn main() {
3129
// resume;
3230
// }
3331
// bb3 (cleanup): {
34-
// _6 = &mut (*_1)[_4];
35-
// _4 = Add(_4, const 1usize);
36-
// drop((*_6)) -> bb4;
32+
// _5 = &mut (*_1)[_4];
33+
// _4 = Add(move _4, const 1usize);
34+
// drop((*_5)) -> bb4;
3735
// }
3836
// bb4 (cleanup): {
39-
// _7 = Eq(_4, _5);
40-
// switchInt(move _7) -> [false: bb3, otherwise: bb2];
37+
// _6 = Eq(_4, _3);
38+
// switchInt(move _6) -> [false: bb3, otherwise: bb2];
4139
// }
4240
// bb5: {
43-
// _8 = &mut (*_1)[_4];
44-
// _4 = Add(_4, const 1usize);
45-
// drop((*_8)) -> [return: bb6, unwind: bb4];
41+
// _7 = &mut (*_1)[_4];
42+
// _4 = Add(move _4, const 1usize);
43+
// drop((*_7)) -> [return: bb6, unwind: bb4];
4644
// }
4745
// bb6: {
48-
// _9 = Eq(_4, _5);
49-
// switchInt(move _9) -> [false: bb5, otherwise: bb1];
46+
// _8 = Eq(_4, _3);
47+
// switchInt(move _8) -> [false: bb5, otherwise: bb1];
5048
// }
5149
// bb7: {
52-
// _5 = Len((*_1));
5350
// _4 = const 0usize;
5451
// goto -> bb6;
5552
// }
5653
// bb8: {
5754
// goto -> bb7;
5855
// }
5956
// bb9 (cleanup): {
60-
// _13 = &mut (*_10);
61-
// _10 = Offset(_10, const 1usize);
62-
// drop((*_13)) -> bb10;
57+
// _11 = &mut (*_9);
58+
// _9 = Offset(move _9, const 1usize);
59+
// drop((*_11)) -> bb10;
6360
// }
6461
// bb10 (cleanup): {
65-
// _14 = Eq(_10, _12);
66-
// switchInt(move _14) -> [false: bb9, otherwise: bb2];
62+
// _12 = Eq(_9, _10);
63+
// switchInt(move _12) -> [false: bb9, otherwise: bb2];
6764
// }
6865
// bb11: {
69-
// _15 = &mut (*_10);
70-
// _10 = Offset(_10, const 1usize);
71-
// drop((*_15)) -> [return: bb12, unwind: bb10];
66+
// _13 = &mut (*_9);
67+
// _9 = Offset(move _9, const 1usize);
68+
// drop((*_13)) -> [return: bb12, unwind: bb10];
7269
// }
7370
// bb12: {
74-
// _16 = Eq(_10, _12);
75-
// switchInt(move _16) -> [false: bb11, otherwise: bb1];
71+
// _14 = Eq(_9, _10);
72+
// switchInt(move _14) -> [false: bb11, otherwise: bb1];
7673
// }
7774
// bb13: {
78-
// _11 = Len((*_1));
79-
// _17 = &mut (*_1);
80-
// _10 = move _17 as *mut std::string::String (Misc);
81-
// _12 = Offset(_10, move _11);
75+
// _15 = &mut (*_1);
76+
// _9 = move _15 as *mut std::string::String (Misc);
77+
// _10 = Offset(_9, move _3);
8278
// goto -> bb12;
8379
// }
8480
// bb14: {
8581
// goto -> bb13;
8682
// }
8783
// bb15: {
8884
// _2 = SizeOf(std::string::String);
89-
// _3 = Eq(move _2, const 0usize);
90-
// switchInt(move _3) -> [false: bb14, otherwise: bb8];
85+
// _3 = Len((*_1));
86+
// switchInt(move _2) -> [0usize: bb8, otherwise: bb14];
9187
// }
9288
// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir

0 commit comments

Comments
 (0)