diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 459d87d74cd7b..7f92199dec455 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -317,16 +317,56 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let block = |blocks: &mut IndexVec<_, _>, kind| { blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false)) }; - block(&mut blocks, TerminatorKind::Goto { target: return_block }); + if ty.is_some() { + block(&mut blocks, TerminatorKind::Goto { target: return_block }); + } block(&mut blocks, TerminatorKind::Return); let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty)); let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); + let Some(ty) = ty else { + return body; + }; + let dropee_ptr = Place::from(Local::arg(0)); - if ty.is_some() { + if let ty::Array(ety, _len) = *ty.kind() { + // Don't write out the elaboration for each array type. + // Instead, just delegate to the slice version. + let slice_ty = Ty::new_slice(tcx, ety); + let mut_slice_ty = Ty::new_ref(tcx, tcx.lifetimes.re_erased, slice_ty, ty::Mutability::Mut); + let erased_local = body.local_decls.push(LocalDecl::new(mut_slice_ty, span)); + + let start = &mut body.basic_blocks_mut()[START_BLOCK]; + start.statements.push(Statement::new( + source_info, + StatementKind::Assign(Box::new(( + Place::from(erased_local), + Rvalue::Cast( + CastKind::PointerCoercion( + ty::adjustment::PointerCoercion::Unsize, + CoercionSource::Implicit, + ), + Operand::Move(dropee_ptr), + mut_slice_ty, + ), + ))), + )); + start.terminator = Some(Terminator { + source_info, + kind: TerminatorKind::Call { + func: Operand::function_handle(tcx, def_id, [ty::GenericArg::from(slice_ty)], span), + args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]), + destination: Place::from(RETURN_PLACE), + target: Some(return_block), + unwind: UnwindAction::Continue, + call_source: CallSource::Misc, + fn_span: span, + }, + }); + } else { let patch = { let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); let mut elaborator = DropShimElaborator { diff --git a/tests/codegen-llvm/array-drop-glue.rs b/tests/codegen-llvm/array-drop-glue.rs new file mode 100644 index 0000000000000..f8bea8f8bd4ac --- /dev/null +++ b/tests/codegen-llvm/array-drop-glue.rs @@ -0,0 +1,67 @@ +//@ revisions: RAW OPT +//@ compile-flags: -C opt-level=z -C panic=abort +//@[RAW] compile-flags: -C no-prepopulate-passes -Z inline-mir + +#![crate_type = "lib"] + +// Ensure all the different array drop_glue functions just delegate to the slice one, +// rather than emitting two loops in each of the three. + +// When this test was first written, the array drop glues came out in the +// seemingly-arbitrary order of 42, then 7, then 13, so to avoid potential +// fragility from that changing we don't check any particular order. + +// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]> +// RAW-NOT: inlinehint +// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> +// RAW-NEXT: noundef [[N]]) +// RAW: } + +// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]> +// RAW-NOT: inlinehint +// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> +// RAW-NEXT: noundef [[N]]) +// RAW: } + +// RAW: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; [[N:7|13|42]]]> +// RAW-NOT: inlinehint +// RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> +// RAW-NEXT: noundef [[N]]) +// RAW: } + +// CHECK-LABEL: ; core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> +// CHECK-NOT: inlinehint +// OPT: add nuw nsw {{.+}} 1 +// CHECK: } + +#[no_mangle] +// CHECK-LABEL: @drop_arrays +pub fn drop_arrays(x: [NeedsDrop; 7], y: [NeedsDrop; 13], z: [NeedsDrop; 42]) { + // I don't remember the parameter drop order, so write out the order the test expects. + + // RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 7]> + // OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> + // OPT-NEXT: noundef 7) + drop(x); + // RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 13]> + // OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> + // OPT-NEXT: noundef 13) + drop(y); + // RAW: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop; 42]> + // OPT: call core::ptr::drop_glue::<[array_drop_glue::NeedsDrop]> + // OPT-NEXT: noundef 42) + drop(z); +} + +struct NeedsDrop(u32); + +impl Drop for NeedsDrop { + #[inline] + fn drop(&mut self) { + do_the_drop(self); + } +} + +unsafe extern "Rust" { + safe fn do_the_drop(_: &mut NeedsDrop); +} diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String;42].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String;42].AddMovesForPackedDrops.before.mir index 66591dcc91df2..1d4b0f033e0be 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String;42].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_glue.[String;42].AddMovesForPackedDrops.before.mir @@ -2,62 +2,14 @@ fn std::ptr::drop_glue(_1: &mut [String; 42]) -> () { let mut _0: (); - let mut _2: *mut [std::string::String; 42]; - let mut _3: *mut [std::string::String]; - 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 _2: &mut [std::string::String]; bb0: { - goto -> bb9; + _2 = move _1 as &mut [std::string::String] (PointerCoercion(Unsize, Implicit)); + _0 = std::ptr::drop_glue::<[String]>(move _2) -> [return: bb1, unwind continue]; } bb1: { return; } - - bb2 (cleanup): { - resume; - } - - bb3 (cleanup): { - _6 = &raw mut (*_3)[_5]; - _5 = Add(move _5, const 1_usize); - drop((*_6)) -> [return: bb4, unwind terminate(cleanup)]; - } - - bb4 (cleanup): { - _7 = Eq(copy _5, copy _4); - switchInt(move _7) -> [0: bb3, otherwise: bb2]; - } - - bb5: { - _8 = &raw mut (*_3)[_5]; - _5 = Add(move _5, const 1_usize); - drop((*_8)) -> [return: bb6, unwind: bb4]; - } - - bb6: { - _9 = Eq(copy _5, copy _4); - switchInt(move _9) -> [0: bb5, otherwise: bb1]; - } - - bb7: { - _4 = PtrMetadata(copy _3); - _5 = const 0_usize; - goto -> bb6; - } - - bb8: { - goto -> bb7; - } - - bb9: { - _2 = &raw mut (*_1); - _3 = move _2 as *mut [std::string::String] (PointerCoercion(Unsize, Implicit)); - goto -> bb8; - } }