From b999cd0aea88cf415bd50ab0c42cff1f6c02f0c0 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Fri, 11 Oct 2024 21:54:23 -0400 Subject: [PATCH] Make `Layout::dangling` return `isize::MAX` --- lcrust/libraries/libcore/src/alloc.rs | 2 +- lcrust/libraries/libcore/src/intrinsics.rs | 31 +++++++++++++---- lcrust/libraries/libcore/src/mem.rs | 40 ++++++++++++++++++++++ lcrust/libraries/libcore/src/ptr.rs | 15 ++------ 4 files changed, 68 insertions(+), 20 deletions(-) diff --git a/lcrust/libraries/libcore/src/alloc.rs b/lcrust/libraries/libcore/src/alloc.rs index 5ecdb51a..2e59a273 100644 --- a/lcrust/libraries/libcore/src/alloc.rs +++ b/lcrust/libraries/libcore/src/alloc.rs @@ -119,7 +119,7 @@ impl Layout { pub fn dangling(&self) -> NonNull { // SAFETY: // _align is a power of two, and thus, the resulting pointer is non-null. - unsafe { NonNull::new_unchecked(self._align as *mut u8) } + unsafe { NonNull::new_unchecked(core::ptr::without_provenance(isize::MIN as usize)) } } } diff --git a/lcrust/libraries/libcore/src/intrinsics.rs b/lcrust/libraries/libcore/src/intrinsics.rs index 4eea2d42..eef20ce3 100644 --- a/lcrust/libraries/libcore/src/intrinsics.rs +++ b/lcrust/libraries/libcore/src/intrinsics.rs @@ -19,29 +19,48 @@ #![unstable(feature = "core_intrinsics", issue = "none")] +#[stable] +pub use core::mem::transmute; + +#[unstable(feature = "lccc_mir_macro", issue = "none")] +#[lcrust::builtin_macro] +pub macro mir($($tt:tt)*) {} + extern "rust-intrinsics" { - pub unsafe fn transmute(x: T) -> U; + + pub fn __builtin_size_of() -> usize; + pub fn __builtin_align_of() -> usize; + pub fn __builtin_known_align_of() -> usize; + pub unsafe fn construct_in_place + FnPointer, Args: Tuple>( dest: *mut T, func: F, args: Args, ); - pub fn __builtin_cmp(a: T, b: T) -> U; + + /// Compares two primitive values three way. `U` must be an integer type + pub const fn __builtin_cmp< + T: core::marker::Copy + core::cmp::PartialOrd, + U: core::marker::Copy, + >( + a: T, + b: T, + ) -> U; /// Same as [`Ord::max`][core::cmp::Ord::max] but only on primitives, and generally more efficient. /// Also functions on `f32` and `f64`, see the corresponding function on those types for behaviour surrounding NaNs. /// This may avoid a branch that may be present on the default function - pub fn __builtin_max_val(a: T, b: T) -> T; + pub const fn __builtin_max_val(a: T, b: T) -> T; /// Same as [`Ord::min`][core::cmp::Ord::min] but only on primitives, and generally more efficient. /// Also functions on `f32` and `f64`, see the corresponding function on those types for behaviour surrounding NaNs. /// This may avoid a branch that may be present on the default function - pub fn __builtin_min_val(a: T, b: T) -> T; + pub const fn __builtin_min_val(a: T, b: T) -> T; /// Same as [`Ord::clamp`][core::cmp::Ord::clamp] but only on primitives, and generally more efficient. /// Also functions on `f32` and `f64`, see the corresponding function on those types for behaviour surrounding NaNs. /// This may avoid a branch that may be present on the default function. - /// + /// /// Note: This function may have unpredictable results, but does not have undefined behaviour, if `lower` > `upper`. - pub fn __builtin_clamp_val( + pub const fn __builtin_clamp_val( val: T, lower: T, upper: T, diff --git a/lcrust/libraries/libcore/src/mem.rs b/lcrust/libraries/libcore/src/mem.rs index 27df7590..9b4f3fe4 100644 --- a/lcrust/libraries/libcore/src/mem.rs +++ b/lcrust/libraries/libcore/src/mem.rs @@ -171,3 +171,43 @@ pub const fn align_of() -> usize { pub const fn size_of_val(x: &T) -> usize { intrinsics::__builtin_size_of_val(x) } + +pub const fn align_of_val(x: &T) -> usize { + intrinsics::__builtin_align_of_val(x) +} + +pub const unsafe fn transmute_copy(x: &T) -> U { + if const { core::intrinsics::__builtin_known_align_of::() < core::mem::align_of::() } { + (x as *const T).cast::().read_unaligned() + } else { + (x as *const T).cast::().read() + } +} + +pub const unsafe fn transmute(x: T) -> U { + const { + assert_eq!( + core::mem::size_of::(), + core::mem::size_of::(), + "Cannot transmute between differently sized types" + ); + } + + transmute_unchecked(x) +} + +#[unstable(feature = "transmute_unchecked")] +#[inline(always)] +pub const unsafe fn transmute_unchecked(x: T) -> U { + union Transmuter { + val: ManuallyDrop, + result: ManuallyDrop, + } + + ManuallyDrop::into_inner( + Transmuter { + val: ManuallyDrop::new(x), + } + .result, + ) +} diff --git a/lcrust/libraries/libcore/src/ptr.rs b/lcrust/libraries/libcore/src/ptr.rs index 3ae5af21..18e96d50 100644 --- a/lcrust/libraries/libcore/src/ptr.rs +++ b/lcrust/libraries/libcore/src/ptr.rs @@ -87,9 +87,8 @@ pub fn slice_from_raw_parts_mut(ptr: *mut T, len: usize) -> *mut [T] { } #[repr(transparent)] -#[__lccc::transparent_as_unreified_field] // Fields with the type just become the transparent field type. pub struct NonNull { - #[__lccc::xlang_pointer_attributes(nonnull)] + #[lcrust::nonnull_pointer] ptr: *const T, } @@ -103,16 +102,7 @@ impl Copy for NonNull {} impl NonNull { pub const fn dangling() -> Self { - // If std is built with debug-assertions=1 (--debug & -Z build-std), or the randomize-dangling feature - // Then mess with code that relies on the unspecified implementation of NonNull::::dangling() - let ptr = if cfg!(debug_assertions) || cfg!(feature = "randomize-dangling") { - (::__lccc::__random_bytes!() & !(::__lccc::builtins::Rust::align_of::() - 1)) - as *const T - } else { - ::__lccc::builtins::Rust::align_of::() as *const T - }; - - NonNull { ptr } + core::alloc::Layout::of::().dangling().cast() } } @@ -162,7 +152,6 @@ impl From<&mut T> for NonNull { #[repr(transparent)] #[unstable(feature = "lccc_unique_ptr")] -#[__lccc::transparent_as_unreified_field] pub struct Unique { #[__lccc::xlang_pointer_attributes(aligned)] ptr: NonNull,