From 9c921dc29526f9acb0c4652ea0ad50ca6587c7ef Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 17 Feb 2026 19:50:27 -0800 Subject: [PATCH 1/3] Add a `layout_of_val` intrinsic to get the `Layout` directly --- .../rustc_hir_analysis/src/check/intrinsic.rs | 3 + compiler/rustc_middle/src/ty/context.rs | 6 ++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/alloc/layout.rs | 23 ++++-- library/core/src/intrinsics/mod.rs | 21 +++++ ...rop_bytes.PreCodegen.after.panic-abort.mir | 81 ++++++++++--------- ...op_bytes.PreCodegen.after.panic-unwind.mir | 81 ++++++++++--------- ...p_generic.PreCodegen.after.panic-abort.mir | 79 +++++++++--------- ..._generic.PreCodegen.after.panic-unwind.mir | 79 +++++++++--------- .../mir-opt/pre-codegen/drop_box_of_sized.rs | 9 ++- ...ace.PreCodegen.after.32bit.panic-abort.mir | 70 +++++++--------- ...ce.PreCodegen.after.32bit.panic-unwind.mir | 70 +++++++--------- ...ace.PreCodegen.after.64bit.panic-abort.mir | 70 +++++++--------- ...ce.PreCodegen.after.64bit.panic-unwind.mir | 70 +++++++--------- tests/mir-opt/pre-codegen/drop_boxed_slice.rs | 5 +- ...ated_loop.PreCodegen.after.panic-abort.mir | 36 +++++---- ...ward_loop.PreCodegen.after.panic-abort.mir | 29 +++---- ...ange_loop.PreCodegen.after.panic-abort.mir | 6 ++ ...erse_loop.PreCodegen.after.panic-abort.mir | 28 +++---- ..._is_empty.PreCodegen.after.panic-abort.mir | 12 +-- ...next_back.PreCodegen.after.panic-abort.mir | 16 ++-- ...iter_next.PreCodegen.after.panic-abort.mir | 44 +++++----- 22 files changed, 432 insertions(+), 407 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 7d606439cedc3..32bbae1f67530 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -294,6 +294,9 @@ pub(crate) fn check_intrinsic_type( sym::size_of_val | sym::align_of_val => { (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } + sym::layout_of_val => { + (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.ty_alloc_layout(span)) + } sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2e9708483a85b..bb06257714d21 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1038,6 +1038,12 @@ impl<'tcx> TyCtxt<'tcx> { self.type_of(ordering_enum).no_bound_vars().unwrap() } + /// Gets a `Ty` representing the [`LangItem::AllocLayout`] + pub fn ty_alloc_layout(self, span: Span) -> Ty<'tcx> { + let layout_did = self.require_lang_item(hir::LangItem::AllocLayout, span); + self.type_of(layout_did).no_bound_vars().unwrap() + } + /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to /// compare against another `DefId`, since `is_diagnostic_item` is cheaper. pub fn get_diagnostic_item(self, name: Symbol) -> Option { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index caeb923c18f78..41a81a74c0a90 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1141,6 +1141,7 @@ symbols! { large_assignments, last, lateout, + layout_of_val, lazy_normalization_consts, lazy_type_alias, le, diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 66f5310db8310..2a69f46f0a3e6 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -5,7 +5,7 @@ // Your performance intuition is useless. Run perf. use crate::error::Error; -use crate::intrinsics::{unchecked_add, unchecked_mul, unchecked_sub}; +use crate::intrinsics::{self, unchecked_add, unchecked_mul, unchecked_sub}; use crate::mem::{Alignment, SizedTypeProperties}; use crate::ptr::NonNull; use crate::{assert_unsafe_precondition, fmt, mem}; @@ -210,14 +210,23 @@ impl Layout { /// Produces layout describing a record that could be used to /// allocate backing structure for `T` (which could be a trait /// or other unsized type like a slice). + /// + /// # Examples + /// + /// ``` + /// use std::alloc::Layout; + /// + /// let array = [1_u8, 2, 3]; + /// assert_eq!(Layout::for_value::<[u8]>(&array), Layout::from_size_align(3, 1).unwrap()); + /// ``` #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")] #[must_use] #[inline] pub const fn for_value(t: &T) -> Self { - let (size, alignment) = (size_of_val(t), Alignment::of_val(t)); - // SAFETY: see rationale in `new` for why this is using the unsafe variant - unsafe { Layout::from_size_alignment_unchecked(size, alignment) } + // SAFETY: val is a reference, so if it's to a DST it has valid metadata. + // (And if `T` is sized there's no requirements on the pointer.) + unsafe { Layout::for_value_raw(t) } } /// Produces layout describing a record that could be used to @@ -250,11 +259,9 @@ impl Layout { #[unstable(feature = "layout_for_ptr", issue = "69835")] #[must_use] #[inline] - pub const unsafe fn for_value_raw(t: *const T) -> Self { + pub const unsafe fn for_value_raw(ptr: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller - let (size, alignment) = unsafe { (mem::size_of_val_raw(t), Alignment::of_val_raw(t)) }; - // SAFETY: see rationale in `new` for why this is using the unsafe variant - unsafe { Layout::from_size_alignment_unchecked(size, alignment) } + unsafe { intrinsics::layout_of_val(ptr) } } /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index c71085ef9f97d..9c0bdd80f51bc 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -53,6 +53,7 @@ issue = "none" )] +use crate::alloc::Layout; use crate::ffi::{VaArgSafe, VaList}; use crate::marker::{ConstParamTy, DiscriminantKind, PointeeSized, Tuple}; use crate::{mem, ptr}; @@ -2887,6 +2888,26 @@ pub const fn type_id_vtable( ) } +/// The size and alignment of the referenced value in bytes. +/// +/// The stabilized version of this intrinsic is [`Layout::for_value_raw`]. +/// +/// # Safety +/// +/// See [`Layout::for_value_raw`] for safety conditions. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +// This adds no semantics or UB atop just calling `size_of_val`+`align_of_val`. +#[miri::intrinsic_fallback_is_spec] +pub const unsafe fn layout_of_val(ptr: *const T) -> Layout { + // SAFETY: we pass along the prerequisites of these functions to the caller + let (size, align) = unsafe { (size_of_val(ptr), align_of_val(ptr)) }; + // SAFETY: The size and alignment of a valid allocation (or type) + // always meet the requirements of `Layout`. + unsafe { Layout::from_size_align_unchecked(size, align) } +} + /// Compute the type information of a concrete type. /// It can only be called at compile time, the backends do /// not implement it. diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir index 7d45c16bb4dd7..5f26ecc817e2c 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir @@ -6,31 +6,35 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box<[u8; 1024]>))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull<[u8; 1024]>; - let _4: (); + let mut _3: *const [u8; 1024]; + let mut _5: usize; + let _8: (); scope 3 { + let _4: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { - let mut _3: std::ptr::NonNull; - scope 19 (inlined NonNull::<[u8; 1024]>::cast::) { - scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) { + scope 9 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { + let mut _6: std::ptr::NonNull; + scope 10 (inlined NonNull::<[u8; 1024]>::cast::) { + scope 11 (inlined NonNull::<[u8; 1024]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _7: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -42,40 +46,43 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[u8; 1024]>) { - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[u8; 1024]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[u8; 1024]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[u8; 1024]>) { - } - } } } } } bb0: { - StorageLive(_3); + StorageLive(_6); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>); - _3 = copy _2 as std::ptr::NonNull (Transmute); - _4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::mem::Alignment {{ _inner_repr_trick: mem::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable]; + StorageLive(_4); + StorageLive(_3); + _3 = copy _2 as *const [u8; 1024] (Transmute); + _4 = layout_of_val::<[u8; 1024]>(move _3) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_2); StorageDead(_3); + _5 = copy (_4.0: usize); + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; + } + + bb2: { + _6 = copy _2 as std::ptr::NonNull (Transmute); + StorageLive(_7); + _7 = copy (_4.1: std::mem::Alignment); + _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_7); + goto -> bb4; + } + + bb4: { + StorageDead(_4); + StorageDead(_2); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir index 7d45c16bb4dd7..5f26ecc817e2c 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir @@ -6,31 +6,35 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box<[u8; 1024]>))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull<[u8; 1024]>; - let _4: (); + let mut _3: *const [u8; 1024]; + let mut _5: usize; + let _8: (); scope 3 { + let _4: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { - let mut _3: std::ptr::NonNull; - scope 19 (inlined NonNull::<[u8; 1024]>::cast::) { - scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) { + scope 9 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { + let mut _6: std::ptr::NonNull; + scope 10 (inlined NonNull::<[u8; 1024]>::cast::) { + scope 11 (inlined NonNull::<[u8; 1024]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _7: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -42,40 +46,43 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[u8; 1024]>) { - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[u8; 1024]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[u8; 1024]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[u8; 1024]>) { - } - } } } } } bb0: { - StorageLive(_3); + StorageLive(_6); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>); - _3 = copy _2 as std::ptr::NonNull (Transmute); - _4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::mem::Alignment {{ _inner_repr_trick: mem::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable]; + StorageLive(_4); + StorageLive(_3); + _3 = copy _2 as *const [u8; 1024] (Transmute); + _4 = layout_of_val::<[u8; 1024]>(move _3) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_2); StorageDead(_3); + _5 = copy (_4.0: usize); + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; + } + + bb2: { + _6 = copy _2 as std::ptr::NonNull (Transmute); + StorageLive(_7); + _7 = copy (_4.1: std::mem::Alignment); + _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_7); + goto -> bb4; + } + + bb4: { + StorageDead(_4); + StorageDead(_2); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir index 4778b4ed7db71..413c23487df43 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir @@ -6,31 +6,35 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let _5: (); + let mut _3: *const T; + let mut _5: usize; + let _8: (); scope 3 { + let _4: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::::cast::) { - let mut _4: std::ptr::NonNull; - scope 19 (inlined NonNull::::cast::) { - scope 20 (inlined NonNull::::as_ptr) { + scope 9 (inlined std::ptr::Unique::::cast::) { + let mut _6: std::ptr::NonNull; + scope 10 (inlined NonNull::::cast::) { + scope 11 (inlined NonNull::::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _7: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -42,50 +46,43 @@ fn drop_generic(_1: *mut Box) -> () { } } scope 7 (inlined Layout::for_value_raw::) { - let mut _3: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::) { - } - } } } } } bb0: { - StorageLive(_4); + StorageLive(_6); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = const ::ALIGN as std::mem::Alignment (Transmute); - switchInt(const ::SIZE) -> [0: bb3, otherwise: bb1]; + StorageLive(_4); + StorageLive(_3); + _3 = copy _2 as *const T (Transmute); + _4 = layout_of_val::(move _3) -> [return: bb1, unwind unreachable]; } bb1: { - _4 = copy _2 as std::ptr::NonNull (Transmute); - switchInt(const ::SIZE) -> [0: bb3, otherwise: bb2]; + StorageDead(_3); + _5 = copy (_4.0: usize); + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - _5 = alloc::alloc::__rust_dealloc(move _4, const ::SIZE, move _3) -> [return: bb3, unwind unreachable]; + _6 = copy _2 as std::ptr::NonNull (Transmute); + StorageLive(_7); + _7 = copy (_4.1: std::mem::Alignment); + _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_2); + StorageDead(_7); + goto -> bb4; + } + + bb4: { StorageDead(_4); + StorageDead(_2); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir index 4778b4ed7db71..413c23487df43 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir @@ -6,31 +6,35 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let _5: (); + let mut _3: *const T; + let mut _5: usize; + let _8: (); scope 3 { + let _4: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::::cast::) { - let mut _4: std::ptr::NonNull; - scope 19 (inlined NonNull::::cast::) { - scope 20 (inlined NonNull::::as_ptr) { + scope 9 (inlined std::ptr::Unique::::cast::) { + let mut _6: std::ptr::NonNull; + scope 10 (inlined NonNull::::cast::) { + scope 11 (inlined NonNull::::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _7: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -42,50 +46,43 @@ fn drop_generic(_1: *mut Box) -> () { } } scope 7 (inlined Layout::for_value_raw::) { - let mut _3: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::) { - } - } } } } } bb0: { - StorageLive(_4); + StorageLive(_6); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = const ::ALIGN as std::mem::Alignment (Transmute); - switchInt(const ::SIZE) -> [0: bb3, otherwise: bb1]; + StorageLive(_4); + StorageLive(_3); + _3 = copy _2 as *const T (Transmute); + _4 = layout_of_val::(move _3) -> [return: bb1, unwind unreachable]; } bb1: { - _4 = copy _2 as std::ptr::NonNull (Transmute); - switchInt(const ::SIZE) -> [0: bb3, otherwise: bb2]; + StorageDead(_3); + _5 = copy (_4.0: usize); + switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { - _5 = alloc::alloc::__rust_dealloc(move _4, const ::SIZE, move _3) -> [return: bb3, unwind unreachable]; + _6 = copy _2 as std::ptr::NonNull (Transmute); + StorageLive(_7); + _7 = copy (_4.1: std::mem::Alignment); + _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_2); + StorageDead(_7); + goto -> bb4; + } + + bb4: { StorageDead(_4); + StorageDead(_2); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs index 3d340eb103a7b..2687106e19dfa 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs @@ -6,14 +6,17 @@ // EMIT_MIR drop_box_of_sized.drop_generic.PreCodegen.after.mir pub unsafe fn drop_generic(x: *mut Box) { // CHECK-LABEL: fn drop_generic - // CHECK: [[ALIGNMENT:_.+]] = const ::ALIGN as std::mem::Alignment (Transmute) - // CHECK: alloc::alloc::__rust_dealloc({{.+}}, const ::SIZE, move [[ALIGNMENT]]) + // CHECK: [[LAYOUT:_.+]] = layout_of_val:: + // CHECK: [[SIZE:_.+]] = copy ([[LAYOUT]].0: usize); + // CHECK: [[ALIGNMENT:_.+]] = copy ([[LAYOUT]].1: std::mem::Alignment); + // CHECK: alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[ALIGNMENT]]) std::ptr::drop_in_place(x) } // EMIT_MIR drop_box_of_sized.drop_bytes.PreCodegen.after.mir pub unsafe fn drop_bytes(x: *mut Box<[u8; 1024]>) { // CHECK-LABEL: fn drop_bytes - // CHECK: alloc::alloc::__rust_dealloc({{.+}}, const 1024_usize, {{.+}}Align1Shl0 {{.+}}) + // CHECK: layout_of_val::<[u8; 1024]> + // CHECK: alloc::alloc::__rust_dealloc std::ptr::drop_in_place(x) } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index 1c5a9bca84d40..fb14e6d04a6c5 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -8,32 +8,35 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let mut _6: usize; + let _10: (); scope 3 { + let _5: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[T]>::cast::) { + scope 9 (inlined std::ptr::Unique::<[T]>::cast::) { let mut _8: std::ptr::NonNull; - scope 19 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _7: *mut u8; - scope 20 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _9: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -45,26 +48,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[T]>) { - let mut _5: usize; - let mut _6: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[T]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[T]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[T]>) { - } - } } } } @@ -72,20 +55,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { bb0: { StorageLive(_3); - StorageLive(_5); StorageLive(_8); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_5); StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; + _5 = layout_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = const ::ALIGN as std::mem::Alignment (Transmute); StorageDead(_4); - switchInt(copy _5) -> [0: bb3, otherwise: bb2]; + _6 = copy (_5.0: usize); + switchInt(copy _6) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -93,13 +76,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _7 = copy _3 as *mut u8 (PtrToPtr); _8 = copy _7 as std::ptr::NonNull (Transmute); StorageDead(_7); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable]; + StorageLive(_9); + _9 = copy (_5.1: std::mem::Alignment); + _10 = alloc::alloc::__rust_dealloc(move _8, move _6, move _9) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_9); + goto -> bb4; + } + + bb4: { + StorageDead(_5); StorageDead(_2); StorageDead(_8); - StorageDead(_5); StorageDead(_3); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index 1c5a9bca84d40..fb14e6d04a6c5 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -8,32 +8,35 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let mut _6: usize; + let _10: (); scope 3 { + let _5: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[T]>::cast::) { + scope 9 (inlined std::ptr::Unique::<[T]>::cast::) { let mut _8: std::ptr::NonNull; - scope 19 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _7: *mut u8; - scope 20 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _9: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -45,26 +48,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[T]>) { - let mut _5: usize; - let mut _6: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[T]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[T]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[T]>) { - } - } } } } @@ -72,20 +55,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { bb0: { StorageLive(_3); - StorageLive(_5); StorageLive(_8); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_5); StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; + _5 = layout_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = const ::ALIGN as std::mem::Alignment (Transmute); StorageDead(_4); - switchInt(copy _5) -> [0: bb3, otherwise: bb2]; + _6 = copy (_5.0: usize); + switchInt(copy _6) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -93,13 +76,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _7 = copy _3 as *mut u8 (PtrToPtr); _8 = copy _7 as std::ptr::NonNull (Transmute); StorageDead(_7); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable]; + StorageLive(_9); + _9 = copy (_5.1: std::mem::Alignment); + _10 = alloc::alloc::__rust_dealloc(move _8, move _6, move _9) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_9); + goto -> bb4; + } + + bb4: { + StorageDead(_5); StorageDead(_2); StorageDead(_8); - StorageDead(_5); StorageDead(_3); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index 1c5a9bca84d40..fb14e6d04a6c5 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -8,32 +8,35 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let mut _6: usize; + let _10: (); scope 3 { + let _5: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[T]>::cast::) { + scope 9 (inlined std::ptr::Unique::<[T]>::cast::) { let mut _8: std::ptr::NonNull; - scope 19 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _7: *mut u8; - scope 20 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _9: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -45,26 +48,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[T]>) { - let mut _5: usize; - let mut _6: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[T]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[T]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[T]>) { - } - } } } } @@ -72,20 +55,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { bb0: { StorageLive(_3); - StorageLive(_5); StorageLive(_8); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_5); StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; + _5 = layout_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = const ::ALIGN as std::mem::Alignment (Transmute); StorageDead(_4); - switchInt(copy _5) -> [0: bb3, otherwise: bb2]; + _6 = copy (_5.0: usize); + switchInt(copy _6) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -93,13 +76,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _7 = copy _3 as *mut u8 (PtrToPtr); _8 = copy _7 as std::ptr::NonNull (Transmute); StorageDead(_7); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable]; + StorageLive(_9); + _9 = copy (_5.1: std::mem::Alignment); + _10 = alloc::alloc::__rust_dealloc(move _8, move _6, move _9) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_9); + goto -> bb4; + } + + bb4: { + StorageDead(_5); StorageDead(_2); StorageDead(_8); - StorageDead(_5); StorageDead(_3); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index 1c5a9bca84d40..fb14e6d04a6c5 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -8,32 +8,35 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _9: (); + let mut _6: usize; + let _10: (); scope 3 { + let _5: std::alloc::Layout; scope 4 { - scope 17 (inlined Layout::size) { + scope 8 (inlined Layout::size) { } - scope 18 (inlined std::ptr::Unique::<[T]>::cast::) { + scope 9 (inlined std::ptr::Unique::<[T]>::cast::) { let mut _8: std::ptr::NonNull; - scope 19 (inlined NonNull::<[T]>::cast::) { + scope 10 (inlined NonNull::<[T]>::cast::) { let mut _7: *mut u8; - scope 20 (inlined NonNull::<[T]>::as_ptr) { + scope 11 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 21 (inlined as From>>::from) { - scope 22 (inlined std::ptr::Unique::::as_non_null_ptr) { + scope 12 (inlined as From>>::from) { + scope 13 (inlined std::ptr::Unique::::as_non_null_ptr) { } } - scope 23 (inlined ::deallocate) { - scope 24 (inlined std::alloc::Global::deallocate_impl) { - scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - scope 26 (inlined Layout::size) { + scope 14 (inlined ::deallocate) { + scope 15 (inlined std::alloc::Global::deallocate_impl) { + scope 16 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 17 (inlined Layout::size) { } - scope 27 (inlined alloc::alloc::dealloc_nonnull) { - scope 28 (inlined Layout::size) { + scope 18 (inlined alloc::alloc::dealloc_nonnull) { + let mut _9: std::mem::Alignment; + scope 19 (inlined Layout::size) { } - scope 29 (inlined Layout::alignment) { + scope 20 (inlined Layout::alignment) { } } } @@ -45,26 +48,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { } } scope 7 (inlined Layout::for_value_raw::<[T]>) { - let mut _5: usize; - let mut _6: std::mem::Alignment; - scope 8 { - scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) { - } - } - scope 9 (inlined size_of_val_raw::<[T]>) { - } - scope 10 (inlined std::mem::Alignment::of_val_raw::<[T]>) { - scope 11 { - scope 13 (inlined #[track_caller] std::mem::Alignment::new_unchecked) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - } - scope 12 (inlined align_of_val_raw::<[T]>) { - } - } } } } @@ -72,20 +55,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { bb0: { StorageLive(_3); - StorageLive(_5); StorageLive(_8); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[T]>).0: std::ptr::NonNull<[T]>); + StorageLive(_5); StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; + _5 = layout_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } bb1: { - _6 = const ::ALIGN as std::mem::Alignment (Transmute); StorageDead(_4); - switchInt(copy _5) -> [0: bb3, otherwise: bb2]; + _6 = copy (_5.0: usize); + switchInt(copy _6) -> [0: bb4, otherwise: bb2]; } bb2: { @@ -93,13 +76,20 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _7 = copy _3 as *mut u8 (PtrToPtr); _8 = copy _7 as std::ptr::NonNull (Transmute); StorageDead(_7); - _9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable]; + StorageLive(_9); + _9 = copy (_5.1: std::mem::Alignment); + _10 = alloc::alloc::__rust_dealloc(move _8, move _6, move _9) -> [return: bb3, unwind unreachable]; } bb3: { + StorageDead(_9); + goto -> bb4; + } + + bb4: { + StorageDead(_5); StorageDead(_2); StorageDead(_8); - StorageDead(_5); StorageDead(_3); return; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index 8f28bc712b4b0..e2fc56730abd1 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -8,8 +8,9 @@ pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { // CHECK-LABEL: fn generic_in_place(_1: *mut Box<[T]>) // CHECK: (inlined as Drop>::drop) - // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> - // CHECK: [[ALIGN:_.+]] = const ::ALIGN as std::mem::Alignment (Transmute); + // CHECK: [[LAYOUT:_.+]] = layout_of_val::<[T]> + // CHECK: [[SIZE:_.+]] = copy ([[LAYOUT]].0: usize); + // CHECK: [[ALIGN:_.+]] = copy ([[LAYOUT]].1: std::mem::Alignment); // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[ALIGN]]) -> std::ptr::drop_in_place(ptr) } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 6d3519846023a..575659e6d0ded 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -180,23 +180,20 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { StorageLive(_32); - StorageLive(_29); StorageLive(_30); StorageLive(_27); - StorageLive(_13); - StorageLive(_14); - StorageLive(_20); StorageLive(_24); - StorageLive(_15); - StorageLive(_26); StorageLive(_16); + StorageLive(_13); _13 = copy _8; + StorageLive(_14); _14 = copy _11; switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb8]; } bb5: { StorageLive(_18); + StorageLive(_15); _15 = copy _14 as std::ptr::NonNull (Transmute); _16 = copy _13 as *mut T (Transmute); StorageLive(_17); @@ -207,6 +204,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb6: { + StorageDead(_15); StorageDead(_18); StorageLive(_19); _19 = Offset(copy _16, const 1_usize); @@ -216,27 +214,27 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb7: { + StorageDead(_15); StorageDead(_18); goto -> bb10; } bb8: { + StorageLive(_20); _20 = copy _14 as usize (Transmute); switchInt(copy _20) -> [0: bb9, otherwise: bb12]; } bb9: { + StorageDead(_20); goto -> bb10; } bb10: { - StorageDead(_16); - StorageDead(_26); - StorageDead(_15); - StorageDead(_24); - StorageDead(_20); StorageDead(_14); StorageDead(_13); + StorageDead(_16); + StorageDead(_24); StorageDead(_27); StorageLive(_21); StorageLive(_23); @@ -246,7 +244,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_23); StorageDead(_21); StorageDead(_30); - StorageDead(_29); StorageDead(_32); StorageDead(_12); drop(_2) -> [return: bb11, unwind unreachable]; @@ -259,24 +256,25 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb12: { _24 = SubUnchecked(copy _20, const 1_usize); _11 = copy _24 as *const T (Transmute); + StorageDead(_20); goto -> bb13; } bb13: { + StorageLive(_26); StorageLive(_25); _25 = copy _13 as *const T (Transmute); _26 = &(*_25); StorageDead(_25); _27 = Option::<&T>::Some(copy _26); - StorageDead(_16); StorageDead(_26); - StorageDead(_15); - StorageDead(_24); - StorageDead(_20); StorageDead(_14); StorageDead(_13); + StorageDead(_16); + StorageDead(_24); _28 = copy ((_27 as Some).0: &T); StorageDead(_27); + StorageLive(_29); _29 = copy _12; _30 = AddWithOverflow(copy _12, const 1_usize); assert(!move (_30.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _12, const 1_usize) -> [success: bb14, unwind unreachable]; @@ -288,9 +286,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _31 = (copy _29, copy _28); _32 = Option::<(usize, &T)>::Some(move _31); StorageDead(_31); - StorageDead(_30); StorageDead(_29); + StorageDead(_30); + StorageLive(_33); _33 = copy (((_32 as Some).0: (usize, &T)).0: usize); + StorageLive(_34); _34 = copy (((_32 as Some).0: (usize, &T)).1: &T); StorageLive(_35); _35 = &_2; @@ -302,6 +302,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb15: { StorageDead(_36); StorageDead(_35); + StorageDead(_34); + StorageDead(_33); StorageDead(_32); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 6e27d02641687..f41dbd567003e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -142,20 +142,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb4: { StorageLive(_23); - StorageLive(_12); - StorageLive(_13); - StorageLive(_19); StorageLive(_20); - StorageLive(_14); - StorageLive(_22); StorageLive(_15); + StorageLive(_12); _12 = copy _8; + StorageLive(_13); _13 = copy _11; switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb8]; } bb5: { StorageLive(_17); + StorageLive(_14); _14 = copy _13 as std::ptr::NonNull (Transmute); _15 = copy _12 as *mut T (Transmute); StorageLive(_16); @@ -166,6 +164,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb6: { + StorageDead(_14); StorageDead(_17); StorageLive(_18); _18 = Offset(copy _15, const 1_usize); @@ -175,27 +174,27 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb7: { + StorageDead(_14); StorageDead(_17); goto -> bb10; } bb8: { + StorageLive(_19); _19 = copy _13 as usize (Transmute); switchInt(copy _19) -> [0: bb9, otherwise: bb12]; } bb9: { + StorageDead(_19); goto -> bb10; } bb10: { - StorageDead(_15); - StorageDead(_22); - StorageDead(_14); - StorageDead(_20); - StorageDead(_19); StorageDead(_13); StorageDead(_12); + StorageDead(_15); + StorageDead(_20); StorageDead(_23); drop(_2) -> [return: bb11, unwind unreachable]; } @@ -207,22 +206,23 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb12: { _20 = SubUnchecked(copy _19, const 1_usize); _11 = copy _20 as *const T (Transmute); + StorageDead(_19); goto -> bb13; } bb13: { + StorageLive(_22); StorageLive(_21); _21 = copy _12 as *const T (Transmute); _22 = &(*_21); StorageDead(_21); _23 = Option::<&T>::Some(copy _22); - StorageDead(_15); StorageDead(_22); - StorageDead(_14); - StorageDead(_20); - StorageDead(_19); StorageDead(_13); StorageDead(_12); + StorageDead(_15); + StorageDead(_20); + StorageLive(_24); _24 = copy ((_23 as Some).0: &T); StorageLive(_25); _25 = &_2; @@ -234,6 +234,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb14: { StorageDead(_26); StorageDead(_25); + StorageDead(_24); StorageDead(_23); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 145375990710b..43e2d24674d96 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -72,11 +72,15 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb4: { + StorageLive(_7); _7 = copy _4; _4 = AddUnchecked(copy _7, const 1_usize); _8 = Option::::Some(copy _7); + StorageDead(_7); StorageDead(_6); + StorageLive(_9); _9 = copy ((_8 as Some).0: usize); + StorageLive(_11); _10 = Lt(copy _9, copy _3); assert(move _10, "index out of bounds: the length is {} but the index is {}", copy _3, copy _9) -> [success: bb5, unwind unreachable]; } @@ -93,6 +97,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb6: { StorageDead(_13); StorageDead(_12); + StorageDead(_11); + StorageDead(_9); StorageDead(_8); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index ac2b0f23b9f90..1f96a8e14a5b2 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -132,10 +132,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb0: { StorageLive(_12); - StorageLive(_3); - StorageLive(_8); StorageLive(_11); + StorageLive(_3); _3 = PtrMetadata(copy _1); + StorageLive(_8); StorageLive(_5); StorageLive(_4); _4 = &raw const (*_1); @@ -170,9 +170,9 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { _12 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: copy _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); StorageDead(_8); StorageDead(_3); + StorageDead(_11); _13 = Rev::> { iter: copy _12 }; StorageDead(_12); StorageLive(_14); @@ -182,15 +182,12 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb4: { StorageLive(_35); - StorageLive(_22); - StorageLive(_21); - StorageLive(_16); - StorageLive(_34); StorageLive(_20); switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb6]; } bb5: { + StorageLive(_16); StorageLive(_15); _15 = copy ((_14.0: std::slice::Iter<'_, T>).1: *const T); _16 = copy _15 as std::ptr::NonNull (Transmute); @@ -205,13 +202,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _20 = Eq(copy _18, copy _19); StorageDead(_19); StorageDead(_18); + StorageDead(_16); goto -> bb7; } bb6: { + StorageLive(_22); + StorageLive(_21); _21 = copy ((_14.0: std::slice::Iter<'_, T>).1: *const T); _22 = copy _21 as usize (Transmute); + StorageDead(_21); _20 = Eq(copy _22, const 0_usize); + StorageDead(_22); goto -> bb7; } @@ -220,6 +222,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { + StorageLive(_34); StorageLive(_28); StorageLive(_30); StorageLive(_24); @@ -279,11 +282,9 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_33); StorageDead(_28); _35 = Option::<&T>::Some(copy _34); - StorageDead(_20); StorageDead(_34); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); + StorageDead(_20); + StorageLive(_36); _36 = copy ((_35 as Some).0: &T); StorageLive(_37); _37 = &_2; @@ -295,16 +296,13 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb14: { StorageDead(_38); StorageDead(_37); + StorageDead(_36); StorageDead(_35); goto -> bb4; } bb15: { StorageDead(_20); - StorageDead(_34); - StorageDead(_16); - StorageDead(_21); - StorageDead(_22); StorageDead(_35); StorageDead(_14); drop(_2) -> [return: bb16, unwind unreachable]; diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir index 9b510380b10b2..04f78fa3e7e3b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir @@ -30,13 +30,11 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { } bb0: { - StorageLive(_8); - StorageLive(_7); - StorageLive(_3); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_3); StorageLive(_2); _2 = copy ((*_1).1: *const T); _3 = copy _2 as std::ptr::NonNull (Transmute); @@ -51,20 +49,22 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { _0 = Eq(copy _5, copy _6); StorageDead(_6); StorageDead(_5); + StorageDead(_3); goto -> bb3; } bb2: { + StorageLive(_8); + StorageLive(_7); _7 = copy ((*_1).1: *const T); _8 = copy _7 as usize (Transmute); + StorageDead(_7); _0 = Eq(copy _8, const 0_usize); + StorageDead(_8); goto -> bb3; } bb3: { - StorageDead(_3); - StorageDead(_7); - StorageDead(_8); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir index 99f793ea67249..94471cbb157c5 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir @@ -73,16 +73,13 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut } bb0: { - StorageLive(_9); - StorageLive(_8); - StorageLive(_3); StorageLive(_2); - StorageLive(_21); StorageLive(_7); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_3); _2 = copy ((*_1).1: *mut T); _3 = copy _2 as std::ptr::NonNull (Transmute); StorageLive(_5); @@ -95,13 +92,18 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut _7 = Eq(copy _5, copy _6); StorageDead(_6); StorageDead(_5); + StorageDead(_3); goto -> bb3; } bb2: { + StorageLive(_9); + StorageLive(_8); _8 = copy ((*_1).1: *mut T); _9 = copy _8 as usize (Transmute); + StorageDead(_8); _7 = Eq(copy _9, const 0_usize); + StorageDead(_9); goto -> bb3; } @@ -110,6 +112,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut } bb4: { + StorageLive(_21); StorageLive(_15); StorageLive(_17); StorageLive(_11); @@ -169,6 +172,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut StorageDead(_20); StorageDead(_15); _0 = Option::<&mut T>::Some(copy _21); + StorageDead(_21); goto -> bb11; } @@ -179,11 +183,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut bb11: { StorageDead(_7); - StorageDead(_21); StorageDead(_2); - StorageDead(_3); - StorageDead(_8); - StorageDead(_9); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir index 5711b556203ac..70e21435cc18f 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir @@ -53,20 +53,18 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { } bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_10); StorageLive(_11); - StorageLive(_4); - StorageLive(_13); StorageLive(_5); + StorageLive(_2); _2 = copy ((*_1).0: std::ptr::NonNull); + StorageLive(_3); _3 = copy ((*_1).1: *const T); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb4]; } bb1: { StorageLive(_7); + StorageLive(_4); _4 = copy _3 as std::ptr::NonNull (Transmute); _5 = copy _2 as *mut T (Transmute); StorageLive(_6); @@ -77,6 +75,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { } bb2: { + StorageDead(_4); StorageDead(_7); StorageLive(_9); StorageLive(_8); @@ -85,48 +84,57 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { StorageDead(_8); ((*_1).0: std::ptr::NonNull) = move _9; StorageDead(_9); - goto -> bb7; + goto -> bb8; } bb3: { + StorageDead(_4); _0 = const {transmute(0x0000000000000000): Option<&T>}; StorageDead(_7); - goto -> bb8; + goto -> bb6; } bb4: { + StorageLive(_10); _10 = copy _3 as usize (Transmute); - switchInt(copy _10) -> [0: bb5, otherwise: bb6]; + switchInt(copy _10) -> [0: bb5, otherwise: bb7]; } bb5: { _0 = const {transmute(0x0000000000000000): Option<&T>}; - goto -> bb8; + StorageDead(_10); + goto -> bb6; } bb6: { + StorageDead(_3); + StorageDead(_2); + goto -> bb9; + } + + bb7: { _11 = SubUnchecked(copy _10, const 1_usize); ((*_1).1: *const T) = copy _11 as *const T (Transmute); - goto -> bb7; + StorageDead(_10); + goto -> bb8; } - bb7: { + bb8: { + StorageLive(_13); StorageLive(_12); _12 = copy _2 as *const T (Transmute); _13 = &(*_12); StorageDead(_12); _0 = Option::<&T>::Some(copy _13); - goto -> bb8; + StorageDead(_13); + StorageDead(_3); + StorageDead(_2); + goto -> bb9; } - bb8: { + bb9: { StorageDead(_5); - StorageDead(_13); - StorageDead(_4); StorageDead(_11); - StorageDead(_10); - StorageDead(_3); - StorageDead(_2); return; } } From ad49e9fb358f8f30cbd7e58e05a4e725645cb20c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 17 Feb 2026 21:49:37 -0800 Subject: [PATCH 2/3] Implement `layout_of_val` in `cg_ssa` It was already computing both anyway with `size_of_val::size_and_align_of_dst`, so we just need to return them both instead of ignoring one. --- compiler/rustc_codegen_llvm/src/lib.rs | 8 +- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 44 +++++++--- compiler/rustc_codegen_ssa/src/size_of_val.rs | 7 +- library/core/src/alloc/layout.rs | 27 +++++++ .../codegen-llvm/intrinsics/layout_of_val.rs | 81 +++++++++++++++++++ 5 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 tests/codegen-llvm/intrinsics/layout_of_val.rs diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 65c70c754918d..37059497ad754 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -319,8 +319,12 @@ impl CodegenBackend for LlvmCodegenBackend { } fn replaced_intrinsics(&self) -> Vec { - let mut will_not_use_fallback = - vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add]; + let mut will_not_use_fallback = vec![ + sym::unchecked_funnel_shl, + sym::unchecked_funnel_shr, + sym::carrying_mul_add, + sym::layout_of_val, + ]; if llvm_util::get_version() >= (22, 0, 0) { will_not_use_fallback.push(sym::carryless_mul); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index f4a5e8baa2a5f..0e3b5b88e8176 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,4 +1,4 @@ -use rustc_abi::{Align, WrappingRange}; +use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, WrappingRange}; use rustc_middle::mir::SourceInfo; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -7,7 +7,7 @@ use rustc_span::sym; use rustc_target::spec::Arch; use super::FunctionCx; -use super::operand::OperandRef; +use super::operand::{OperandRef, OperandRefBuilder}; use super::place::PlaceRef; use crate::common::{AtomicRmwBinOp, SynchronizationScope}; use crate::errors::InvalidMonomorphization; @@ -150,17 +150,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::va_start => bx.va_start(args[0].immediate()), sym::va_end => bx.va_end(args[0].immediate()), - sym::size_of_val => { + sym::size_of_val | sym::align_of_val | sym::layout_of_val => { let tp_ty = fn_args.type_at(0); let (_, meta) = args[0].val.pointer_parts(); - let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); - llsize - } - sym::align_of_val => { - let tp_ty = fn_args.type_at(0); - let (_, meta) = args[0].val.pointer_parts(); - let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); - llalign + let (llsize, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); + match name { + sym::size_of_val => llsize, + sym::align_of_val => llalign, + sym::layout_of_val => { + // The builder insulates us from in-memory order, but double-check declared order + debug_assert!({ + let layout_adt = result.layout.ty.ty_adt_def().unwrap(); + let layout_fields = layout_adt.variant(FIRST_VARIANT).fields.as_slice(); + if let [size, align] = &layout_fields.raw + && size.name == sym::size + && align.name == sym::align + { + true + } else { + false + } + }); + + let mut builder = OperandRefBuilder::<'_, Bx::Value>::new(result.layout); + builder.insert_imm(FieldIdx::from_u32(0), llsize); + builder.insert_imm(FieldIdx::from_u32(1), llalign); + let val = builder.build(bx.cx()).val; + // the match can only return a single `Bx::Value`, + // so we need to do the store and return. + val.store(bx, result); + return Ok(()); + } + _ => bug!(), + } } sym::vtable_size | sym::vtable_align => { let vtable = args[0].immediate(); diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 52ffc321cbb6f..eb5ac1bb2829c 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -159,7 +159,12 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Furthermore, `align >= unsized_align`, and therefore we only need to do: // let full_size = (unsized_offset_unadjusted + unsized_size).align_to(full_align); - let full_size = bx.add(unsized_offset_unadjusted, unsized_size); + // This is the size *before* rounding up, which cannot exceed the size *after* + // rounding up, which itself cannot exceed `isize::MAX`. Thus the addition + // itself cannot overflow `isize::MAX`, let alone `usize::MAX`. + // (The range attribute from loading the size from the vtable is enough to prove + // `nuw`, but not `nsw`, which we only know from Rust's layout rules.) + let full_size = bx.unchecked_suadd(unsized_offset_unadjusted, unsized_size); // Issue #27023: must add any necessary padding to `size` // (to make it a multiple of `align`) before returning it. diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 2a69f46f0a3e6..7fda6926b4f28 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -26,6 +26,9 @@ use crate::{assert_unsafe_precondition, fmt, mem}; /// requirements, or use the more lenient `Allocator` interface.) #[stable(feature = "alloc_layout", since = "1.28.0")] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +// BEWARE! The implementation of the `layout_of_val` intrinsic is coupled to the +// declared order of these fields. As a reminder, you'll also get a (debug-only) +// ICE if you change their names, though you can easily update that expectation. #[lang = "alloc_layout"] pub struct Layout { // size of the requested block of memory, measured in bytes. @@ -256,6 +259,30 @@ impl Layout { /// /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html + /// + /// # Examples + /// + /// ``` + /// #![feature(layout_for_ptr)] + /// + /// use std::alloc::Layout; + /// use std::ptr; + /// + /// let arbitrary = ptr::without_provenance::<[u16; 3]>(123456); + /// assert_eq!( + /// // SAFETY: for a sized pointee, the function is always sound. + /// unsafe { Layout::for_value_raw(arbitrary) }, + /// Layout::from_size_align(6, 2).unwrap(), + /// ); + /// + /// let slice = ptr::slice_from_raw_parts(arbitrary, 789); + /// assert_eq!( + /// // SAFETY: with a slice pointee, this is sound because the length + /// // is short enough that size in bytes doesn't overflow isize::MAX. + /// unsafe { Layout::for_value_raw(slice) }, + /// Layout::from_size_align(6 * 789, 2).unwrap(), + /// ); + /// ``` #[unstable(feature = "layout_for_ptr", issue = "69835")] #[must_use] #[inline] diff --git a/tests/codegen-llvm/intrinsics/layout_of_val.rs b/tests/codegen-llvm/intrinsics/layout_of_val.rs new file mode 100644 index 0000000000000..75fe4a19749ad --- /dev/null +++ b/tests/codegen-llvm/intrinsics/layout_of_val.rs @@ -0,0 +1,81 @@ +//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -Z inline-mir +//@ only-64bit (so I don't need to worry about usize) +//@ needs-deterministic-layouts + +// Note that the layout algorithm currently puts the align before the size, +// because the *type* for the size doesn't have a niche. This test may need +// to be updated if the in-memory field order of `Layout` ever changes. + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::alloc::Layout; +use std::intrinsics::layout_of_val; + +// CHECK-LABEL: @thin_metadata( +#[no_mangle] +pub unsafe fn thin_metadata(ptr: *const [u32; 2]) -> Layout { + // CHECK: [[LAYOUT:%.+]] = alloca [16 x i8], align 8 + // CHECK-NOT: load + // CHECK-NOT: store + // CHECK: store i64 4, ptr [[LAYOUT]], align 8 + // CHECK-NEXT: [[SIZEP:%.+]] = getelementptr inbounds i8, ptr [[LAYOUT]], i64 8 + // CHECK-NEXT: store i64 8, ptr [[SIZEP]], align 8 + // CHECK-NOT: store + layout_of_val(ptr) +} + +// CHECK-LABEL: @slice_metadata(ptr noundef %ptr.0, i64 noundef %ptr.1) +#[no_mangle] +pub unsafe fn slice_metadata(ptr: *const [u32]) -> Layout { + // CHECK: [[LAYOUT:%.+]] = alloca [16 x i8], align 8 + // CHECK-NOT: load + // CHECK-NOT: store + // CHECK: [[BYTES:%.+]] = mul nuw nsw i64 %ptr.1, 4 + // CHECK-NEXT: store i64 4, ptr [[LAYOUT]], align 8 + // CHECK-NEXT: [[SIZEP:%.+]] = getelementptr inbounds i8, ptr [[LAYOUT]], i64 8 + // CHECK-NEXT: store i64 [[BYTES]], ptr [[SIZEP]], align 8 + // CHECK-NOT: store + layout_of_val(ptr) +} + +pub struct WithTail([u32; 3], T); + +// CHECK-LABEL: @dst_metadata +// CHECK-SAME: (ptr noundef %ptr.0, ptr{{.+}}%ptr.1) +#[no_mangle] +pub unsafe fn dst_metadata(ptr: *const WithTail) -> Layout { + // CHECK: [[LAYOUT:%.+]] = alloca [16 x i8], align 8 + // CHECK-NOT: load + // CHECK-NOT: store + // CHECK: [[DST_SIZEP:%.+]] = getelementptr inbounds i8, ptr %ptr.1, i64 8 + // CHECK-NEXT: [[DST_SIZE:%.+]] = load i64, ptr [[DST_SIZEP]], align 8, + // CHECK-SAME: !range [[SIZE_RANGE:.+]], !invariant.load + // CHECK-NEXT: [[DST_ALIGNP:%.+]] = getelementptr inbounds i8, ptr %ptr.1, i64 16 + // CHECK-NEXT: [[DST_ALIGN:%.+]] = load i64, ptr [[DST_ALIGNP]], align 8, + // CHECK-SAME: !range [[ALIGN_RANGE:!.+]], !invariant.load + + // CHECK-NEXT: [[STRUCT_MORE:%.+]] = icmp ugt i64 4, [[DST_ALIGN]] + // CHECK-NEXT: [[ALIGN:%.+]] = select i1 [[STRUCT_MORE]], i64 4, i64 [[DST_ALIGN]] + + // CHECK-NEXT: [[MINSIZE:%.+]] = add nuw nsw i64 12, [[DST_SIZE]] + // CHECK-NEXT: [[ALIGN_M1:%.+]] = sub i64 [[ALIGN]], 1 + // CHECK-NEXT: [[MAXSIZE:%.+]] = add i64 [[MINSIZE]], [[ALIGN_M1]] + // CHECK-NEXT: [[ALIGN_NEG:%.+]] = sub i64 0, [[ALIGN]] + // CHECK-NEXT: [[SIZE:%.+]] = and i64 [[MAXSIZE]], [[ALIGN_NEG]] + + // CHECK-NEXT: store i64 [[ALIGN]], ptr [[LAYOUT]], align 8 + // CHECK-NEXT: [[LAYOUT_SIZEP:%.+]] = getelementptr inbounds i8, ptr [[LAYOUT]], i64 8 + // CHECK-NEXT: store i64 [[SIZE]], ptr [[LAYOUT_SIZEP]], align 8 + + // CHECK-NOT: store + // CHECK: load i64, {{.+}} !range [[ALIGNMENT_RANGE:!.+]], + // CHECK-NOT: store + layout_of_val(ptr) +} + +// CHECK-LABEL: declare + +// CHECK: [[ALIGNMENT_RANGE]] = !{i64 1, i64 -[[#0x7FFFFFFFFFFFFFFF]]} +// CHECK: [[SIZE_RANGE]] = !{i64 0, i64 -[[#0x8000000000000000]]} +// CHECK: [[ALIGN_RANGE]] = !{i64 1, i64 [[#0x20000001]]} From 84eb2f09d34516dde81e20e68ffe0712568f0c34 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 19 Feb 2026 18:59:16 -0800 Subject: [PATCH 3/3] Also simplify `layout_of_val` down to a constant Same as rust-lang/rust 152689 did for align/size. --- compiler/rustc_hir/src/lang_items.rs | 1 + .../rustc_mir_transform/src/instsimplify.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/mem/mod.rs | 1 + .../codegen-llvm/intrinsics/layout_of_val.rs | 9 +---- ..._sized.InstSimplify-after-simplifycfg.diff | 22 +++++++++++ .../align_or_size_of_sized_val.rs | 9 +++++ ...rop_bytes.PreCodegen.after.panic-abort.mir | 37 +++---------------- ...op_bytes.PreCodegen.after.panic-unwind.mir | 37 +++---------------- ...p_generic.PreCodegen.after.panic-abort.mir | 35 ++++++------------ ..._generic.PreCodegen.after.panic-unwind.mir | 35 ++++++------------ .../mir-opt/pre-codegen/drop_box_of_sized.rs | 9 ++--- 12 files changed, 78 insertions(+), 120 deletions(-) create mode 100644 tests/mir-opt/instsimplify/align_or_size_of_sized_val.layout_of_val_sized.InstSimplify-after-simplifycfg.diff diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 6a8e5d25e54cc..c114c04af03fa 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -158,6 +158,7 @@ language_item_table! { Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); AlignOf, sym::mem_align_const, align_const, Target::AssocConst, GenericRequirement::Exact(0); SizeOf, sym::mem_size_const, size_const, Target::AssocConst, GenericRequirement::Exact(0); + LayoutOf, sym::mem_layout_const, layout_const, Target::AssocConst, GenericRequirement::Exact(0); OffsetOf, sym::offset_of, offset_of, Target::Fn, GenericRequirement::Exact(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None; diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b97901f075bc6..007b512a78323 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -271,6 +271,8 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { LangItem::SizeOf } else if self.tcx.is_intrinsic(fn_def_id, sym::align_of_val) { LangItem::AlignOf + } else if self.tcx.is_intrinsic(fn_def_id, sym::layout_of_val) { + LangItem::LayoutOf } else { return; }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 41a81a74c0a90..91ed09da67425 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1245,6 +1245,7 @@ symbols! { mem_discriminant, mem_drop, mem_forget, + mem_layout_const, mem_size_const, mem_swap, mem_uninitialized, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 2fbb5842ef778..7975c0b4b09c5 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1421,6 +1421,7 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] + #[lang = "mem_layout_const"] const LAYOUT: Layout = { // SAFETY: if the type is instantiated, rustc already ensures that its // layout is valid. Use the unchecked constructor to avoid inserting a diff --git a/tests/codegen-llvm/intrinsics/layout_of_val.rs b/tests/codegen-llvm/intrinsics/layout_of_val.rs index 75fe4a19749ad..5a12899d42af0 100644 --- a/tests/codegen-llvm/intrinsics/layout_of_val.rs +++ b/tests/codegen-llvm/intrinsics/layout_of_val.rs @@ -15,13 +15,8 @@ use std::intrinsics::layout_of_val; // CHECK-LABEL: @thin_metadata( #[no_mangle] pub unsafe fn thin_metadata(ptr: *const [u32; 2]) -> Layout { - // CHECK: [[LAYOUT:%.+]] = alloca [16 x i8], align 8 - // CHECK-NOT: load - // CHECK-NOT: store - // CHECK: store i64 4, ptr [[LAYOUT]], align 8 - // CHECK-NEXT: [[SIZEP:%.+]] = getelementptr inbounds i8, ptr [[LAYOUT]], i64 8 - // CHECK-NEXT: store i64 8, ptr [[SIZEP]], align 8 - // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK: ret { i64, i64 } { i64 4, i64 8 } layout_of_val(ptr) } diff --git a/tests/mir-opt/instsimplify/align_or_size_of_sized_val.layout_of_val_sized.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/align_or_size_of_sized_val.layout_of_val_sized.InstSimplify-after-simplifycfg.diff new file mode 100644 index 0000000000000..26554f32daec3 --- /dev/null +++ b/tests/mir-opt/instsimplify/align_or_size_of_sized_val.layout_of_val_sized.InstSimplify-after-simplifycfg.diff @@ -0,0 +1,22 @@ +- // MIR for `layout_of_val_sized` before InstSimplify-after-simplifycfg ++ // MIR for `layout_of_val_sized` after InstSimplify-after-simplifycfg + + fn layout_of_val_sized(_1: &T) -> Layout { + debug val => _1; + let mut _0: std::alloc::Layout; + let mut _2: *const T; + + bb0: { + StorageLive(_2); + _2 = &raw const (*_1); +- _0 = layout_of_val::(move _2) -> [return: bb1, unwind unreachable]; ++ _0 = const ::LAYOUT; ++ goto -> bb1; + } + + bb1: { + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/align_or_size_of_sized_val.rs b/tests/mir-opt/instsimplify/align_or_size_of_sized_val.rs index d186e1bc90141..ea0310b165d54 100644 --- a/tests/mir-opt/instsimplify/align_or_size_of_sized_val.rs +++ b/tests/mir-opt/instsimplify/align_or_size_of_sized_val.rs @@ -4,6 +4,8 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] +use std::alloc::Layout; + // EMIT_MIR align_or_size_of_sized_val.align_of_val_sized.InstSimplify-after-simplifycfg.diff pub fn align_of_val_sized(val: &T) -> usize { // CHECK-LABEL: fn align_of_val_sized @@ -17,3 +19,10 @@ pub fn size_of_val_sized(val: &T) -> usize { // CHECK: _0 = const ::SIZE; unsafe { core::intrinsics::size_of_val(val) } } + +// EMIT_MIR align_or_size_of_sized_val.layout_of_val_sized.InstSimplify-after-simplifycfg.diff +pub fn layout_of_val_sized(val: &T) -> Layout { + // CHECK-LABEL: fn layout_of_val_sized + // CHECK: _0 = const ::LAYOUT; + unsafe { core::intrinsics::layout_of_val(val) } +} diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir index 5f26ecc817e2c..e818b8df420a5 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir @@ -6,16 +6,13 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box<[u8; 1024]>))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull<[u8; 1024]>; - let mut _3: *const [u8; 1024]; - let mut _5: usize; - let _8: (); + let _4: (); scope 3 { - let _4: std::alloc::Layout; scope 4 { scope 8 (inlined Layout::size) { } scope 9 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { - let mut _6: std::ptr::NonNull; + let mut _3: std::ptr::NonNull; scope 10 (inlined NonNull::<[u8; 1024]>::cast::) { scope 11 (inlined NonNull::<[u8; 1024]>::as_ptr) { } @@ -31,7 +28,6 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 17 (inlined Layout::size) { } scope 18 (inlined alloc::alloc::dealloc_nonnull) { - let mut _7: std::mem::Alignment; scope 19 (inlined Layout::size) { } scope 20 (inlined Layout::alignment) { @@ -52,37 +48,16 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { } bb0: { - StorageLive(_6); + StorageLive(_3); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>); - StorageLive(_4); - StorageLive(_3); - _3 = copy _2 as *const [u8; 1024] (Transmute); - _4 = layout_of_val::<[u8; 1024]>(move _3) -> [return: bb1, unwind unreachable]; + _3 = copy _2 as std::ptr::NonNull (Transmute); + _4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::mem::Alignment {{ _inner_repr_trick: mem::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_3); - _5 = copy (_4.0: usize); - switchInt(copy _5) -> [0: bb4, otherwise: bb2]; - } - - bb2: { - _6 = copy _2 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy (_4.1: std::mem::Alignment); - _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_7); - goto -> bb4; - } - - bb4: { - StorageDead(_4); StorageDead(_2); - StorageDead(_6); + StorageDead(_3); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir index 5f26ecc817e2c..e818b8df420a5 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir @@ -6,16 +6,13 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box<[u8; 1024]>))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull<[u8; 1024]>; - let mut _3: *const [u8; 1024]; - let mut _5: usize; - let _8: (); + let _4: (); scope 3 { - let _4: std::alloc::Layout; scope 4 { scope 8 (inlined Layout::size) { } scope 9 (inlined std::ptr::Unique::<[u8; 1024]>::cast::) { - let mut _6: std::ptr::NonNull; + let mut _3: std::ptr::NonNull; scope 10 (inlined NonNull::<[u8; 1024]>::cast::) { scope 11 (inlined NonNull::<[u8; 1024]>::as_ptr) { } @@ -31,7 +28,6 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { scope 17 (inlined Layout::size) { } scope 18 (inlined alloc::alloc::dealloc_nonnull) { - let mut _7: std::mem::Alignment; scope 19 (inlined Layout::size) { } scope 20 (inlined Layout::alignment) { @@ -52,37 +48,16 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () { } bb0: { - StorageLive(_6); + StorageLive(_3); StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>); - StorageLive(_4); - StorageLive(_3); - _3 = copy _2 as *const [u8; 1024] (Transmute); - _4 = layout_of_val::<[u8; 1024]>(move _3) -> [return: bb1, unwind unreachable]; + _3 = copy _2 as std::ptr::NonNull (Transmute); + _4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::mem::Alignment {{ _inner_repr_trick: mem::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_3); - _5 = copy (_4.0: usize); - switchInt(copy _5) -> [0: bb4, otherwise: bb2]; - } - - bb2: { - _6 = copy _2 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy (_4.1: std::mem::Alignment); - _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_7); - goto -> bb4; - } - - bb4: { - StorageDead(_4); StorageDead(_2); - StorageDead(_6); + StorageDead(_3); return; } } diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir index 413c23487df43..b8f2a31faddae 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir @@ -6,11 +6,11 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let mut _3: *const T; - let mut _5: usize; - let _8: (); + let _7: (); scope 3 { - let _4: std::alloc::Layout; + let _3: std::alloc::Layout; + let _4: usize; + let _5: std::mem::Alignment; scope 4 { scope 8 (inlined Layout::size) { } @@ -31,7 +31,6 @@ fn drop_generic(_1: *mut Box) -> () { scope 17 (inlined Layout::size) { } scope 18 (inlined alloc::alloc::dealloc_nonnull) { - let mut _7: std::mem::Alignment; scope 19 (inlined Layout::size) { } scope 20 (inlined Layout::alignment) { @@ -56,31 +55,21 @@ fn drop_generic(_1: *mut Box) -> () { StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); StorageLive(_4); - StorageLive(_3); - _3 = copy _2 as *const T (Transmute); - _4 = layout_of_val::(move _3) -> [return: bb1, unwind unreachable]; + StorageLive(_5); + _3 = const ::LAYOUT; + _4 = move (_3.0: usize); + _5 = move (_3.1: std::mem::Alignment); + switchInt(copy _4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_3); - _5 = copy (_4.0: usize); - switchInt(copy _5) -> [0: bb4, otherwise: bb2]; - } - - bb2: { _6 = copy _2 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy (_4.1: std::mem::Alignment); - _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; + _7 = alloc::alloc::__rust_dealloc(move _6, move _4, move _5) -> [return: bb2, unwind unreachable]; } - bb3: { - StorageDead(_7); - goto -> bb4; - } - - bb4: { + bb2: { StorageDead(_4); + StorageDead(_5); StorageDead(_2); StorageDead(_6); return; diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir index 413c23487df43..b8f2a31faddae 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir @@ -6,11 +6,11 @@ fn drop_generic(_1: *mut Box) -> () { scope 1 (inlined drop_in_place::> - shim(Some(Box))) { scope 2 (inlined as Drop>::drop) { let _2: std::ptr::NonNull; - let mut _3: *const T; - let mut _5: usize; - let _8: (); + let _7: (); scope 3 { - let _4: std::alloc::Layout; + let _3: std::alloc::Layout; + let _4: usize; + let _5: std::mem::Alignment; scope 4 { scope 8 (inlined Layout::size) { } @@ -31,7 +31,6 @@ fn drop_generic(_1: *mut Box) -> () { scope 17 (inlined Layout::size) { } scope 18 (inlined alloc::alloc::dealloc_nonnull) { - let mut _7: std::mem::Alignment; scope 19 (inlined Layout::size) { } scope 20 (inlined Layout::alignment) { @@ -56,31 +55,21 @@ fn drop_generic(_1: *mut Box) -> () { StorageLive(_2); _2 = copy (((*_1).0: std::ptr::Unique).0: std::ptr::NonNull); StorageLive(_4); - StorageLive(_3); - _3 = copy _2 as *const T (Transmute); - _4 = layout_of_val::(move _3) -> [return: bb1, unwind unreachable]; + StorageLive(_5); + _3 = const ::LAYOUT; + _4 = move (_3.0: usize); + _5 = move (_3.1: std::mem::Alignment); + switchInt(copy _4) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_3); - _5 = copy (_4.0: usize); - switchInt(copy _5) -> [0: bb4, otherwise: bb2]; - } - - bb2: { _6 = copy _2 as std::ptr::NonNull (Transmute); - StorageLive(_7); - _7 = copy (_4.1: std::mem::Alignment); - _8 = alloc::alloc::__rust_dealloc(move _6, move _5, move _7) -> [return: bb3, unwind unreachable]; + _7 = alloc::alloc::__rust_dealloc(move _6, move _4, move _5) -> [return: bb2, unwind unreachable]; } - bb3: { - StorageDead(_7); - goto -> bb4; - } - - bb4: { + bb2: { StorageDead(_4); + StorageDead(_5); StorageDead(_2); StorageDead(_6); return; diff --git a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs index 2687106e19dfa..c49657656250a 100644 --- a/tests/mir-opt/pre-codegen/drop_box_of_sized.rs +++ b/tests/mir-opt/pre-codegen/drop_box_of_sized.rs @@ -6,9 +6,9 @@ // EMIT_MIR drop_box_of_sized.drop_generic.PreCodegen.after.mir pub unsafe fn drop_generic(x: *mut Box) { // CHECK-LABEL: fn drop_generic - // CHECK: [[LAYOUT:_.+]] = layout_of_val:: - // CHECK: [[SIZE:_.+]] = copy ([[LAYOUT]].0: usize); - // CHECK: [[ALIGNMENT:_.+]] = copy ([[LAYOUT]].1: std::mem::Alignment); + // CHECK: [[LAYOUT:_.+]] = const ::LAYOUT; + // CHECK: [[SIZE:_.+]] = move ([[LAYOUT]].0: usize); + // CHECK: [[ALIGNMENT:_.+]] = move ([[LAYOUT]].1: std::mem::Alignment); // CHECK: alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[ALIGNMENT]]) std::ptr::drop_in_place(x) } @@ -16,7 +16,6 @@ pub unsafe fn drop_generic(x: *mut Box) { // EMIT_MIR drop_box_of_sized.drop_bytes.PreCodegen.after.mir pub unsafe fn drop_bytes(x: *mut Box<[u8; 1024]>) { // CHECK-LABEL: fn drop_bytes - // CHECK: layout_of_val::<[u8; 1024]> - // CHECK: alloc::alloc::__rust_dealloc + // CHECK: alloc::alloc::__rust_dealloc({{.+}}, const 1024_usize, {{.+}}Align1Shl0 {{.+}}) std::ptr::drop_in_place(x) }