]> git.proxmox.com Git - rustc.git/blobdiff - src/libcore/intrinsics.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / libcore / intrinsics.rs
index ece285a831355e3610ead728e5d6193d87667c44..e844a158484af488b2adea942de2127bc12644cc 100644 (file)
@@ -10,7 +10,7 @@
 
 //! rustc compiler intrinsics.
 //!
-//! The corresponding definitions are in librustc_trans/trans/intrinsic.rs.
+//! The corresponding definitions are in librustc_trans/intrinsic.rs.
 //!
 //! # Volatiles
 //!
             issue = "0")]
 #![allow(missing_docs)]
 
-use marker::Sized;
-
 extern "rust-intrinsic" {
 
     // NB: These intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
 
-    pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> T;
-    pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> T;
-    pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> T;
-    pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> T;
-    pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> T;
+    pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+
+    pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     pub fn atomic_load<T>(src: *const T) -> T;
     pub fn atomic_load_acq<T>(src: *const T) -> T;
@@ -154,6 +166,15 @@ extern "rust-intrinsic" {
     pub fn atomic_singlethreadfence_rel();
     pub fn atomic_singlethreadfence_acqrel();
 
+    /// Magic intrinsic that derives its meaning from attributes
+    /// attached to the function.
+    ///
+    /// For example, dataflow uses this to inject static assertions so
+    /// that `rustc_peek(potentially_uninitialized)` would actually
+    /// double-check that dataflow did indeed compute that it is
+    /// uninitialized at that point in the control flow.
+    pub fn rustc_peek<T>(_: T) -> T;
+
     /// Aborts the execution of the process.
     pub fn abort() -> !;
 
@@ -173,16 +194,25 @@ extern "rust-intrinsic" {
     /// own, or if it does not enable any significant optimizations.
     pub fn assume(b: bool);
 
+    /// Hints to the compiler that branch condition is likely to be true.
+    /// Returns the value passed to it.
+    ///
+    /// Any use other than with `if` statements will probably not have an effect.
+    pub fn likely(b: bool) -> bool;
+
+    /// Hints to the compiler that branch condition is likely to be false.
+    /// Returns the value passed to it.
+    ///
+    /// Any use other than with `if` statements will probably not have an effect.
+    pub fn unlikely(b: bool) -> bool;
+
     /// Executes a breakpoint trap, for inspection by a debugger.
     pub fn breakpoint();
 
     /// The size of a type in bytes.
     ///
-    /// This is the exact number of bytes in memory taken up by a
-    /// value of the given type. In other words, a memset of this size
-    /// would *exactly* overwrite a value. When laid out in vectors
-    /// and structures there may be additional padding between
-    /// elements.
+    /// More specifically, this is the offset in bytes between successive
+    /// items of the same type, including alignment padding.
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
@@ -195,7 +225,26 @@ extern "rust-intrinsic" {
 
     pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
-    pub fn drop_in_place<T: ?Sized>(_: *mut T);
+
+    /// Executes the destructor (if any) of the pointed-to value.
+    ///
+    /// This has two use cases:
+    ///
+    /// * It is *required* to use `drop_in_place` to drop unsized types like
+    ///   trait objects, because they can't be read out onto the stack and
+    ///   dropped normally.
+    ///
+    /// * It is friendlier to the optimizer to do this over `ptr::read` when
+    ///   dropping manually allocated memory (e.g. when writing Box/Rc/Vec),
+    ///   as the compiler doesn't need to prove that it's sound to elide the
+    ///   copy.
+    ///
+    /// # Undefined Behavior
+    ///
+    /// This has all the same safety problems as `ptr::read` with respect to
+    /// invalid pointers, types, and double drops.
+    #[stable(feature = "drop_in_place", since = "1.8.0")]
+    pub fn drop_in_place<T: ?Sized>(to_drop: *mut T);
 
     /// Gets a static string slice containing the name of a type.
     pub fn type_name<T: ?Sized>() -> &'static str;
@@ -205,19 +254,6 @@ extern "rust-intrinsic" {
     /// crate it is invoked in.
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
-    /// Creates a value initialized to so that its drop flag,
-    /// if any, says that it has been dropped.
-    ///
-    /// `init_dropped` is unsafe because it returns a datum with all
-    /// of its bytes set to the drop flag, which generally does not
-    /// correspond to a valid value.
-    ///
-    /// This intrinsic is likely to be deprecated in the future when
-    /// Rust moves to non-zeroing dynamic drop (and thus removes the
-    /// embedded drop flags that are being established by this
-    /// intrinsic).
-    pub fn init_dropped<T>() -> T;
-
     /// Creates a value initialized to zero.
     ///
     /// `init` is unsafe because it returns a zeroed-out datum,
@@ -238,27 +274,217 @@ extern "rust-intrinsic" {
     /// Moves a value out of scope without running drop glue.
     pub fn forget<T>(_: T) -> ();
 
-    /// Unsafely transforms a value of one type into a value of another type.
+    /// Reinterprets the bits of a value of one type as another type.
+    ///
+    /// Both types must have the same size. Neither the original, nor the result,
+    /// may be an [invalid value](../../nomicon/meet-safe-and-unsafe.html).
+    ///
+    /// `transmute` is semantically equivalent to a bitwise move of one type
+    /// into another. It copies the bits from the source value into the
+    /// destination value, then forgets the original. It's equivalent to C's
+    /// `memcpy` under the hood, just like `transmute_copy`.
+    ///
+    /// `transmute` is **incredibly** unsafe. There are a vast number of ways to
+    /// cause [undefined behavior][ub] with this function. `transmute` should be
+    /// the absolute last resort.
+    ///
+    /// The [nomicon](../../nomicon/transmutes.html) has additional
+    /// documentation.
     ///
-    /// Both types must have the same size.
+    /// [ub]: ../../reference.html#behavior-considered-undefined
     ///
     /// # Examples
     ///
+    /// There are a few things that `transmute` is really useful for.
+    ///
+    /// Getting the bitpattern of a floating point type (or, more generally,
+    /// type punning, when `T` and `U` aren't pointers):
+    ///
     /// ```
-    /// use std::mem;
+    /// let bitpattern = unsafe {
+    ///     std::mem::transmute::<f32, u32>(1.0)
+    /// };
+    /// assert_eq!(bitpattern, 0x3F800000);
+    /// ```
+    ///
+    /// Turning a pointer into a function pointer. This is *not* portable to
+    /// machines where function pointers and data pointers have different sizes.
     ///
-    /// let array: &[u8] = unsafe { mem::transmute("Rust") };
-    /// assert_eq!(array, [82, 117, 115, 116]);
+    /// ```
+    /// fn foo() -> i32 {
+    ///     0
+    /// }
+    /// let pointer = foo as *const ();
+    /// let function = unsafe {
+    ///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
+    /// };
+    /// assert_eq!(function(), 0);
+    /// ```
+    ///
+    /// Extending a lifetime, or shortening an invariant lifetime. This is
+    /// advanced, very unsafe Rust!
+    ///
+    /// ```
+    /// struct R<'a>(&'a i32);
+    /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
+    ///     std::mem::transmute::<R<'b>, R<'static>>(r)
+    /// }
+    ///
+    /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
+    ///                                              -> &'b mut R<'c> {
+    ///     std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
+    /// }
+    /// ```
+    ///
+    /// # Alternatives
+    ///
+    /// Don't despair: many uses of `transmute` can be achieved through other means.
+    /// Below are common applications of `transmute` which can be replaced with safer
+    /// constructs.
+    ///
+    /// Turning a pointer into a `usize`:
+    ///
+    /// ```
+    /// let ptr = &0;
+    /// let ptr_num_transmute = unsafe {
+    ///     std::mem::transmute::<&i32, usize>(ptr)
+    /// };
+    ///
+    /// // Use an `as` cast instead
+    /// let ptr_num_cast = ptr as *const i32 as usize;
+    /// ```
+    ///
+    /// Turning a `*mut T` into an `&mut T`:
+    ///
+    /// ```
+    /// let ptr: *mut i32 = &mut 0;
+    /// let ref_transmuted = unsafe {
+    ///     std::mem::transmute::<*mut i32, &mut i32>(ptr)
+    /// };
+    ///
+    /// // Use a reborrow instead
+    /// let ref_casted = unsafe { &mut *ptr };
+    /// ```
+    ///
+    /// Turning an `&mut T` into an `&mut U`:
+    ///
+    /// ```
+    /// let ptr = &mut 0;
+    /// let val_transmuted = unsafe {
+    ///     std::mem::transmute::<&mut i32, &mut u32>(ptr)
+    /// };
+    ///
+    /// // Now, put together `as` and reborrowing - note the chaining of `as`
+    /// // `as` is not transitive
+    /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
+    /// ```
+    ///
+    /// Turning an `&str` into an `&[u8]`:
+    ///
+    /// ```
+    /// // this is not a good way to do this.
+    /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    ///
+    /// // You could use `str::as_bytes`
+    /// let slice = "Rust".as_bytes();
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    ///
+    /// // Or, just use a byte string, if you have control over the string
+    /// // literal
+    /// assert_eq!(b"Rust", &[82, 117, 115, 116]);
+    /// ```
+    ///
+    /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
+    ///
+    /// ```
+    /// let store = [0, 1, 2, 3];
+    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    ///
+    /// // Using transmute: this is Undefined Behavior, and a bad idea.
+    /// // However, it is no-copy.
+    /// let v_transmuted = unsafe {
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
+    ///         v_orig.clone())
+    /// };
+    ///
+    /// // This is the suggested, safe way.
+    /// // It does copy the entire vector, though, into a new array.
+    /// let v_collected = v_orig.clone()
+    ///                         .into_iter()
+    ///                         .map(|r| Some(r))
+    ///                         .collect::<Vec<Option<&i32>>>();
+    ///
+    /// // The no-copy, unsafe way, still using transmute, but not UB.
+    /// // This is equivalent to the original, but safer, and reuses the
+    /// // same Vec internals. Therefore the new inner type must have the
+    /// // exact same size, and the same or lesser alignment, as the old
+    /// // type. The same caveats exist for this method as transmute, for
+    /// // the original inner type (`&i32`) to the converted inner type
+    /// // (`Option<&i32>`), so read the nomicon pages linked above.
+    /// let v_from_raw = unsafe {
+    ///     Vec::from_raw_parts(v_orig.as_mut_ptr(),
+    ///                         v_orig.len(),
+    ///                         v_orig.capacity())
+    /// };
+    /// std::mem::forget(v_orig);
+    /// ```
+    ///
+    /// Implementing `split_at_mut`:
+    ///
+    /// ```
+    /// use std::{slice, mem};
+    ///
+    /// // There are multiple ways to do this; and there are multiple problems
+    /// // with the following, transmute, way.
+    /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
+    ///                              -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
+    ///         // first: transmute is not typesafe; all it checks is that T and
+    ///         // U are of the same size. Second, right here, you have two
+    ///         // mutable references pointing to the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    ///
+    /// // This gets rid of the typesafety problems; `&mut *` will *only* give
+    /// // you an `&mut T` from an `&mut T` or `*mut T`.
+    /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
+    ///                          -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = &mut *(slice as *mut [T]);
+    ///         // however, you still have two mutable references pointing to
+    ///         // the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    ///
+    /// // This is how the standard library does it. This is the best method, if
+    /// // you need to do something like this
+    /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
+    ///                       -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let ptr = slice.as_mut_ptr();
+    ///         // This now has three mutable references pointing at the same
+    ///         // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
+    ///         // `slice` is never used after `let ptr = ...`, and so one can
+    ///         // treat it as "dead", and therefore, you only have two real
+    ///         // mutable slices.
+    ///         (slice::from_raw_parts_mut(ptr, mid),
+    ///          slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+    ///     }
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn transmute<T, U>(e: T) -> U;
 
-    /// Gives the address for the return value of the enclosing function.
-    ///
-    /// Using this intrinsic in a function that does not use an out pointer
-    /// will trigger a compiler error.
-    pub fn return_address() -> *const u8;
-
     /// Returns `true` if the actual type given as `T` requires drop
     /// glue; returns `false` if the actual type provided for `T`
     /// implements `Copy`.
@@ -301,7 +527,7 @@ extern "rust-intrinsic" {
     /// # Safety
     ///
     /// Beyond requiring that the program must be allowed to access both regions
-    /// of memory, it is Undefined Behaviour for source and destination to
+    /// of memory, it is Undefined Behavior for source and destination to
     /// overlap. Care must also be taken with the ownership of `src` and
     /// `dst`. This method semantically moves the values of `src` into `dst`.
     /// However it does not drop the contents of `dst`, or prevent the contents
@@ -315,6 +541,7 @@ extern "rust-intrinsic" {
     /// use std::mem;
     /// use std::ptr;
     ///
+    /// # #[allow(dead_code)]
     /// fn swap<T>(x: &mut T, y: &mut T) {
     ///     unsafe {
     ///         // Give ourselves some scratch space to work with
@@ -353,6 +580,7 @@ extern "rust-intrinsic" {
     /// ```
     /// use std::ptr;
     ///
+    /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst = Vec::with_capacity(elts);
     ///     dst.set_len(elts);
@@ -365,7 +593,20 @@ extern "rust-intrinsic" {
     pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
 
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
-    /// bytes of memory starting at `dst` to `c`.
+    /// bytes of memory starting at `dst` to `val`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ptr;
+    ///
+    /// let mut vec = vec![0; 4];
+    /// unsafe {
+    ///     let vec_ptr = vec.as_mut_ptr();
+    ///     ptr::write_bytes(vec_ptr, b'a', 2);
+    /// }
+    /// assert_eq!(vec, [b'a', b'a', 0, 0]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
 
@@ -373,20 +614,20 @@ extern "rust-intrinsic" {
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
                                                   count: usize);
     /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
     /// size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`.
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
 
     /// Perform a volatile load from the `src` pointer.
@@ -491,121 +732,73 @@ extern "rust-intrinsic" {
     /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
     pub fn roundf64(x: f64) -> f64;
 
-    /// Returns the number of bits set in a `u8`.
-    pub fn ctpop8(x: u8) -> u8;
-    /// Returns the number of bits set in a `u16`.
-    pub fn ctpop16(x: u16) -> u16;
-    /// Returns the number of bits set in a `u32`.
-    pub fn ctpop32(x: u32) -> u32;
-    /// Returns the number of bits set in a `u64`.
-    pub fn ctpop64(x: u64) -> u64;
-
-    /// Returns the number of leading bits unset in a `u8`.
-    pub fn ctlz8(x: u8) -> u8;
-    /// Returns the number of leading bits unset in a `u16`.
-    pub fn ctlz16(x: u16) -> u16;
-    /// Returns the number of leading bits unset in a `u32`.
-    pub fn ctlz32(x: u32) -> u32;
-    /// Returns the number of leading bits unset in a `u64`.
-    pub fn ctlz64(x: u64) -> u64;
-
-    /// Returns the number of trailing bits unset in a `u8`.
-    pub fn cttz8(x: u8) -> u8;
-    /// Returns the number of trailing bits unset in a `u16`.
-    pub fn cttz16(x: u16) -> u16;
-    /// Returns the number of trailing bits unset in a `u32`.
-    pub fn cttz32(x: u32) -> u32;
-    /// Returns the number of trailing bits unset in a `u64`.
-    pub fn cttz64(x: u64) -> u64;
-
-    /// Reverses the bytes in a `u16`.
-    pub fn bswap16(x: u16) -> u16;
-    /// Reverses the bytes in a `u32`.
-    pub fn bswap32(x: u32) -> u32;
-    /// Reverses the bytes in a `u64`.
-    pub fn bswap64(x: u64) -> u64;
-
-    /// Performs checked `i8` addition.
-    pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool);
-    /// Performs checked `i16` addition.
-    pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool);
-    /// Performs checked `i32` addition.
-    pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool);
-    /// Performs checked `i64` addition.
-    pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool);
-
-    /// Performs checked `u8` addition.
-    pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool);
-    /// Performs checked `u16` addition.
-    pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool);
-    /// Performs checked `u32` addition.
-    pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool);
-    /// Performs checked `u64` addition.
-    pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool);
-
-    /// Performs checked `i8` subtraction.
-    pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool);
-    /// Performs checked `i16` subtraction.
-    pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool);
-    /// Performs checked `i32` subtraction.
-    pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool);
-    /// Performs checked `i64` subtraction.
-    pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool);
-
-    /// Performs checked `u8` subtraction.
-    pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool);
-    /// Performs checked `u16` subtraction.
-    pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool);
-    /// Performs checked `u32` subtraction.
-    pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool);
-    /// Performs checked `u64` subtraction.
-    pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool);
-
-    /// Performs checked `i8` multiplication.
-    pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool);
-    /// Performs checked `i16` multiplication.
-    pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool);
-    /// Performs checked `i32` multiplication.
-    pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool);
-    /// Performs checked `i64` multiplication.
-    pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool);
-
-    /// Performs checked `u8` multiplication.
-    pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool);
-    /// Performs checked `u16` multiplication.
-    pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool);
-    /// Performs checked `u32` multiplication.
-    pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool);
-    /// Performs checked `u64` multiplication.
-    pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
-
-    /// Returns (a + b) mod 2^N, where N is the width of N in bits.
+    /// Float addition that allows optimizations based on algebraic rules.
+    /// May assume inputs are finite.
+    pub fn fadd_fast<T>(a: T, b: T) -> T;
+
+    /// Float subtraction that allows optimizations based on algebraic rules.
+    /// May assume inputs are finite.
+    pub fn fsub_fast<T>(a: T, b: T) -> T;
+
+    /// Float multiplication that allows optimizations based on algebraic rules.
+    /// May assume inputs are finite.
+    pub fn fmul_fast<T>(a: T, b: T) -> T;
+
+    /// Float division that allows optimizations based on algebraic rules.
+    /// May assume inputs are finite.
+    pub fn fdiv_fast<T>(a: T, b: T) -> T;
+
+    /// Float remainder that allows optimizations based on algebraic rules.
+    /// May assume inputs are finite.
+    pub fn frem_fast<T>(a: T, b: T) -> T;
+
+
+    /// Returns the number of bits set in an integer type `T`
+    pub fn ctpop<T>(x: T) -> T;
+
+    /// Returns the number of leading bits unset in an integer type `T`
+    pub fn ctlz<T>(x: T) -> T;
+
+    /// Returns the number of trailing bits unset in an integer type `T`
+    pub fn cttz<T>(x: T) -> T;
+
+    /// Reverses the bytes in an integer type `T`.
+    pub fn bswap<T>(x: T) -> T;
+
+    /// Performs checked integer addition.
+    pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
+
+    /// Performs checked integer subtraction
+    pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
+
+    /// Performs checked integer multiplication
+    pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
+
+    /// Performs an unchecked division, resulting in undefined behavior
+    /// where y = 0 or x = `T::min_value()` and y = -1
+    pub fn unchecked_div<T>(x: T, y: T) -> T;
+    /// Returns the remainder of an unchecked division, resulting in
+    /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
+    pub fn unchecked_rem<T>(x: T, y: T) -> T;
+
+    /// Returns (a + b) mod 2^N, where N is the width of T in bits.
     pub fn overflowing_add<T>(a: T, b: T) -> T;
-    /// Returns (a - b) mod 2^N, where N is the width of N in bits.
+    /// Returns (a - b) mod 2^N, where N is the width of T in bits.
     pub fn overflowing_sub<T>(a: T, b: T) -> T;
-    /// Returns (a * b) mod 2^N, where N is the width of N in bits.
+    /// Returns (a * b) mod 2^N, where N is the width of T in bits.
     pub fn overflowing_mul<T>(a: T, b: T) -> T;
 
-    /// Performs an unchecked signed division, which results in undefined behavior,
-    /// in cases where y == 0, or x == isize::MIN and y == -1
-    pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
-    /// Performs an unchecked unsigned division, which results in undefined behavior,
-    /// in cases where y == 0
-    pub fn unchecked_udiv<T>(x: T, y: T) -> T;
-
-    /// Returns the remainder of an unchecked signed division, which results in
-    /// undefined behavior, in cases where y == 0, or x == isize::MIN and y == -1
-    pub fn unchecked_srem<T>(x: T, y: T) -> T;
-    /// Returns the remainder of an unchecked unsigned division, which results in
-    /// undefined behavior, in cases where y == 0
-    pub fn unchecked_urem<T>(x: T, y: T) -> T;
-
     /// Returns the value of the discriminant for the variant in 'v',
     /// cast to a `u64`; if `T` has no discriminant, returns 0.
     pub fn discriminant_value<T>(v: &T) -> u64;
 
     /// Rust's "try catch" construct which invokes the function pointer `f` with
-    /// the data pointer `data`, returning the exception payload if an exception
-    /// is thrown (aka the thread panics).
-    pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
+    /// the data pointer `data`.
+    ///
+    /// The third pointer is a target-specific data pointer which is filled in
+    /// with the specifics of the exception that occurred. For examples on Unix
+    /// platforms this is a `*mut *mut T` which is filled in by the compiler and
+    /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
+    /// source as well as std's catch implementation.
+    pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
 }