Skip to content

Commit

Permalink
Add basic library support for f16 and f128
Browse files Browse the repository at this point in the history
Implement basic operation traits that get lowered to intrinsics.

Additionally, add codegn tests for the implemented operations.
  • Loading branch information
tgross35 committed Mar 26, 2024
1 parent c3b05c6 commit 6651c16
Show file tree
Hide file tree
Showing 14 changed files with 341 additions and 9 deletions.
3 changes: 3 additions & 0 deletions library/core/src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ mod impls {
bool char
}

#[cfg(not(bootstrap))]
impl_clone! { f16 f128 }

#[unstable(feature = "never_type", issue = "35121")]
impl Clone for ! {
#[inline]
Expand Down
6 changes: 6 additions & 0 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,9 @@ mod impls {
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64
}

#[cfg(not(bootstrap))]
partial_eq_impl! { f16 f128 }

macro_rules! eq_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -1541,6 +1544,9 @@ mod impls {

partial_ord_impl! { f32 f64 }

#[cfg(not(bootstrap))]
partial_ord_impl! { f16 f128 }

macro_rules! ord_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
15 changes: 15 additions & 0 deletions library/core/src/convert/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ macro_rules! impl_float_to_int {
}
}

#[cfg(not(bootstrap))]
impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
#[cfg(not(bootstrap))]
impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

// Conversion traits for primitive integer and float types
// Conversions T -> T are covered by a blanket impl and therefore excluded
Expand Down Expand Up @@ -164,7 +168,18 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);

// float -> float
// todo: these are insta-stable regardless of the gate, right?
#[cfg(not(bootstrap))]
impl_from!(f16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
#[cfg(not(bootstrap))]
impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
#[cfg(not(bootstrap))]
impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
#[cfg(not(bootstrap))]
impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
#[cfg(not(bootstrap))]
impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);

macro_rules! impl_float_from_bool {
($float:ty) => {
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,9 @@ default_impl! { i32, 0, "Returns the default value of `0`" }
default_impl! { i64, 0, "Returns the default value of `0`" }
default_impl! { i128, 0, "Returns the default value of `0`" }

#[cfg(not(bootstrap))]
default_impl! { f16, 0.0f16, "Returns the default value of `0.0`" }
default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
#[cfg(not(bootstrap))]
default_impl! { f128, 0.0f128, "Returns the default value of `0.0`" }
4 changes: 4 additions & 0 deletions library/core/src/fmt/nofloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@ macro_rules! floating {
};
}

#[cfg(not(bootstrap))]
floating! { f16 }
floating! { f32 }
floating! { f64 }
#[cfg(not(bootstrap))]
floating! { f128 }
2 changes: 2 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@
#![feature(doc_notable_trait)]
#![feature(effects)]
#![feature(extern_types)]
#![feature(f128)]
#![feature(f16)]
#![feature(freeze_impls)]
#![feature(fundamental)]
#![feature(generic_arg_infer)]
Expand Down
7 changes: 7 additions & 0 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,13 @@ marker_impls! {

}

// todo: which feature gate should we use?
#[cfg(not(bootstrap))]
marker_impls! {
#[stable(feature = "rust1", since = "1.0.0")]
Copy for f16, f128
}

#[unstable(feature = "never_type", issue = "35121")]
impl Copy for ! {}

Expand Down
33 changes: 33 additions & 0 deletions library/core/src/ops/arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ macro_rules! add_impl {

add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
add_impl! { f16 f128 }

/// The subtraction operator `-`.
///
/// Note that `Rhs` is `Self` by default, but this is not mandatory. For
Expand Down Expand Up @@ -220,6 +223,9 @@ macro_rules! sub_impl {

sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
sub_impl! { f16 f128 }

/// The multiplication operator `*`.
///
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
Expand Down Expand Up @@ -350,6 +356,9 @@ macro_rules! mul_impl {

mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
mul_impl! { f16 f128 }

/// The division operator `/`.
///
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
Expand Down Expand Up @@ -508,6 +517,9 @@ macro_rules! div_impl_float {

div_impl_float! { f32 f64 }

#[cfg(not(bootstrap))]
div_impl_float! { f16 f128 }

/// The remainder operator `%`.
///
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
Expand Down Expand Up @@ -625,6 +637,9 @@ macro_rules! rem_impl_float {

rem_impl_float! { f32 f64 }

#[cfg(not(bootstrap))]
rem_impl_float! { f16 f128 }

/// The unary negation operator `-`.
///
/// # Examples
Expand Down Expand Up @@ -700,6 +715,9 @@ macro_rules! neg_impl {

neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
neg_impl! { f16 f128 }

/// The addition assignment operator `+=`.
///
/// # Examples
Expand Down Expand Up @@ -767,6 +785,9 @@ macro_rules! add_assign_impl {

add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
add_assign_impl! { f16 f128 }

/// The subtraction assignment operator `-=`.
///
/// # Examples
Expand Down Expand Up @@ -834,6 +855,9 @@ macro_rules! sub_assign_impl {

sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
sub_assign_impl! { f16 f128 }

/// The multiplication assignment operator `*=`.
///
/// # Examples
Expand Down Expand Up @@ -892,6 +916,9 @@ macro_rules! mul_assign_impl {

mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
mul_assign_impl! { f16 f128 }

/// The division assignment operator `/=`.
///
/// # Examples
Expand Down Expand Up @@ -949,6 +976,9 @@ macro_rules! div_assign_impl {

div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
div_assign_impl! { f16 f128 }

/// The remainder assignment operator `%=`.
///
/// # Examples
Expand Down Expand Up @@ -1009,3 +1039,6 @@ macro_rules! rem_assign_impl {
}

rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

#[cfg(not(bootstrap))]
rem_assign_impl! { f16 f128 }
129 changes: 129 additions & 0 deletions tests/codegen/float/f128.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Verify that our intrinsics generate the correct LLVM calls for f128

#![crate_type = "lib"]
#![feature(f128)]
#![feature(core_intrinsics)]

// CHECK-LABEL: i1 @f128_eq(
#[no_mangle]
pub fn f128_eq(a: f128, b: f128) -> bool {
// CHECK: fcmp oeq fp128 %{{.+}}, %{{.+}}
a == b
}

// CHECK-LABEL: i1 @f128_ne(
#[no_mangle]
pub fn f128_ne(a: f128, b: f128) -> bool {
// CHECK: fcmp une fp128 %{{.+}}, %{{.+}}
a != b
}

// CHECK-LABEL: i1 @f128_gt(
#[no_mangle]
pub fn f128_gt(a: f128, b: f128) -> bool {
// CHECK: fcmp ogt fp128 %{{.+}}, %{{.+}}
a > b
}

// CHECK-LABEL: i1 @f128_ge(
#[no_mangle]
pub fn f128_ge(a: f128, b: f128) -> bool {
// CHECK: fcmp oge fp128 %{{.+}}, %{{.+}}
a >= b
}

// CHECK-LABEL: i1 @f128_lt(
#[no_mangle]
pub fn f128_lt(a: f128, b: f128) -> bool {
// CHECK: fcmp olt fp128 %{{.+}}, %{{.+}}
a < b
}

// CHECK-LABEL: i1 @f128_le(
#[no_mangle]
pub fn f128_le(a: f128, b: f128) -> bool {
// CHECK: fcmp ole fp128 %{{.+}}, %{{.+}}
a <= b
}

// CHECK-LABEL: fp128 @f128_neg(
#[no_mangle]
pub fn f128_neg(a: f128) -> f128 {
// CHECK: fneg fp128
-a
}

// CHECK-LABEL: fp128 @f128_add(
#[no_mangle]
pub fn f128_add(a: f128, b: f128) -> f128 {
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
a + b
}

// CHECK-LABEL: fp128 @f128_sub(
#[no_mangle]
pub fn f128_sub(a: f128, b: f128) -> f128 {
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
a - b
}

// CHECK-LABEL: fp128 @f128_mul(
#[no_mangle]
pub fn f128_mul(a: f128, b: f128) -> f128 {
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
a * b
}

// CHECK-LABEL: fp128 @f128_div(
#[no_mangle]
pub fn f128_div(a: f128, b: f128) -> f128 {
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
a / b
}

// CHECK-LABEL: fp128 @f128_rem(
#[no_mangle]
pub fn f128_rem(a: f128, b: f128) -> f128 {
// CHECK: frem fp128 %{{.+}}, %{{.+}}
a % b
}

// CHECK-LABEL: void @f128_add_assign(
#[no_mangle]
pub fn f128_add_assign(a: &mut f128, b: f128) {
// CHECK: fadd fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a += b;
}

// CHECK-LABEL: void @f128_sub_assign(
#[no_mangle]
pub fn f128_sub_assign(a: &mut f128, b: f128) {
// CHECK: fsub fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a -= b;
}

// CHECK-LABEL: void @f128_mul_assign(
#[no_mangle]
pub fn f128_mul_assign(a: &mut f128, b: f128) {
// CHECK: fmul fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a *= b
}

// CHECK-LABEL: void @f128_div_assign(
#[no_mangle]
pub fn f128_div_assign(a: &mut f128, b: f128) {
// CHECK: fdiv fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a /= b
}

// CHECK-LABEL: void @f128_rem_assign(
#[no_mangle]
pub fn f128_rem_assign(a: &mut f128, b: f128) {
// CHECK: frem fp128 %{{.+}}, %{{.+}}
// CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}}
*a %= b
}
Loading

0 comments on commit 6651c16

Please sign in to comment.