]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/intrinsics.rs
Auto merge of #61492 - RalfJung:const-qualif-comments, r=eddyb
[rust.git] / src / libcore / intrinsics.rs
index 782a7ba45598455de4b03064c000aeb7bad862ad..8d9a51742fd97ac9159c514c293f8cbb3bf19f9d 100644 (file)
@@ -1051,6 +1051,19 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// Returns the absolute value of an `f64`.
     pub fn fabsf64(x: f64) -> f64;
 
+    /// Returns the minimum of two `f32` values.
+    #[cfg(not(bootstrap))]
+    pub fn minnumf32(x: f32, y: f32) -> f32;
+    /// Returns the minimum of two `f64` values.
+    #[cfg(not(bootstrap))]
+    pub fn minnumf64(x: f64, y: f64) -> f64;
+    /// Returns the maximum of two `f32` values.
+    #[cfg(not(bootstrap))]
+    pub fn maxnumf32(x: f32, y: f32) -> f32;
+    /// Returns the maximum of two `f64` values.
+    #[cfg(not(bootstrap))]
+    pub fn maxnumf64(x: f64, y: f64) -> f64;
+
     /// Copies the sign from `y` to `x` for `f32` values.
     pub fn copysignf32(x: f32, y: f32) -> f32;
     /// Copies the sign from `y` to `x` for `f64` values.
@@ -1240,6 +1253,21 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// y < 0 or y >= N, where N is the width of T in bits.
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
+    /// Returns the result of an unchecked addition, resulting in
+    /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+    #[cfg(not(bootstrap))]
+    pub fn unchecked_add<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked substraction, resulting in
+    /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+    #[cfg(not(bootstrap))]
+    pub fn unchecked_sub<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked multiplication, resulting in
+    /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+    #[cfg(not(bootstrap))]
+    pub fn unchecked_mul<T>(x: T, y: T) -> T;
+
     /// Performs rotate left.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
@@ -1298,30 +1326,10 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 }
 
-mod real_intrinsics {
-  extern "rust-intrinsic" {
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination must *not* overlap.
-    /// For the full docs, see the stabilized wrapper [`copy_nonoverlapping`].
-    ///
-    /// [`copy_nonoverlapping`]: ../../std/ptr/fn.copy_nonoverlapping.html
-    pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination may overlap.
-    /// For the full docs, see the stabilized wrapper [`copy`].
-    ///
-    /// [`copy`]: ../../std/ptr/fn.copy.html
-    pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
-
-    /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
-    /// `val`.
-    /// For the full docs, see the stabilized wrapper [`write_bytes`].
-    ///
-    /// [`write_bytes`]: ../../std/ptr/fn.write_bytes.html
-    pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
-  }
-}
+// Some functions are defined here because they accidentally got made
+// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
+// (`transmute` also falls into this category, but it cannot be wrapped due to the
+// check that `T` and `U` have the same size.)
 
 /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
 /// and destination must *not* overlap.
@@ -1409,7 +1417,10 @@ mod real_intrinsics {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[inline]
 pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
-    real_intrinsics::copy_nonoverlapping(src, dst, count);
+    extern "rust-intrinsic" {
+        fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+    }
+    copy_nonoverlapping(src, dst, count);
 }
 
 /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
@@ -1466,7 +1477,10 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[inline]
 pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    real_intrinsics::copy(src, dst, count)
+    extern "rust-intrinsic" {
+        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    }
+    copy(src, dst, count)
 }
 
 /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
@@ -1544,5 +1558,52 @@ pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[inline]
 pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
-    real_intrinsics::write_bytes(dst, val, count)
+    extern "rust-intrinsic" {
+        fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+    }
+    write_bytes(dst, val, count)
+}
+
+// Simple bootstrap implementations of minnum/maxnum for stage0 compilation.
+
+/// Returns the minimum of two `f32` values.
+#[cfg(bootstrap)]
+pub fn minnumf32(x: f32, y: f32) -> f32 {
+    // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
+    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+    // is either x or y, canonicalized (this means results might differ among implementations).
+    // When either x or y is a signaling NaN, then the result is according to 6.2.
+    //
+    // Since we do not support sNaN in Rust yet, we do not need to handle them.
+    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+    (if x < y || y != y { x } else { y }) * 1.0
+}
+
+/// Returns the minimum of two `f64` values.
+#[cfg(bootstrap)]
+pub fn minnumf64(x: f64, y: f64) -> f64 {
+    // Identical to the `f32` case.
+    (if x < y || y != y { x } else { y }) * 1.0
+}
+
+/// Returns the maximum of two `f32` values.
+#[cfg(bootstrap)]
+pub fn maxnumf32(x: f32, y: f32) -> f32 {
+    // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
+    // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
+    // is either x or y, canonicalized (this means results might differ among implementations).
+    // When either x or y is a signaling NaN, then the result is according to 6.2.
+    //
+    // Since we do not support sNaN in Rust yet, we do not need to handle them.
+    // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
+    // multiplying by 1.0. Should switch to the `canonicalize` when it works.
+    (if x < y || x != x { y } else { x }) * 1.0
+}
+
+/// Returns the maximum of two `f64` values.
+#[cfg(bootstrap)]
+pub fn maxnumf64(x: f64, y: f64) -> f64 {
+    // Identical to the `f32` case.
+    (if x < y || x != x { y } else { x }) * 1.0
 }