Skip to content

Commit 6f8bd3a

Browse files
committed
Advance the port to llvm/llvm-project@6dabc38
(last APFloat-related LLVM commit from 2020).
1 parent a3362d1 commit 6f8bd3a

File tree

5 files changed

+45
-20
lines changed

5 files changed

+45
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
members = ["fuzz"]
33

44
[workspace.package]
5-
version = "0.0.5+llvm-a2588948febc"
5+
version = "0.0.6+llvm-6dabc38cce73"
66
edition = "2021"
77
license = "Apache-2.0 WITH LLVM-exception"
88

fuzz/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ echo | clang++ -x c++ - -std=c++17 \
9191
$clang_codegen_flags \
9292
-I "$llvm"/include \
9393
-I "$OUT_DIR"/fake-config \
94-
-DNDEBUG -DHAVE_UNISTD_H \
94+
-DNDEBUG -DHAVE_UNISTD_H -DLLVM_ON_UNIX \
9595
--include="$llvm"/lib/Support/{APInt,APFloat,SmallVector,ErrorHandling}.cpp \
9696
--include="$OUT_DIR"/cxx_apf_fuzz.cpp \
9797
-c -emit-llvm -o "$OUT_DIR"/cxx_apf_fuzz.bc

src/ieee.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,10 @@ pub trait Semantics: Sized {
100100
};
101101

102102
if r.exp == Self::MIN_EXP - 1 && r.sig == [0] {
103-
// Exponent, significand meaningless.
104103
r.category = Category::Zero;
105104
} else if r.exp == Self::MAX_EXP + 1 && r.sig == [0] {
106-
// Exponent, significand meaningless.
107105
r.category = Category::Infinity;
108106
} else if r.exp == Self::MAX_EXP + 1 && r.sig != [0] {
109-
// Sign, exponent, significand meaningless.
110107
r.category = Category::NaN;
111108
} else {
112109
r.category = Category::Normal;
@@ -220,16 +217,14 @@ impl Semantics for X87DoubleExtendedS {
220217
let integer_bit = r.sig[0] >> (Self::PRECISION - 1);
221218

222219
if r.exp == Self::MIN_EXP - 1 && r.sig == [0] {
223-
// Exponent, significand meaningless.
224220
r.category = Category::Zero;
225221
} else if r.exp == Self::MAX_EXP + 1 && r.sig == [1 << (Self::PRECISION - 1)] {
226-
// Exponent, significand meaningless.
227222
r.category = Category::Infinity;
228223
} else if r.exp == Self::MAX_EXP + 1 && r.sig != [1 << (Self::PRECISION - 1)]
229224
|| r.exp != Self::MAX_EXP + 1 && r.exp != Self::MIN_EXP - 1 && integer_bit == 0
230225
{
231-
// Sign, exponent, significand meaningless.
232226
r.category = Category::NaN;
227+
r.exp = Self::MAX_EXP + 1;
233228
} else {
234229
r.category = Category::Normal;
235230
if r.exp == Self::MIN_EXP - 1 {
@@ -1739,11 +1734,10 @@ impl<S: Semantics, T: Semantics> FloatConvert<IeeeFloat<T>> for IeeeFloat<S> {
17391734
sig::set_bit(&mut r.sig, T::PRECISION - 1);
17401735
}
17411736

1742-
// gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
1743-
// does not give you back the same bits. This is dubious, and we
1744-
// don't currently do it. You're really supposed to get
1745-
// an invalid operation signal at runtime, but nobody does that.
1746-
status = Status::OK;
1737+
// Convert of sNaN creates qNaN and raises an exception (invalid op).
1738+
// This also guarantees that a sNaN does not become Inf on a truncation
1739+
// that loses all payload bits.
1740+
r = unpack!(status=, IeeeDefaultExceptionHandling::result_from_nan(r));
17471741
} else {
17481742
*loses_info = false;
17491743
status = Status::OK;

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Port of LLVM's APFloat software floating-point implementation from the
22
//! following C++ sources (please update commit hash when backporting):
3-
//! https://github.com/llvm/llvm-project/commit/a2588948febccfed5ba074fc32dcb093484fa5c8
3+
//! https://github.com/llvm/llvm-project/commit/6dabc38cce73549ed747c537f81f6f4dd79eba39
44
//! * `llvm/include/llvm/ADT/APFloat.h` -> `Float` and `FloatConvert` traits
55
//! * `llvm/lib/Support/APFloat.cpp` -> `ieee` and `ppc` modules
66
//! * `llvm/unittests/ADT/APFloatTest.cpp` -> `tests` directory

tests/ieee.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,8 @@ fn copy_sign() {
17431743
#[test]
17441744
fn convert() {
17451745
let mut loses_info = false;
1746+
let mut status;
1747+
17461748
let test = "1.0".parse::<Double>().unwrap();
17471749
let test: Single = test.convert(&mut loses_info).value;
17481750
assert_eq!(1.0, test.to_f32());
@@ -1768,26 +1770,45 @@ fn convert() {
17681770
assert!(!loses_info);
17691771

17701772
let test = Single::snan(None);
1771-
let x87_snan = X87DoubleExtended::snan(None);
1772-
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
1773-
assert!(test.bitwise_eq(x87_snan));
1773+
let test: X87DoubleExtended = unpack!(status=, test.convert(&mut loses_info));
1774+
// Conversion quiets the SNAN, so now 2 bits of the 64-bit significand should be set.
1775+
assert!(test.bitwise_eq(X87DoubleExtended::qnan(Some(0x6000000000000000))));
17741776
assert!(!loses_info);
1777+
assert_eq!(status, Status::INVALID_OP);
17751778

17761779
let test = Single::qnan(None);
17771780
let x87_qnan = X87DoubleExtended::qnan(None);
17781781
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
17791782
assert!(test.bitwise_eq(x87_qnan));
17801783
assert!(!loses_info);
17811784

1782-
let test = X87DoubleExtended::snan(None);
1785+
// NOTE(eddyb) these were mistakenly noops upstream, here they're already
1786+
// fixed (by instead converting from `Double` to `X87DoubleExtended`),
1787+
// see also upstream issue https://github.com/llvm/llvm-project/issues/63842.
1788+
let test = Double::snan(None);
17831789
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
1784-
assert!(test.bitwise_eq(x87_snan));
1790+
// Conversion quiets the SNAN, so now 2 bits of the 64-bit significand should be set.
1791+
assert!(test.bitwise_eq(X87DoubleExtended::qnan(Some(0x6000000000000000))));
17851792
assert!(!loses_info);
17861793

1787-
let test = X87DoubleExtended::qnan(None);
1794+
let test = Double::qnan(None);
17881795
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
17891796
assert!(test.bitwise_eq(x87_qnan));
17901797
assert!(!loses_info);
1798+
1799+
// The payload is lost in truncation, but we retain NaN by setting the quiet bit.
1800+
let test = Double::snan(Some(1));
1801+
let test: Single = unpack!(status=, test.convert(&mut loses_info));
1802+
assert_eq!(0x7fc00000, test.to_bits());
1803+
assert!(loses_info);
1804+
assert_eq!(status, Status::INVALID_OP);
1805+
1806+
// The payload is lost in truncation. QNaN remains QNaN.
1807+
let test = Double::qnan(Some(1));
1808+
let test: Single = unpack!(status=, test.convert(&mut loses_info));
1809+
assert_eq!(0x7fc00000, test.to_bits());
1810+
assert!(loses_info);
1811+
assert_eq!(status, Status::OK);
17911812
}
17921813

17931814
#[test]
@@ -3978,3 +3999,13 @@ fn remainder() {
39783999
assert_eq!(status, Status::OK);
39794000
}
39804001
}
4002+
4003+
#[test]
4004+
fn x87_largest() {
4005+
assert!(X87DoubleExtended::largest().is_largest());
4006+
}
4007+
4008+
#[test]
4009+
fn x87_next() {
4010+
assert_eq!("-1.0".parse::<X87DoubleExtended>().unwrap().next_up().value.ilogb(), -1);
4011+
}

0 commit comments

Comments
 (0)