diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 2ded0f6177d7b..51d0734a4c4df 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -11,11 +11,12 @@ concurrency: env: CARGO_TERM_COLOR: always + CARGO_TERM_VERBOSE: true LIBM_BUILD_VERBOSE: true RUSTDOCFLAGS: -Dwarnings - RUSTFLAGS: -Dwarnings + RUSTFLAGS: -Dwarnings -Dlinker_messages RUST_BACKTRACE: full - BENCHMARK_RUSTC: nightly-2026-08-05 # Pin the toolchain for reproducable results + BENCHMARK_RUSTC: nightly-2026-08-19 # Pin the toolchain for reproducable results defaults: run: @@ -91,6 +92,8 @@ jobs: # os: ["self-hosted", "linux", "riscv64"] - target: riscv64gc-unknown-linux-gnu os: ubuntu-26.04 + - target: s390x-unknown-linux-gnu + os: self-hosted-linux-s390x-resolute-large-rust # resolute == ubuntu-26.04 - target: s390x-unknown-linux-gnu os: ubuntu-24.04-s390x - target: thumbv6m-none-eabi @@ -111,9 +114,10 @@ jobs: os: windows-2025-vs2026 - target: x86_64-pc-windows-msvc os: windows-2025-vs2026 - - target: i686-pc-windows-gnu - os: windows-2025-vs2026 - channel: nightly-i686-gnu + # FIXME(rust-lang/compiler-builtins#1306): disabled due to broken environment + # - target: i686-pc-windows-gnu + # os: windows-2025-vs2026 + # channel: nightly-i686-gnu - target: x86_64-pc-windows-gnu os: windows-2025-vs2026 channel: nightly-x86_64-gnu @@ -132,26 +136,20 @@ jobs: lscpu || (sysctl -a | grep cpu) || true echo "home: ${HOME:-not found}" pwd - - # Native ppc and s390x runners don't have rustup by default - - name: Install rustup - if: matrix.os == 'ubuntu-26.04-ppc64le' || matrix.os == 'ubuntu-26.04-s390x' - run: sudo apt-get update && sudo apt-get install -y rustup - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - - name: Install Rust (rustup) - run: | - channel="nightly" - # Account for channels that have required components (MinGW) - [ -n "$JOB_CHANNEL" ] && channel="$JOB_CHANNEL" - rustup update "$channel" --no-self-update - rustup default "$channel" - rustup target add "$JOB_TARGET" + + - name: Set up dependencies and Rust + run: ./ci/install-test-deps.sh "$JOB_TARGET" "$JOB_CHANNEL" "$RUN_IN_DOCKER" - uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2.85.11 + continue-on-error: true with: tool: nextest@0.9.131 + # On platforms without prebuilts, nextest can be installed system-wide + # or omitted. Building it probably takes longer than running tests + # without it + fallback: none - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: @@ -172,7 +170,7 @@ jobs: uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: compiler-rt - key: ${{ runner.os }}-compiler-rt-${{ hashFiles('ci/download-compiler-rt.sh', 'ci/compiler-rt-patches') }} + key: ${{ runner.os }}-compiler-rt-${{ hashFiles('ci/download-compiler-rt.sh') }} - name: Download compiler-rt reference sources if: steps.cache-compiler-rt.outputs.cache-hit != 'true' run: ./ci/download-compiler-rt.sh @@ -345,7 +343,7 @@ jobs: msrv: name: Check libm MSRV runs-on: ubuntu-26.04 - timeout-minutes: 10 + timeout-minutes: 20 env: RUSTFLAGS: # No need to check warnings on old MSRV, unset `-Dwarnings` steps: @@ -358,7 +356,7 @@ jobs: rustup update "$msrv" --no-self-update && rustup default "$msrv" - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - run: | - # FIXME(msrv): Remove the workspace Cargo.toml so 1.63 cargo doesn't see + # FIXME(msrv): Remove the workspace Cargo.toml so MSRV cargo doesn't see # `edition = "2024"` and get spooked. rm Cargo.toml cargo build --manifest-path libm/Cargo.toml diff --git a/library/compiler-builtins/builtins-test/Cargo.toml b/library/compiler-builtins/builtins-test/Cargo.toml index f1a5be415675d..b3227b5751164 100644 --- a/library/compiler-builtins/builtins-test/Cargo.toml +++ b/library/compiler-builtins/builtins-test/Cargo.toml @@ -37,6 +37,10 @@ icount = ["dep:gungraun"] benchmarking-reports = ["walltime", "criterion/plotters", "criterion/html_reports"] walltime = ["dep:criterion"] +[lints.clippy] +# This sometimes reads better +needless-range-loop = "allow" + [[bench]] name = "float_add" harness = false diff --git a/library/compiler-builtins/builtins-test/benches/mem.rs b/library/compiler-builtins/builtins-test/benches/mem.rs index 3f83926b6c5a2..875e4b8699778 100644 --- a/library/compiler-builtins/builtins-test/benches/mem.rs +++ b/library/compiler-builtins/builtins-test/benches/mem.rs @@ -1,72 +1,39 @@ #![feature(test)] extern crate test; +use builtins_test::mem::AlignedSlice; use test::{Bencher, black_box}; extern crate compiler_builtins; use compiler_builtins::mem::{memcmp, memcpy, memmove, memset}; -const WORD_SIZE: usize = core::mem::size_of::(); - -struct AlignedVec { - vec: Vec, - size: usize, -} - -impl AlignedVec { - fn new(fill: u8, size: usize) -> Self { - let mut broadcast = fill as usize; - let mut bits = 8; - while bits < WORD_SIZE * 8 { - broadcast |= broadcast << bits; - bits *= 2; - } - - let vec = vec![broadcast; (size + WORD_SIZE - 1) & !WORD_SIZE]; - AlignedVec { vec, size } - } -} - -impl core::ops::Deref for AlignedVec { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { core::slice::from_raw_parts(self.vec.as_ptr() as *const u8, self.size) } - } -} - -impl core::ops::DerefMut for AlignedVec { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { core::slice::from_raw_parts_mut(self.vec.as_mut_ptr() as *mut u8, self.size) } - } -} - fn memcpy_builtin(b: &mut Bencher, n: usize, offset1: usize, offset2: usize) { - let v1 = AlignedVec::new(1, n + offset1); - let mut v2 = AlignedVec::new(0, n + offset2); + let v1 = AlignedSlice::new(1, n, offset1); + let mut v2 = AlignedSlice::new(0, n, offset2); b.bytes = n as u64; b.iter(|| { - let src: &[u8] = black_box(&v1[offset1..]); - let dst: &mut [u8] = black_box(&mut v2[offset2..]); + let src: &[u8] = black_box(&v1); + let dst: &mut [u8] = black_box(&mut v2); dst.copy_from_slice(src); }) } fn memcpy_rust(b: &mut Bencher, n: usize, offset1: usize, offset2: usize) { - let v1 = AlignedVec::new(1, n + offset1); - let mut v2 = AlignedVec::new(0, n + offset2); + let v1 = AlignedSlice::new(1, n, offset1); + let mut v2 = AlignedSlice::new(0, n, offset2); b.bytes = n as u64; b.iter(|| { - let src: &[u8] = black_box(&v1[offset1..]); - let dst: &mut [u8] = black_box(&mut v2[offset2..]); + let src: &[u8] = black_box(&v1); + let dst: &mut [u8] = black_box(&mut v2); unsafe { memcpy(dst.as_mut_ptr(), src.as_ptr(), n) } }) } fn memset_builtin(b: &mut Bencher, n: usize, offset: usize) { - let mut v1 = AlignedVec::new(0, n + offset); + let mut v1 = AlignedSlice::new(0, n, offset); b.bytes = n as u64; b.iter(|| { - let dst: &mut [u8] = black_box(&mut v1[offset..]); + let dst: &mut [u8] = black_box(&mut v1); let val: u8 = black_box(27); for b in dst { *b = val; @@ -75,18 +42,18 @@ fn memset_builtin(b: &mut Bencher, n: usize, offset: usize) { } fn memset_rust(b: &mut Bencher, n: usize, offset: usize) { - let mut v1 = AlignedVec::new(0, n + offset); + let mut v1 = AlignedSlice::new(0, n, offset); b.bytes = n as u64; b.iter(|| { - let dst: &mut [u8] = black_box(&mut v1[offset..]); + let dst: &mut [u8] = black_box(&mut v1); let val = black_box(27); unsafe { memset(dst.as_mut_ptr(), val, n) } }) } fn memcmp_builtin(b: &mut Bencher, n: usize) { - let v1 = AlignedVec::new(0, n); - let mut v2 = AlignedVec::new(0, n); + let v1 = AlignedSlice::new(0, n, 0); + let mut v2 = AlignedSlice::new(0, n, 0); v2[n - 1] = 1; b.bytes = n as u64; b.iter(|| { @@ -97,20 +64,20 @@ fn memcmp_builtin(b: &mut Bencher, n: usize) { } fn memcmp_builtin_unaligned(b: &mut Bencher, n: usize) { - let v1 = AlignedVec::new(0, n); - let mut v2 = AlignedVec::new(0, n); + let v1 = AlignedSlice::new(0, n, 0); + let mut v2 = AlignedSlice::new(0, n, 1); v2[n - 1] = 1; b.bytes = n as u64; b.iter(|| { - let s1: &[u8] = black_box(&v1[0..]); - let s2: &[u8] = black_box(&v2[1..]); + let s1: &[u8] = black_box(&v1); + let s2: &[u8] = black_box(&v2); s1.cmp(s2) }) } fn memcmp_rust(b: &mut Bencher, n: usize) { - let v1 = AlignedVec::new(0, n); - let mut v2 = AlignedVec::new(0, n); + let v1 = AlignedSlice::new(0, n, 0); + let mut v2 = AlignedSlice::new(0, n, 0); v2[n - 1] = 1; b.bytes = n as u64; b.iter(|| { @@ -121,19 +88,20 @@ fn memcmp_rust(b: &mut Bencher, n: usize) { } fn memcmp_rust_unaligned(b: &mut Bencher, n: usize) { - let v1 = AlignedVec::new(0, n); - let mut v2 = AlignedVec::new(0, n); + let v1 = AlignedSlice::new(0, n, 0); + let mut v2 = AlignedSlice::new(0, n, 1); v2[n - 1] = 1; b.bytes = n as u64; b.iter(|| { - let s1: &[u8] = black_box(&v1[0..]); - let s2: &[u8] = black_box(&v2[1..]); - unsafe { memcmp(s1.as_ptr(), s2.as_ptr(), n - 1) } + let s1: &[u8] = black_box(&v1); + let s2: &[u8] = black_box(&v2); + unsafe { memcmp(s1.as_ptr(), s2.as_ptr(), n) } }) } fn memmove_builtin(b: &mut Bencher, n: usize, offset: usize) { - let mut v = AlignedVec::new(0, n + n / 2 + offset); + // Aligned source, misaligned dest + let mut v = AlignedSlice::new(0, n + n / 2 + offset, 0); b.bytes = n as u64; b.iter(|| { let s: &mut [u8] = black_box(&mut v); @@ -142,7 +110,8 @@ fn memmove_builtin(b: &mut Bencher, n: usize, offset: usize) { } fn memmove_rust(b: &mut Bencher, n: usize, offset: usize) { - let mut v = AlignedVec::new(0, n + n / 2 + offset); + // Aligned source, misaligned dest + let mut v = AlignedSlice::new(0, n + n / 2 + offset, 0); b.bytes = n as u64; b.iter(|| { let dst: *mut u8 = black_box(&mut v[n / 2 + offset..]).as_mut_ptr(); diff --git a/library/compiler-builtins/builtins-test/benches/mem_icount.rs b/library/compiler-builtins/builtins-test/benches/mem_icount.rs index 7a3cad09b4044..ff03269dc7142 100644 --- a/library/compiler-builtins/builtins-test/benches/mem_icount.rs +++ b/library/compiler-builtins/builtins-test/benches/mem_icount.rs @@ -2,74 +2,15 @@ //! is stable enough to be tested in CI. use std::hint::black_box; -use std::{ops, slice}; -use compiler_builtins::mem::{memcmp, memcpy, memmove, memset}; +use builtins_test::mem::{AlignedSlice, MEG1}; use gungraun::{library_benchmark, library_benchmark_group, main}; -const PAGE_SIZE: usize = 0x1000; // 4 kiB -const MAX_ALIGN: usize = 512; // assume we may use avx512 operations one day -const MEG1: usize = 1 << 20; // 1 MiB - -#[derive(Clone)] -#[repr(C, align(0x1000))] -struct Page([u8; PAGE_SIZE]); - -/// A buffer that is page-aligned by default, with an optional offset to create a -/// misalignment. -struct AlignedSlice { - buf: Box<[Page]>, - len: usize, - offset: usize, -} - -impl AlignedSlice { - /// Allocate a slice aligned to ALIGN with at least `len` items, with `offset` from - /// page alignment. - fn new_zeroed(len: usize, offset: usize) -> Self { - assert!(offset < PAGE_SIZE); - let total_len = len + offset; - let items = (total_len / PAGE_SIZE) + if total_len % PAGE_SIZE > 0 { 1 } else { 0 }; - let buf = vec![Page([0u8; PAGE_SIZE]); items].into_boxed_slice(); - AlignedSlice { buf, len, offset } - } -} - -impl ops::Deref for AlignedSlice { - type Target = [u8]; - fn deref(&self) -> &Self::Target { - unsafe { slice::from_raw_parts(self.buf.as_ptr().cast::().add(self.offset), self.len) } - } -} - -impl ops::DerefMut for AlignedSlice { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { - slice::from_raw_parts_mut( - self.buf.as_mut_ptr().cast::().add(self.offset), - self.len, - ) - } - } -} - mod mcpy { - use super::*; - - struct Cfg { - len: usize, - s_off: usize, - d_off: usize, - } + use builtins_test::mem::mcpy::{Cfg, setup}; + use compiler_builtins::mem::memcpy; - fn setup(cfg: Cfg) -> (usize, AlignedSlice, AlignedSlice) { - let Cfg { len, s_off, d_off } = cfg; - println!("bytes: {len} bytes, src offset: {s_off}, dst offset: {d_off}"); - let mut src = AlignedSlice::new_zeroed(len, s_off); - let dst = AlignedSlice::new_zeroed(len, d_off); - src.fill(1); - (len, src, dst) - } + use super::*; #[library_benchmark] #[benches::aligned( @@ -85,7 +26,7 @@ mod mcpy { setup = setup, )] #[benches::offset( - // Both at the same offset + // Both unaligned but at the same offset args = [ Cfg { len: 16, s_off: 65, d_off: 65 }, Cfg { len: 32, s_off: 65, d_off: 65 }, @@ -122,17 +63,10 @@ mod mcpy { } mod mset { - use super::*; - - struct Cfg { - len: usize, - offset: usize, - } + use builtins_test::mem::mset::{Cfg, setup}; + use compiler_builtins::mem::memset; - fn setup(Cfg { len, offset }: Cfg) -> (usize, AlignedSlice) { - println!("bytes: {len}, offset: {offset}"); - (len, AlignedSlice::new_zeroed(len, offset)) - } + use super::*; #[library_benchmark] #[benches::aligned( @@ -171,22 +105,10 @@ mod mset { } mod mcmp { - use super::*; - - struct Cfg { - len: usize, - s_off: usize, - d_off: usize, - } + use builtins_test::mem::mcmp::{Cfg, setup}; + use compiler_builtins::mem::memcmp; - fn setup(cfg: Cfg) -> (usize, AlignedSlice, AlignedSlice) { - let Cfg { len, s_off, d_off } = cfg; - println!("bytes: {len}, src offset: {s_off}, dst offset: {d_off}"); - let b1 = AlignedSlice::new_zeroed(len, s_off); - let mut b2 = AlignedSlice::new_zeroed(len, d_off); - b2[len - 1] = 1; - (len, b1, b2) - } + use super::*; #[library_benchmark] #[benches::aligned( @@ -240,68 +162,11 @@ mod mcmp { mod mmove { use Spread::{Aligned, Large, Medium, Small}; + use builtins_test::mem::mmove::{Cfg, Spread, setup_backward, setup_forward}; + use compiler_builtins::mem::memmove; use super::*; - struct Cfg { - len: usize, - spread: Spread, - off: usize, - } - - enum Spread { - /// `src` and `dst` are close and have the same alignment (or offset). - Aligned, - /// `src` and `dst` are close. - Small, - /// `src` and `dst` are halfway offset in the buffer. - Medium, - /// `src` and `dst` only overlap by a single byte. - Large, - } - - // Note that small and large are - fn calculate_spread(len: usize, spread: Spread) -> usize { - match spread { - // Note that this test doesn't make sense for lengths less than len=128 - Aligned => { - assert!(len > MAX_ALIGN, "aligned memset would have no overlap"); - MAX_ALIGN - } - Small => 1, - Medium => (len / 2) + 1, // add 1 so all are misaligned - Large => len - 1, - } - } - - fn setup_forward(cfg: Cfg) -> (usize, usize, AlignedSlice) { - let Cfg { len, spread, off } = cfg; - let spread = calculate_spread(len, spread); - println!("bytes: {len}, spread: {spread}, offset: {off}, forward"); - assert!(spread < len, "memmove tests should have some overlap"); - let mut buf = AlignedSlice::new_zeroed(len + spread, off); - let mut fill: usize = 0; - buf[..len].fill_with(|| { - fill += 1; - fill as u8 - }); - (len, spread, buf) - } - - fn setup_backward(cfg: Cfg) -> (usize, usize, AlignedSlice) { - let Cfg { len, spread, off } = cfg; - let spread = calculate_spread(len, spread); - println!("bytes: {len}, spread: {spread}, offset: {off}, backward"); - assert!(spread < len, "memmove tests should have some overlap"); - let mut buf = AlignedSlice::new_zeroed(len + spread, off); - let mut fill: usize = 0; - buf[spread..].fill_with(|| { - fill += 1; - fill as u8 - }); - (len, spread, buf) - } - #[library_benchmark] #[benches::aligned( args = [ @@ -492,9 +357,50 @@ mod mmove { library_benchmark_group!(name = memmove, benchmarks = [forward_move, backward_move]); } +mod slen { + use builtins_test::mem::slen::{Cfg, setup}; + use compiler_builtins::mem::strlen; + + use super::*; + + #[library_benchmark] + #[benches::aligned( + args = [ + Cfg { len: 1, offset: 0 }, + Cfg { len: 16, offset: 0 }, + Cfg { len: 32, offset: 0 }, + Cfg { len: 64, offset: 0 }, + Cfg { len: 512, offset: 0 }, + Cfg { len: 4096, offset: 0 }, + Cfg { len: MEG1, offset: 0 }, + ], + setup = setup, + )] + #[benches::offset( + args = [ + Cfg { len: 1, offset: 65 }, + Cfg { len: 16, offset: 65 }, + Cfg { len: 32, offset: 65 }, + Cfg { len: 64, offset: 65 }, + Cfg { len: 512, offset: 65 }, + Cfg { len: 4096, offset: 65 }, + Cfg { len: MEG1, offset: 65 }, + ], + setup = setup, + )] + fn bench_strlen(s: AlignedSlice) { + unsafe { + black_box(strlen(black_box(s.as_ptr().cast::()))); + } + } + + library_benchmark_group!(name = strlen, benchmarks = [bench_strlen]); +} + use mcmp::memcmp; use mcpy::memcpy; use mmove::memmove; use mset::memset; +use slen::strlen; -main!(library_benchmark_groups = [memcpy, memset, memcmp, memmove]); +main!(library_benchmark_groups = [memcpy, memset, memcmp, memmove, strlen]); diff --git a/library/compiler-builtins/builtins-test/build.rs b/library/compiler-builtins/builtins-test/build.rs index 133186bc7f57d..b36d581b9d195 100644 --- a/library/compiler-builtins/builtins-test/build.rs +++ b/library/compiler-builtins/builtins-test/build.rs @@ -58,12 +58,6 @@ fn main() { if cfg.target_arch == "arm" || cfg.target_vendor == "apple" || cfg.target_env == "msvc" - // GCC and LLVM disagree on the ABI of `f16` and `f128` with MinGW. See - // . - || (cfg.target_os == "windows" && cfg.target_env == "gnu") - // FIXME(llvm): There is an ABI incompatibility between GCC and Clang on 32-bit x86. - // See . - || cfg.target_arch == "x86" // 32-bit PowerPC and 64-bit LE gets code generated that Qemu cannot handle. See // . || cfg.target_arch == "powerpc" diff --git a/library/compiler-builtins/builtins-test/src/bench.rs b/library/compiler-builtins/builtins-test/src/bench.rs index dd03579285cbc..2985303988287 100644 --- a/library/compiler-builtins/builtins-test/src/bench.rs +++ b/library/compiler-builtins/builtins-test/src/bench.rs @@ -76,11 +76,11 @@ macro_rules! float_bench { sig: ($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty, // Path to the crate in compiler_builtins crate_fn: $crate_fn:path, - // Optional alias on ppc + // Optional name on ppc $( crate_fn_ppc: $crate_fn_ppc:path, )? // Name of the system symbol sys_fn: $sys_fn:ident, - // Optional alias on ppc + // Optional name on ppc $( sys_fn_ppc: $sys_fn_ppc:path, )? // Meta saying whether the system symbol is available sys_available: $sys_available:meta, @@ -122,7 +122,7 @@ macro_rules! float_bench { #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] let target_crate_fn = $crate_fn; - // On PPC, use an alias if specified + // On PPC, use the PPC name if specified #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] let target_crate_fn = float_bench!(@coalesce $($crate_fn_ppc)?, $crate_fn); @@ -135,7 +135,7 @@ macro_rules! float_bench { #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] let target_sys_fn = $sys_fn; - // On PPC, use an alias if specified + // On PPC, use the PPC name if specified #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] let target_sys_fn = float_bench!(@coalesce $($sys_fn_ppc)?, $sys_fn); diff --git a/library/compiler-builtins/builtins-test/src/lib.rs b/library/compiler-builtins/builtins-test/src/lib.rs index 56c04e551df9d..ebd0162dfae05 100644 --- a/library/compiler-builtins/builtins-test/src/lib.rs +++ b/library/compiler-builtins/builtins-test/src/lib.rs @@ -17,6 +17,7 @@ #![cfg_attr(f16_enabled, feature(f16))] pub mod bench; +pub mod mem; extern crate alloc; use compiler_builtins::support::{Float, Int, MinInt}; diff --git a/library/compiler-builtins/builtins-test/src/mem.rs b/library/compiler-builtins/builtins-test/src/mem.rs new file mode 100644 index 0000000000000..aa66890d56180 --- /dev/null +++ b/library/compiler-builtins/builtins-test/src/mem.rs @@ -0,0 +1,212 @@ +extern crate alloc; + +use alloc::boxed::Box; +use alloc::vec; +use core::{ops, slice}; + +/// 4 kiB +pub const PAGE_SIZE: usize = 0x1000; +/// 1 MiB +pub const MEG1: usize = 1 << 20; +/// When we want to test behavior that may depend on aligned reads/writes, use this value. Large +/// enough for AVX512. +pub const MAX_TESTED_ALIGN: usize = 512; + +#[derive(Clone)] +#[repr(C, align(0x1000))] +struct Page([u8; PAGE_SIZE]); + +/// A buffer that is page-aligned by default and dereferences to a slice, with an optional offset +/// for the deref to create a misaligned buffer. +pub struct AlignedSlice { + buf: Box<[Page]>, + len: usize, + offset: usize, +} + +impl AlignedSlice { + /// Allocate a slice aligned to ALIGN with at least `len` items, with `offset` from + /// page alignment. + pub fn new(fill: u8, len: usize, offset: usize) -> Self { + assert!(offset < PAGE_SIZE); + let total_len = len + offset; + let limbs = total_len.div_ceil(PAGE_SIZE); + let buf = vec![Page([fill; PAGE_SIZE]); limbs].into_boxed_slice(); + AlignedSlice { buf, len, offset } + } + + /// Same as [`new`] but with 0 as the value. + pub fn new_zeroed(len: usize, offset: usize) -> Self { + AlignedSlice::new(0, len, offset) + } +} + +impl ops::Deref for AlignedSlice { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + unsafe { slice::from_raw_parts(self.buf.as_ptr().cast::().add(self.offset), self.len) } + } +} + +impl ops::DerefMut for AlignedSlice { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + slice::from_raw_parts_mut( + self.buf.as_mut_ptr().cast::().add(self.offset), + self.len, + ) + } + } +} + +pub mod mcpy { + use super::*; + + pub struct Cfg { + pub len: usize, + pub s_off: usize, + pub d_off: usize, + } + + /// Return `(len, src, dst)` for a cfg. + pub fn setup(cfg: Cfg) -> (usize, AlignedSlice, AlignedSlice) { + let Cfg { len, s_off, d_off } = cfg; + let mut src = AlignedSlice::new_zeroed(len, s_off); + let dst = AlignedSlice::new_zeroed(len, d_off); + src.fill(1); + (len, src, dst) + } +} + +pub mod mset { + use super::*; + + pub struct Cfg { + pub len: usize, + pub offset: usize, + } + + pub fn setup(Cfg { len, offset }: Cfg) -> (usize, AlignedSlice) { + (len, AlignedSlice::new_zeroed(len, offset)) + } +} + +pub mod mcmp { + use super::*; + + pub struct Cfg { + pub len: usize, + pub s_off: usize, + pub d_off: usize, + } + + pub fn setup(cfg: Cfg) -> (usize, AlignedSlice, AlignedSlice) { + let Cfg { len, s_off, d_off } = cfg; + let b1 = AlignedSlice::new_zeroed(len, s_off); + let mut b2 = AlignedSlice::new_zeroed(len, d_off); + b2[len - 1] = 1; + (len, b1, b2) + } +} + +pub mod mmove { + use Spread::{Aligned, Large, Medium, Small}; + + use super::*; + + pub struct Cfg { + pub len: usize, + pub spread: Spread, + pub off: usize, + } + + pub enum Spread { + /// `src` and `dst` are close and have the same alignment (or offset). + Aligned, + /// `src` and `dst` are close. + Small, + /// `src` and `dst` are halfway offset in the buffer. + Medium, + /// `src` and `dst` only overlap by a single byte. + Large, + } + + // Note that small and large are + pub fn calculate_spread(len: usize, spread: Spread) -> usize { + match spread { + // Note that this test doesn't make sense for lengths less than len=128 + Aligned => { + assert!( + len > MAX_TESTED_ALIGN, + "aligned memset would have no overlap" + ); + MAX_TESTED_ALIGN + } + Small => 1, + Medium => (len / 2) + 1, // add 1 so all are misaligned + Large => len - 1, + } + } + + pub fn setup_forward(cfg: Cfg) -> (usize, usize, AlignedSlice) { + let Cfg { len, spread, off } = cfg; + let spread = calculate_spread(len, spread); + assert!(spread < len, "memmove tests should have some overlap"); + let mut buf = AlignedSlice::new_zeroed(len + spread, off); + let mut fill: usize = 0; + buf[..len].fill_with(|| { + fill += 1; + fill as u8 + }); + (len, spread, buf) + } + + pub fn setup_backward(cfg: Cfg) -> (usize, usize, AlignedSlice) { + let Cfg { len, spread, off } = cfg; + let spread = calculate_spread(len, spread); + assert!(spread < len, "memmove tests should have some overlap"); + let mut buf = AlignedSlice::new_zeroed(len + spread, off); + let mut fill: usize = 0; + buf[spread..].fill_with(|| { + fill += 1; + fill as u8 + }); + (len, spread, buf) + } +} + +pub mod slen { + use super::*; + + pub struct Cfg { + pub len: usize, + pub offset: usize, + } + + pub fn setup(Cfg { len, offset }: Cfg) -> AlignedSlice { + assert!(len > 0, "must have one byte for the \\0"); + let mut ret = AlignedSlice::new(b'x', len, offset); + ret[len - 1] = 0; + ret + } +} + +#[test] +fn test_alignment() { + let v = AlignedSlice::new_zeroed(1, 0); + assert_eq!(v.len(), 1); + assert_eq!(v.as_ptr().addr() % PAGE_SIZE, 0); + + let v = AlignedSlice::new_zeroed(PAGE_SIZE + 1, 0); + assert_eq!(v.len(), PAGE_SIZE + 1); + assert_eq!(v.as_ptr().addr() % PAGE_SIZE, 0); + + let v = AlignedSlice::new_zeroed(1, 1); + assert_eq!(v.len(), 1); + assert_eq!(v.as_ptr().addr() % 2, 1); + + let v = AlignedSlice::new_zeroed(1, 64); + assert_eq!(v.len(), 1); + assert_eq!(v.as_ptr().addr() % 64, 0); + assert_eq!(v.as_ptr().addr() % 128, 64); +} diff --git a/library/compiler-builtins/builtins-test/tests/complex.rs b/library/compiler-builtins/builtins-test/tests/complex.rs new file mode 100644 index 0000000000000..a67a1b3c58783 --- /dev/null +++ b/library/compiler-builtins/builtins-test/tests/complex.rs @@ -0,0 +1,426 @@ +#![cfg_attr(f16_enabled, feature(f16))] +#![cfg_attr(f128_enabled, feature(f128))] +#![feature(complex_numbers)] +#![allow(unused_features)] + +mod complex { + use core::num::Complex; + + use compiler_builtins::support::Float; + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + enum Class { + /// Both components are NaN. + NaN, + /// At least one component is infinite. + Infinite, + /// Both components are zero. + Zero, + /// One component is a "regular" number, the other is NaN. + NonZeroAndNaN, + /// Both components are "regular" numbers. + NonZero, + } + + fn classify(c: Complex) -> Class { + if c.re == F::ZERO && c.im == F::ZERO { + Class::Zero + } else if c.re.is_infinite() || c.im.is_infinite() { + Class::Infinite + } else if c.re.is_nan() && c.im.is_nan() { + Class::NaN + } else if c.re.is_nan() { + if c.im == F::ZERO { + Class::NaN + } else { + Class::NonZeroAndNaN + } + } else if c.im.is_nan() { + if c.re == F::ZERO { + Class::NaN + } else { + Class::NonZeroAndNaN + } + } else { + Class::NonZero + } + } + + fn test_mul(p: Complex, q: Complex, actual: Complex, tolerance: F) -> bool { + let expected = match classify(p) { + Class::Zero => match classify(q) { + Class::Zero | Class::NonZero => Class::Zero, + Class::Infinite | Class::NaN | Class::NonZeroAndNaN => Class::NaN, + }, + + Class::NonZero => match classify(q) { + Class::Zero => Class::Zero, + Class::NonZero => { + if classify(actual) != Class::NonZero { + return true; + } + + let Complex { re: a, im: b } = p; + let Complex { re: c, im: d } = q; + + let z = Complex::new(a * c - b * d, a * d + b * c); + let r = actual; + + let diff_re = r.re - z.re; + let diff_im = r.im - z.im; + + let diff_sq = diff_re * diff_re + diff_im * diff_im; + let mag_sq = r.re * r.re + r.im * r.im; + + if diff_sq > (tolerance * tolerance) * mag_sq { + return true; + } + + return false; + } + Class::Infinite => Class::Infinite, + Class::NaN | Class::NonZeroAndNaN => Class::NaN, + }, + + Class::Infinite => match classify(q) { + Class::Zero | Class::NaN => Class::NaN, + Class::NonZero | Class::Infinite | Class::NonZeroAndNaN => Class::Infinite, + }, + + Class::NaN => Class::NaN, + + Class::NonZeroAndNaN => match classify(q) { + Class::Infinite => Class::Infinite, + Class::Zero | Class::NonZero | Class::NaN | Class::NonZeroAndNaN => Class::NaN, + }, + }; + + classify(actual) != expected + } + + fn test_div( + dividend: Complex, + divisor: Complex, + actual: Complex, + tolerance: F, + ) -> bool { + let expected = match classify(dividend) { + Class::Zero => match classify(divisor) { + Class::Zero => Class::NaN, + Class::NonZero => Class::Zero, + Class::Infinite => Class::Zero, + Class::NaN => Class::NaN, + Class::NonZeroAndNaN => Class::NaN, + }, + + Class::NonZero => match classify(divisor) { + Class::Zero => Class::Infinite, + Class::NonZero => { + if classify(actual) != Class::NonZero { + return true; + } + + let Complex { re: a, im: b } = dividend; + let Complex { re: c, im: d } = divisor; + + let denominator = c * c + d * d; + let z = Complex::new( + (a * c + b * d) / denominator, // + (b * c - a * d) / denominator, + ); + + let r = actual; + + let diff_re = r.re - z.re; + let diff_im = r.im - z.im; + + let diff_sq = diff_re * diff_re + diff_im * diff_im; + let mag_sq = r.re * r.re + r.im * r.im; + + if diff_sq > (tolerance * tolerance) * mag_sq { + return true; + } + + return false; + } + Class::Infinite => Class::Zero, + Class::NaN => Class::NaN, + Class::NonZeroAndNaN => Class::NaN, + }, + + Class::Infinite => match classify(divisor) { + Class::Zero | Class::NonZero => Class::Infinite, + Class::Infinite | Class::NaN | Class::NonZeroAndNaN => Class::NaN, + }, + + Class::NaN => Class::NaN, + + Class::NonZeroAndNaN => match classify(divisor) { + Class::Zero => Class::Infinite, + Class::NonZero | Class::Infinite | Class::NaN | Class::NonZeroAndNaN => Class::NaN, + }, + }; + + classify(actual) != expected + } + + macro_rules! complex_test_data { + ($f:ty) => {{ + const INFINITY: $f = <$f>::INFINITY; + const NEG_INFINITY: $f = <$f>::NEG_INFINITY; + const NAN: $f = <$f>::NAN; + const SNAN: $f = <$f>::SNAN; + + #[allow(overflowing_literals)] + let (small, big) = if size_of::<$f>() == 2 { + (1.0e-2, 1.0e2) + } else { + (1.0e-6, 1.0e6) + }; + + [ + Complex::new(small, small), + Complex::new(-small, small), + Complex::new(-small, -small), + Complex::new(small, -small), + Complex::new(big, small), + Complex::new(-big, small), + Complex::new(-big, -small), + Complex::new(big, -small), + Complex::new(small, big), + Complex::new(-small, big), + Complex::new(-small, -big), + Complex::new(small, -big), + Complex::new(big, big), + Complex::new(-big, big), + Complex::new(-big, -big), + Complex::new(big, -big), + Complex::new(NAN, NAN), + Complex::new(NEG_INFINITY, NAN), + Complex::new(-2., NAN), + Complex::new(-1., NAN), + Complex::new(-0.5, NAN), + Complex::new(-0., NAN), + Complex::new(0., NAN), + Complex::new(0.5, NAN), + Complex::new(1., NAN), + Complex::new(2., NAN), + Complex::new(INFINITY, NAN), + Complex::new(NAN, NEG_INFINITY), + Complex::new(NEG_INFINITY, NEG_INFINITY), + Complex::new(-2., NEG_INFINITY), + Complex::new(-1., NEG_INFINITY), + Complex::new(-0.5, NEG_INFINITY), + Complex::new(-0., NEG_INFINITY), + Complex::new(0., NEG_INFINITY), + Complex::new(0.5, NEG_INFINITY), + Complex::new(1., NEG_INFINITY), + Complex::new(2., NEG_INFINITY), + Complex::new(INFINITY, NEG_INFINITY), + Complex::new(NAN, -2.), + Complex::new(NEG_INFINITY, -2.), + Complex::new(-2., -2.), + Complex::new(-1., -2.), + Complex::new(-0.5, -2.), + Complex::new(-0., -2.), + Complex::new(0., -2.), + Complex::new(0.5, -2.), + Complex::new(1., -2.), + Complex::new(2., -2.), + Complex::new(INFINITY, -2.), + Complex::new(NAN, -1.), + Complex::new(NEG_INFINITY, -1.), + Complex::new(-2., -1.), + Complex::new(-1., -1.), + Complex::new(-0.5, -1.), + Complex::new(-0., -1.), + Complex::new(0., -1.), + Complex::new(0.5, -1.), + Complex::new(1., -1.), + Complex::new(2., -1.), + Complex::new(INFINITY, -1.), + Complex::new(NAN, -0.5), + Complex::new(NEG_INFINITY, -0.5), + Complex::new(-2., -0.5), + Complex::new(-1., -0.5), + Complex::new(-0.5, -0.5), + Complex::new(-0., -0.5), + Complex::new(0., -0.5), + Complex::new(0.5, -0.5), + Complex::new(1., -0.5), + Complex::new(2., -0.5), + Complex::new(INFINITY, -0.5), + Complex::new(NAN, -0.), + Complex::new(NEG_INFINITY, -0.), + Complex::new(-2., -0.), + Complex::new(-1., -0.), + Complex::new(-0.5, -0.), + Complex::new(-0., -0.), + Complex::new(0., -0.), + Complex::new(0.5, -0.), + Complex::new(1., -0.), + Complex::new(2., -0.), + Complex::new(INFINITY, -0.), + Complex::new(NAN, 0.), + Complex::new(NEG_INFINITY, 0.), + Complex::new(-2., 0.), + Complex::new(-1., 0.), + Complex::new(-0.5, 0.), + Complex::new(-0., 0.), + Complex::new(0., 0.), + Complex::new(0.5, 0.), + Complex::new(1., 0.), + Complex::new(2., 0.), + Complex::new(INFINITY, 0.), + Complex::new(NAN, 0.5), + Complex::new(NEG_INFINITY, 0.5), + Complex::new(-2., 0.5), + Complex::new(-1., 0.5), + Complex::new(-0.5, 0.5), + Complex::new(-0., 0.5), + Complex::new(0., 0.5), + Complex::new(0.5, 0.5), + Complex::new(1., 0.5), + Complex::new(2., 0.5), + Complex::new(INFINITY, 0.5), + Complex::new(NAN, 1.), + Complex::new(NEG_INFINITY, 1.), + Complex::new(-2., 1.), + Complex::new(-1., 1.), + Complex::new(-0.5, 1.), + Complex::new(-0., 1.), + Complex::new(0., 1.), + Complex::new(0.5, 1.), + Complex::new(1., 1.), + Complex::new(2., 1.), + Complex::new(INFINITY, 1.), + Complex::new(NAN, 2.), + Complex::new(NEG_INFINITY, 2.), + Complex::new(-2., 2.), + Complex::new(-1., 2.), + Complex::new(-0.5, 2.), + Complex::new(-0., 2.), + Complex::new(0., 2.), + Complex::new(0.5, 2.), + Complex::new(1., 2.), + Complex::new(2., 2.), + Complex::new(INFINITY, 2.), + Complex::new(NAN, INFINITY), + Complex::new(NEG_INFINITY, INFINITY), + Complex::new(-2., INFINITY), + Complex::new(-1., INFINITY), + Complex::new(-0.5, INFINITY), + Complex::new(-0., INFINITY), + Complex::new(0., INFINITY), + Complex::new(0.5, INFINITY), + Complex::new(1., INFINITY), + Complex::new(2., INFINITY), + Complex::new(INFINITY, INFINITY), + Complex::new(INFINITY, SNAN), + ] + }}; + } + + macro_rules! complex_mul { + ($($f:ty, $fn:ident, $tolerance:literal);*;) => { + + $( + #[test] + fn $fn() { + use compiler_builtins::float::complex::mul::$fn; + + let input = complex_test_data!($f); + + for p in input { + for q in input { + let Complex{ re: a, im: b } = p; + let Complex{ re: c, im: d } = q; + + let actual = $fn(a, b, c, d); + + assert!( + !test_mul(p, q, actual, $tolerance), + "{func}({a:?}, {b:?}, {c:?}, {d:?}): incorrect ({:?}, {:?})", + actual.re, + actual.im, + func = stringify!($fn), + ); + } + } + } + )* + }; + } + + macro_rules! complex_div { + ($($f:ty, $fn:ident, $tolerance:literal);*;) => { + $( + #[test] + fn $fn() { + use compiler_builtins::float::complex::div::$fn; + + let input = complex_test_data!($f); + + for p in input { + for q in input { + let Complex{ re: a, im: b } = p; + let Complex{ re: c, im: d } = q; + + let actual = $fn(a, b, c, d); + + assert!( + !test_div(p, q, actual, $tolerance), + "{func}({a:?}, {b:?}, {c:?}, {d:?}): incorrect ({:?}, {:?})", + actual.re, + actual.im, + func = stringify!($fn), + ); + } + } + } + )* + }; + } + + #[cfg(all(f16_enabled, not(x86_no_sse2)))] + complex_mul! { + f16, __rust_mulhc3, 1.0e-3; + } + + #[cfg(all(f16_enabled, not(x86_no_sse2)))] + complex_div! { + f16, __rust_divhc3, 1.0e-3; + } + + complex_mul! { + f32, __rust_mulsc3, 1.0e-6; + f64, __rust_muldc3, 1.0e-9; + } + + complex_div! { + f32, __rust_divsc3, 1.0e-6; + f64, __rust_divdc3, 1.0e-9; + } + + #[cfg(f128_enabled)] + cfg_select! { + any(target_arch = "powerpc", target_arch = "powerpc64") => { + complex_mul! { + f128, __rust_mulkc3, 1.0e-12; + } + + complex_div! { + f128, __rust_divkc3, 1.0e-12; + } + } + _ => { + complex_mul! { + f128, __rust_multc3, 1.0e-12; + } + + complex_div! { + f128, __rust_divtc3, 1.0e-12; + } + } + } +} diff --git a/library/compiler-builtins/builtins-test/tests/mem.rs b/library/compiler-builtins/builtins-test/tests/mem.rs index d838ef159a024..a10dddbd19c1f 100644 --- a/library/compiler-builtins/builtins-test/tests/mem.rs +++ b/library/compiler-builtins/builtins-test/tests/mem.rs @@ -1,5 +1,4 @@ -extern crate compiler_builtins; -use compiler_builtins::mem::{memcmp, memcpy, memmove, memset}; +use compiler_builtins::mem::{memcmp, memcpy, memmove, memset, strlen}; const WORD_SIZE: usize = core::mem::size_of::(); @@ -284,3 +283,13 @@ fn memset_backward_aligned() { assert_eq!(arr.0, reference.0); } } + +#[test] +fn test_strlen() { + unsafe { + let s = c""; + assert_eq!(strlen(s.as_ptr()), 0); + let s = c"hello, world!"; + assert_eq!(strlen(s.as_ptr()), 13); + } +} diff --git a/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch b/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch deleted file mode 100644 index 13f4bc31d08f7..0000000000000 --- a/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 849c51e082b0958524246a0a880f46d468a55147 Mon Sep 17 00:00:00 2001 -From: Trevor Gross -Date: Thu, 6 Aug 2026 09:08:27 -0400 -Subject: [PATCH] [compiler-rt] Disable executable stack on - `aeabi_u{read,write}*.S` (#214465) - -These were missing `NO_EXEC_STACK_DIRECTIVE` to add `.note.GNU-stack`; -without it, a binary including any of these files will have the stack -marked executable. Add the directive here, matching other similar files. - -Symtab diff before: - -$ clang compiler-rt/lib/builtins/arm/aeabi_uread4.S ---target=arm-unknown-linux-gnueabi -c - $ llvm-readelf aeabi_uread4.o -S - There are 5 section headers, starting at offset 0xe4: - - Section Headers: -[Nr] Name Type Address Off Size ES Flg Lk Inf Al -[ 0] NULL 00000000 000000 000000 00 0 0 0 -[ 1] .strtab STRTAB 00000000 0000a8 000039 00 0 0 1 -[ 2] .text PROGBITS 00000000 000034 000020 00 AX 0 0 4 -[ 3] .ARM.attributes ARM_ATTRIBUTES 00000000 000054 000022 00 0 0 1 -[ 4] .symtab SYMTAB 00000000 000078 000030 10 1 2 4 - -After: - -$ clang compiler-rt/lib/builtins/arm/aeabi_uread4.S ---target=arm-unknown-linux-gnueabi -c - $ llvm-readelf aeabi_uread4.o -S - There are 6 section headers, starting at offset 0xf4: - - Section Headers: -[Nr] Name Type Address Off Size ES Flg Lk Inf Al -[ 0] NULL 00000000 000000 000000 00 0 0 0 -[ 1] .strtab STRTAB 00000000 0000a8 000049 00 0 0 1 -[ 2] .text PROGBITS 00000000 000034 000020 00 AX 0 0 4 -[ 3] .note.GNU-stack PROGBITS 00000000 000054 000000 00 0 0 1 -[ 4] .ARM.attributes ARM_ATTRIBUTES 00000000 000054 000022 00 0 0 1 -[ 5] .symtab SYMTAB 00000000 000078 000030 10 1 2 4 - -Fixes: 39413af931a7 ("[Compiler-rt] Implement AEABI Unaligned Read/Write - Helpers in compiler-rt (#167913)") ---- - -Add this patch to avoid a symcheck failure until the LLVM update can work -through. - - compiler-rt/lib/builtins/arm/aeabi_uread4.S | 1 + - compiler-rt/lib/builtins/arm/aeabi_uread8.S | 2 ++ - compiler-rt/lib/builtins/arm/aeabi_uwrite4.S | 2 ++ - compiler-rt/lib/builtins/arm/aeabi_uwrite8.S | 2 ++ - 4 files changed, 7 insertions(+) - -diff --git a/compiler-rt/lib/builtins/arm/aeabi_uread4.S b/compiler-rt/lib/builtins/arm/aeabi_uread4.S -index 4a54890fdf83..05e476a17905 100644 ---- a/compiler-rt/lib/builtins/arm/aeabi_uread4.S -+++ b/compiler-rt/lib/builtins/arm/aeabi_uread4.S -@@ -61,3 +61,4 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uread4) - #endif - END_COMPILERRT_FUNCTION(__aeabi_uread4) - -+NO_EXEC_STACK_DIRECTIVE -diff --git a/compiler-rt/lib/builtins/arm/aeabi_uread8.S b/compiler-rt/lib/builtins/arm/aeabi_uread8.S -index 32844b8b3c7e..0b12c48ae46f 100644 ---- a/compiler-rt/lib/builtins/arm/aeabi_uread8.S -+++ b/compiler-rt/lib/builtins/arm/aeabi_uread8.S -@@ -98,3 +98,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uread8) - #endif - - END_COMPILERRT_FUNCTION(__aeabi_uread8) -+ -+NO_EXEC_STACK_DIRECTIVE -diff --git a/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S b/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S -index 9f749695910b..7e9a0337b781 100644 ---- a/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S -+++ b/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S -@@ -33,3 +33,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uwrite4) - #endif - bx lr - END_COMPILERRT_FUNCTION(__aeabi_uwrite4) -+ -+NO_EXEC_STACK_DIRECTIVE -diff --git a/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S b/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S -index 8188032fc3bd..763f42ff7ed0 100644 ---- a/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S -+++ b/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S -@@ -49,3 +49,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uwrite8) - #endif - bx lr - END_COMPILERRT_FUNCTION(__aeabi_uwrite8) -+ -+NO_EXEC_STACK_DIRECTIVE --- -2.50.1 (Apple Git-155) diff --git a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 30a13fc5de910..555191eedecb6 100644 --- a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,10 +1,14 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-aarch64-linux-gnu m4 make libc6-dev-arm64-cross \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-aarch64-linux-gnu \ + libc6-dev \ + libc6-dev-arm64-cross \ + m4 \ + make \ qemu-user ENV TOOLCHAIN_PREFIX=aarch64-linux-gnu- @@ -12,5 +16,4 @@ ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64 \ AR_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/aarch64-linux-gnu diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile index 41ff36a49e3bb..a23e3526855f9 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -1,15 +1,17 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-arm-linux-gnueabi \ + libc6-dev \ + libc6-dev-armel-cross \ + qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabi- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/arm-linux-gnueabi \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/arm-linux-gnueabi diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile index 1fad72c470f03..003cc64c8ddc6 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -1,15 +1,17 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-arm-linux-gnueabihf \ + libc6-dev \ + libc6-dev-armhf-cross \ + qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf diff --git a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile index 039ccd5745256..391096e01c8a6 100644 --- a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -1,15 +1,17 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-arm-linux-gnueabihf \ + libc6-dev \ + libc6-dev-armhf-cross \ + qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf diff --git a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile index 9319e73dd03f0..8c0aea18a66bd 100644 --- a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -1,6 +1,9 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc-multilib m4 make libc6-dev ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc-multilib \ + libc6-dev \ + m4 \ + make diff --git a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile index 9319e73dd03f0..8c0aea18a66bd 100644 --- a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,6 +1,9 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc-multilib m4 make libc6-dev ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc-multilib \ + libc6-dev \ + m4 \ + make diff --git a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index 442a13164880c..0684b7cc4bb63 100644 --- a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -1,14 +1,16 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user ca-certificates \ - gcc-14-loongarch64-linux-gnu libc6-dev-loong64-cross +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-14-loongarch64-linux-gnu \ + libc6-dev \ + libc6-dev-loong64-cross \ + qemu-user ENV CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER=loongarch64-linux-gnu-gcc-14 \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-loongarch64 \ AR_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-ar \ CC_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-gcc-14 \ - QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu diff --git a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile index 9941a8c2736c0..690d878a23ef1 100644 --- a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -1,16 +1,19 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-mips-linux-gnu libc6-dev-mips-cross \ - binfmt-support qemu-user qemu-system-mips +RUN apt-get update && apt-get install -y --no-install-recommends \ + binfmt-support \ + ca-certificates \ + gcc \ + gcc-mips-linux-gnu \ + libc6-dev \ + libc6-dev-mips-cross \ + qemu-system-mips \ + qemu-user ENV TOOLCHAIN_PREFIX=mips-linux-gnu- ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips \ AR_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/mips-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/mips-linux-gnu diff --git a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile index c20d0a77b81c3..6ff8effb8570d 100644 --- a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -1,20 +1,18 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ gcc \ gcc-mips64-linux-gnuabi64 \ libc6-dev \ libc6-dev-mips64-cross \ - qemu-user \ qemu-system-mips + qemu-user \ ENV TOOLCHAIN_PREFIX=mips64-linux-gnuabi64- ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64 \ AR_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 diff --git a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile index 584f7ffff45a5..445fec6786d32 100644 --- a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -1,8 +1,7 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ gcc \ gcc-mips64el-linux-gnuabi64 \ @@ -15,5 +14,4 @@ ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el \ AR_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 diff --git a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile index ead99bb9c1132..6d4dc124443b8 100644 --- a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile @@ -1,16 +1,18 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ - binfmt-support qemu-user +RUN apt-get update && apt-get install -y --no-install-recommends \ + binfmt-support \ + ca-certificates \ + gcc \ + gcc-mipsel-linux-gnu \ + libc6-dev \ + libc6-dev-mipsel-cross \ + qemu-user ENV TOOLCHAIN_PREFIX=mipsel-linux-gnu- ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel \ AR_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/mipsel-linux-gnu diff --git a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile index 74071874ed7cf..025ba1a7c419a 100644 --- a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -1,16 +1,18 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user ca-certificates \ - gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ - qemu-system-ppc +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-powerpc-linux-gnu \ + libc6-dev \ + libc6-dev-powerpc-cross \ + qemu-system-ppc \ + qemu-user ENV TOOLCHAIN_PREFIX=powerpc-linux-gnu- ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc \ AR_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/powerpc-linux-gnu diff --git a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile index ba4fec7160b64..fc6e011aaae58 100644 --- a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -1,16 +1,19 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ - gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ - binfmt-support qemu-user qemu-system-ppc +RUN apt-get update && apt-get install -y --no-install-recommends \ + binfmt-support \ + ca-certificates \ + gcc \ + gcc-powerpc64-linux-gnu \ + libc6-dev \ + libc6-dev-ppc64-cross \ + qemu-system-ppc \ + qemu-user ENV TOOLCHAIN_PREFIX=powerpc64-linux-gnu- ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64 \ AR_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu diff --git a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile index e90d4c8812042..0913b2a609349 100644 --- a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -1,16 +1,18 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user ca-certificates \ - gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ - qemu-system-ppc +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-powerpc64le-linux-gnu \ + libc6-dev \ + libc6-dev-ppc64el-cross \ + qemu-system-ppc \ + qemu-user ENV TOOLCHAIN_PREFIX=powerpc64le-linux-gnu- ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le \ AR_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu diff --git a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile index 96442121bcd9e..af8e0f3d4733a 100644 --- a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -1,16 +1,18 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user ca-certificates \ - gcc-riscv64-linux-gnu libc6-dev-riscv64-cross \ - qemu-system-riscv +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + gcc-riscv64-linux-gnu \ + libc6-dev \ + libc6-dev-riscv64-cross \ + qemu-system-riscv \ + qemu-user ENV TOOLCHAIN_PREFIX=riscv64-linux-gnu- ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64 \ AR_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ - QEMU_LD_PREFIX=/usr/riscv64-linux-gnu \ - RUST_TEST_THREADS=1 + QEMU_LD_PREFIX=/usr/riscv64-linux-gnu diff --git a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile index 463cce94e5540..d77fb4fc60db5 100644 --- a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile @@ -1,9 +1,10 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ gcc-arm-none-eabi \ + libc6-dev \ libnewlib-arm-none-eabi ENV BUILD_ONLY=1 diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile index 463cce94e5540..d77fb4fc60db5 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile @@ -1,9 +1,10 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ gcc-arm-none-eabi \ + libc6-dev \ libnewlib-arm-none-eabi ENV BUILD_ONLY=1 diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile index 463cce94e5540..d77fb4fc60db5 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile @@ -1,9 +1,10 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ gcc-arm-none-eabi \ + libc6-dev \ libnewlib-arm-none-eabi ENV BUILD_ONLY=1 diff --git a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile index 463cce94e5540..d77fb4fc60db5 100644 --- a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile @@ -1,9 +1,10 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libc6-dev ca-certificates \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ gcc-arm-none-eabi \ + libc6-dev \ libnewlib-arm-none-eabi ENV BUILD_ONLY=1 diff --git a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile index 09f35c3b128d0..0e203d20700ac 100644 --- a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile +++ b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile @@ -1,8 +1,10 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc clang libc6-dev ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + clang \ + gcc \ + libc6-dev ENV CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=true diff --git a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index 103c395ee8496..1cf59a802511a 100644 --- a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,6 +1,9 @@ ARG IMAGE=ubuntu:26.04 FROM $IMAGE -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc m4 make libc6-dev ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + gcc \ + libc6-dev \ + m4 \ + make diff --git a/library/compiler-builtins/ci/download-compiler-rt.sh b/library/compiler-builtins/ci/download-compiler-rt.sh index 55498c61d54b4..414e75c0dd6b7 100755 --- a/library/compiler-builtins/ci/download-compiler-rt.sh +++ b/library/compiler-builtins/ci/download-compiler-rt.sh @@ -8,9 +8,3 @@ rust_llvm_version=23.1-2026-07-22 curl -L --retry 3 -o code.tar.gz "https://github.com/rust-lang/llvm-project/archive/rustc/${rust_llvm_version}.tar.gz" tar xzf code.tar.gz --strip-components 1 llvm-project-rustc-${rust_llvm_version}/compiler-rt - -cd compiler-rt - -for p in ../ci/compiler-rt-patches/*; do - cat "$p" | patch -p 2 -done diff --git a/library/compiler-builtins/ci/install-test-deps.sh b/library/compiler-builtins/ci/install-test-deps.sh new file mode 100755 index 0000000000000..7321e4c5d5440 --- /dev/null +++ b/library/compiler-builtins/ci/install-test-deps.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -eux + +target="${1}" + +# Allow setting a channel to account for required components (MinGW) +channel="${2:-nightly}" + +# Some runners (native ppc and s390x, self-hosted) don't have all the dependencies +# we need, so we need to install them. + +needed_deps=() +to_install=() + +if [ "$RUN_IN_DOCKER" != "0" ]; then + needed_deps+=(rustup m4) +fi + +for dep in "${needed_deps[@]}"; do + ! command -v "$dep" && to_install+=("$dep") +done + +if [ ${#to_install[@]} -ne 0 ]; then + if command -v apt-get; then + sudo apt-get update + sudo apt-get install -y "${to_install[@]}" + elif command -v apk; then + doas apk add "${to_install[@]}" + else + echo "No package manager found" + fi +fi + +# Install the correct Rust version +rustup update "$channel" --no-self-update +rustup default "$channel" +rustup target add "$target" diff --git a/library/compiler-builtins/ci/run-docker.sh b/library/compiler-builtins/ci/run-docker.sh index 08f20b934acd5..5bf81bce13516 100755 --- a/library/compiler-builtins/ci/run-docker.sh +++ b/library/compiler-builtins/ci/run-docker.sh @@ -58,7 +58,7 @@ run() { "IMAGE=${DOCKER_BASE_IMAGE:-rustlang/rust:nightly}" ) run_args=(-v "compiler-builtins-cache:/builtins-target") - run_cmd="$run_cmd HOME=/tmp" "USING_CONTAINER_RUSTC=1" + run_cmd="$run_cmd HOME=/tmp USING_CONTAINER_RUSTC=1" fi if [ -d compiler-rt ]; then diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index 359bf3d945b9b..22c136e2df39f 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -26,6 +26,13 @@ if [ "${USING_CONTAINER_RUSTC:-}" = 1 ]; then rustup target add "$target" fi +# Run the command with its output in a collapsable section +asgroup() { + echo "::group::$*" + "$@" + echo "::endgroup" +} + # If nextest is available, use that command -v cargo-nextest && nextest=1 || nextest=0 if [ "$nextest" = "1" ]; then @@ -57,14 +64,13 @@ else --target "$target" ) - "${test_builtins[@]}" - "${test_builtins[@]}" --release - "${test_builtins[@]}" --features c - "${test_builtins[@]}" --features c --release - "${test_builtins[@]}" --benches - "${test_builtins[@]}" --benches --release - "${test_builtins[@]}" --no-default-features - "${test_builtins[@]}" --no-default-features --release + asgroup "${test_builtins[@]}" + asgroup "${test_builtins[@]}" --release + asgroup "${test_builtins[@]}" --features c + asgroup "${test_builtins[@]}" --features c --release + asgroup "${test_builtins[@]}" --benches --release + asgroup "${test_builtins[@]}" --no-default-features + asgroup "${test_builtins[@]}" --no-default-features --release # Validate that having a verbatim path for the target directory works # (trivial to regress using `/` in paths to build artifacts rather than @@ -75,6 +81,9 @@ else fi fi + +echo "::group::Run symcheck" + # Ensure there are no duplicate symbols or references to `core` when # `compiler-builtins` is built with various features. Symcheck invokes Cargo to # build with the arguments we provide it, then validates the built artifacts. @@ -94,6 +103,11 @@ symcheck_cb_args=(-- --package compiler_builtins --features compiler-builtins) "${symcheck[@]}" "${symcheck_cb_args[@]}" --no-default-features "${symcheck[@]}" "${symcheck_cb_args[@]}" --no-default-features --release +echo "::endgroup" + + +echo "::group::Run intrinsics tests" + run_intrinsics_test() { build_args=(--verbose --manifest-path builtins-test-intrinsics/Cargo.toml) build_args+=("$@") @@ -119,6 +133,8 @@ run_intrinsics_test --features c --release CARGO_PROFILE_DEV_LTO=true run_intrinsics_test CARGO_PROFILE_RELEASE_LTO=true run_intrinsics_test --release +echo "::endgroup" + # Test libm # Make sure a simple build works @@ -190,32 +206,31 @@ else cmd=("${test_runner[@]}" "${mflags[@]}") # Test once without intrinsics - "${cmd[@]}" + asgroup "${cmd[@]}" # Run doctests if they were excluded by nextest - [ "$nextest" = "1" ] && cargo test --doc --exclude compiler_builtins "${mflags[@]}" + [ "$nextest" = "1" ] && asgroup cargo test --doc --exclude compiler_builtins "${mflags[@]}" # Exclude the macros and utile crates from the rest of the tests to save CI # runtime, they shouldn't have anything feature- or opt-level-dependent. cmd+=(--exclude util --exclude libm-macros) # Test once with intrinsics enabled - "${cmd[@]}" --features arch,unstable-intrinsics - "${cmd[@]}" --features arch,unstable-intrinsics --benches + asgroup "${cmd[@]}" --features arch,unstable-intrinsics # Test the same in release mode, which also increases coverage. Also ensure # the soft float routines are checked. - "${cmd[@]}" "$profile_flag" release-checked - "${cmd[@]}" "$profile_flag" release-checked --features arch - "${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics - "${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics --benches + asgroup "${cmd[@]}" "$profile_flag" release-checked + asgroup "${cmd[@]}" "$profile_flag" release-checked --features arch + asgroup "${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics + asgroup "${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics --benches # Ensure that the routines do not panic. # # `--tests` must be passed because no-panic is only enabled as a dev # dependency. The `release-opt` profile must be used to enable LTO and a # single CGU. - ENSURE_NO_PANIC=1 cargo build \ + ENSURE_NO_PANIC=1 asgroup cargo build \ -p libm \ --target "$target" \ --no-default-features \ diff --git a/library/compiler-builtins/compiler-builtins/README.md b/library/compiler-builtins/compiler-builtins/README.md index 63cbf33d2aea2..72faec3dc5c97 100644 --- a/library/compiler-builtins/compiler-builtins/README.md +++ b/library/compiler-builtins/compiler-builtins/README.md @@ -174,6 +174,15 @@ of being added to Rust. - [x] trunctfhf2.c - [x] trunctfsf2.c +These builtins involve complex floating-point types that are in the process of +being added to Rust. + +- [x] divdc3.c +- [x] divsc3.c +- [x] divtc3.c +- [x] muldc3.c +- [x] mulsc3.c +- [x] multc3.c These builtins are used by the Hexagon DSP @@ -223,6 +232,12 @@ by Rust. - ~~i386/floatundixf.S~~ - ~~x86_64/floatdixf.c~~ - ~~x86_64/floatundixf.S~~ +- ~~powixf2.c~~ + +These builtins are for complex X87 `f80` floating-point numbers. + +- ~~divxc3.c~~ +- ~~mulxc3.c~~ These builtins are for IBM "extended double" non-IEEE 128-bit floating-point numbers. @@ -248,19 +263,6 @@ supported by Rust. - ~~truncsfbf2.c~~ - ~~trunctfxf2.c~~ -These builtins involve complex floating-point types that are not supported by -Rust. - -- ~~divdc3.c~~ -- ~~divsc3.c~~ -- ~~divtc3.c~~ -- ~~divxc3.c~~ -- ~~muldc3.c~~ -- ~~mulsc3.c~~ -- ~~multc3.c~~ -- ~~mulxc3.c~~ -- ~~powixf2.c~~ - These builtins are never called by LLVM. - ~~absvdi2.c~~ diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs index 8869add9f5ee4..64a4e3b6c9e9c 100644 --- a/library/compiler-builtins/compiler-builtins/build.rs +++ b/library/compiler-builtins/compiler-builtins/build.rs @@ -297,14 +297,7 @@ mod c { ]); if consider_float_intrinsics { - sources.extend(&[ - ("__divdc3", "divdc3.c"), - ("__divsc3", "divsc3.c"), - ("__muldc3", "muldc3.c"), - ("__mulsc3", "mulsc3.c"), - ("__negdf2", "negdf2.c"), - ("__negsf2", "negsf2.c"), - ]); + sources.extend(&[("__negdf2", "negdf2.c"), ("__negsf2", "negsf2.c")]); } // On iOS and 32-bit OSX these are all just empty intrinsics, no need to @@ -460,10 +453,6 @@ mod c { ("__fe_getround", "fp_mode.c"), ("__fe_raise_inexact", "fp_mode.c"), ]); - - if cfg.target_os != "windows" && cfg.target_os != "cygwin" { - sources.extend(&[("__multc3", "multc3.c")]); - } } if cfg.target_arch == "mips" || cfg.target_arch == "riscv32" || cfg.target_arch == "riscv64" diff --git a/library/compiler-builtins/compiler-builtins/src/float/add.rs b/library/compiler-builtins/compiler-builtins/src/float/add.rs index 69de07372f16e..6503bc37dd75f 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/add.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/add.rs @@ -195,19 +195,17 @@ intrinsics! { add(a, b) } - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fadd] pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 { add(a, b) } - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_dadd] pub extern "C" fn __adddf3(a: f64, b: f64) -> f64 { add(a, b) } - #[ppc_alias = __addkf3] + #[ppc_name = __addkf3] #[cfg(f128_enabled)] pub extern "C" fn __addtf3(a: f128, b: f128) -> f128 { add(a, b) diff --git a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs index 243c9c767f61b..a5ce9a2113b4d 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs @@ -227,37 +227,37 @@ intrinsics! { #[cfg(f128_enabled)] intrinsics! { - #[ppc_alias = __lekf2] + #[ppc_name = __lekf2] pub extern "C" fn __letf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_default_cmp_result() } - #[ppc_alias = __gekf2] + #[ppc_name = __gekf2] pub extern "C" fn __getf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_gt_ge_cmp_result() } - #[ppc_alias = __unordkf2] + #[ppc_name = __unordkf2] pub extern "C" fn __unordtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { unord(a, b) as crate::float::cmp::CmpResult } - #[ppc_alias = __eqkf2] + #[ppc_name = __eqkf2] pub extern "C" fn __eqtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_default_cmp_result() } - #[ppc_alias = __ltkf2] + #[ppc_name = __ltkf2] pub extern "C" fn __lttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_default_cmp_result() } - #[ppc_alias = __nekf2] + #[ppc_name = __nekf2] pub extern "C" fn __netf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_default_cmp_result() } - #[ppc_alias = __gtkf2] + #[ppc_name = __gtkf2] pub extern "C" fn __gttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult { cmp(a, b).to_gt_ge_cmp_result() } diff --git a/library/compiler-builtins/compiler-builtins/src/float/complex/div.rs b/library/compiler-builtins/compiler-builtins/src/float/complex/div.rs new file mode 100644 index 0000000000000..4a8d6b7231c67 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/float/complex/div.rs @@ -0,0 +1,74 @@ +use core::num::Complex; + +use crate::math::libm_math::generic::{fmax, ilogb, scalbn}; +use crate::support::{CastInto, Float}; + +/// Returns the quotient of `(a + ib)` and `(c + id)`. +/// +/// This implementation uses the standard formula, but has special behavior when the output +/// of that formula has both a real and imaginary component that are NaN. +fn complex_div(mut a: F, mut b: F, mut c: F, mut d: F) -> Complex +where + u32: CastInto, +{ + let max = fmax(c.abs(), d.abs()); + let mut ilogbw = 0; + if max.is_finite() && max != F::ZERO { + ilogbw = ilogb(max); + c = scalbn(c, -ilogbw); + d = scalbn(d, -ilogbw); + } + + let denom = c * c + d * d; + let mut z = Complex::new( + scalbn((a * c + b * d) / denom, -ilogbw), + scalbn((b * c - a * d) / denom, -ilogbw), + ); + + // The fast path: exit when at least one component is not NaN. + if !(z.re.is_nan() && z.im.is_nan()) { + return z; + } + + let signed_unit_if_inf = |x: F| { + let mag = if x.is_infinite() { F::ONE } else { F::ZERO }; + mag.copysign(x) + }; + + if denom == F::ZERO && (!a.is_nan() || !b.is_nan()) { + z.re = F::INFINITY.copysign(c) * a; + z.im = F::INFINITY.copysign(c) * b; + } else if (a.is_infinite() || b.is_infinite()) && c.is_finite() && d.is_finite() { + a = signed_unit_if_inf(a); + b = signed_unit_if_inf(b); + z.re = F::INFINITY * (a * c + b * d); + z.im = F::INFINITY * (b * c - a * d); + } else if max.is_infinite() && a.is_finite() && b.is_finite() { + c = signed_unit_if_inf(c); + d = signed_unit_if_inf(d); + z.re = F::ZERO * (a * c + b * d); + z.im = F::ZERO * (b * c - a * d); + } + + z +} + +intrinsics! { + #[cfg(all(f16_enabled, not(x86_no_sse2)))] + pub extern "C" fn __rust_divhc3(a: f16, b: f16, c: f16, d: f16) -> core::num::Complex { + complex_div(a, b, c, d) + } + + pub extern "C" fn __rust_divsc3(a: f32, b: f32, c: f32, d: f32) -> core::num::Complex { + complex_div(a, b, c, d) + } + + pub extern "C" fn __rust_divdc3(a: f64, b: f64, c: f64, d: f64) -> core::num::Complex { + complex_div(a, b, c, d) + } + + #[cfg(f128_enabled)] + pub extern "C" fn __rust_divtc3(a: f128, b: f128, c: f128, d: f128) -> core::num::Complex { + complex_div(a, b, c, d) + } +} diff --git a/library/compiler-builtins/compiler-builtins/src/float/complex/mod.rs b/library/compiler-builtins/compiler-builtins/src/float/complex/mod.rs new file mode 100644 index 0000000000000..5e67fbb85b206 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/float/complex/mod.rs @@ -0,0 +1,2 @@ +pub mod div; +pub mod mul; diff --git a/library/compiler-builtins/compiler-builtins/src/float/complex/mul.rs b/library/compiler-builtins/compiler-builtins/src/float/complex/mul.rs new file mode 100644 index 0000000000000..66c5d42baab3b --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/float/complex/mul.rs @@ -0,0 +1,80 @@ +use core::num::Complex; + +use crate::support::Float; + +/// Returns the product of `a + ib` and `c + id`. +/// +/// The standard formula is `(ac - bd) + (ad + bc)i`, but this function has custom behavior when +/// both the real and imaginary components of that expression are NaN. +fn complex_mul(mut a: F, mut b: F, mut c: F, mut d: F) -> Complex { + let ac = a * c; + let bd = b * d; + let ad = a * d; + let bc = b * c; + + let z = Complex::new(ac - bd, ad + bc); + + // The fast path: exit when at least one component is not NaN. + if !(z.re.is_nan() && z.im.is_nan()) { + return z; + } + + let zero_if_nan = |x: F| if x.is_nan() { F::ZERO.copysign(x) } else { x }; + + let signed_unit_if_inf = |x: F| { + let mag = if x.is_infinite() { F::ONE } else { F::ZERO }; + mag.copysign(x) + }; + + let mut recalc = false; + + if a.is_infinite() || b.is_infinite() { + a = signed_unit_if_inf(a); + b = signed_unit_if_inf(b); + c = zero_if_nan(c); + d = zero_if_nan(d); + recalc = true; + } + + if c.is_infinite() || d.is_infinite() { + c = signed_unit_if_inf(c); + d = signed_unit_if_inf(d); + a = zero_if_nan(a); + b = zero_if_nan(b); + recalc = true; + } + + if !recalc && (ac.is_infinite() || bd.is_infinite() || ad.is_infinite() || bc.is_infinite()) { + a = zero_if_nan(a); + b = zero_if_nan(b); + c = zero_if_nan(c); + d = zero_if_nan(d); + recalc = true; + } + + if !recalc { + return z; + } + + Complex::new(F::INFINITY * (a * c - b * d), F::INFINITY * (a * d + b * c)) +} + +intrinsics! { + #[cfg(all(f16_enabled, not(x86_no_sse2)))] + pub extern "C" fn __rust_mulhc3(a: f16, b: f16, c: f16, d: f16) -> core::num::Complex { + complex_mul(a, b, c, d) + } + + pub extern "C" fn __rust_mulsc3(a: f32, b: f32, c: f32, d: f32) -> core::num::Complex { + complex_mul(a, b, c, d) + } + + pub extern "C" fn __rust_muldc3(a: f64, b: f64, c: f64, d: f64) -> core::num::Complex { + complex_mul(a, b, c, d) + } + + #[cfg(f128_enabled)] + pub extern "C" fn __rust_multc3(a: f128, b: f128, c: f128, d: f128) -> core::num::Complex { + complex_mul(a, b, c, d) + } +} diff --git a/library/compiler-builtins/compiler-builtins/src/float/conv.rs b/library/compiler-builtins/compiler-builtins/src/float/conv.rs index 6193aa416e222..13a0ed4fcd39f 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/conv.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/conv.rs @@ -248,19 +248,19 @@ intrinsics! { f64::from_bits(int_to_float::u128_to_f64_bits((u128::from(hi) << 64) | u128::from(lo))) } - #[ppc_alias = __floatunsikf] + #[ppc_name = __floatunsikf] #[cfg(f128_enabled)] pub extern "C" fn __floatunsitf(i: u32) -> f128 { f128::from_bits(int_to_float::u32_to_f128_bits(i)) } - #[ppc_alias = __floatundikf] + #[ppc_name = __floatundikf] #[cfg(f128_enabled)] pub extern "C" fn __floatunditf(i: u64) -> f128 { f128::from_bits(int_to_float::u64_to_f128_bits(i)) } - #[ppc_alias = __floatuntikf] + #[ppc_name = __floatuntikf] #[cfg(f128_enabled)] pub extern "C" fn __floatuntitf(i: u128) -> f128 { f128::from_bits(int_to_float::u128_to_f128_bits(i)) @@ -309,19 +309,19 @@ intrinsics! { int_to_float::signed((i128::from(hi) << 64) | i128::from(lo), int_to_float::u128_to_f64_bits) } - #[ppc_alias = __floatsikf] + #[ppc_name = __floatsikf] #[cfg(f128_enabled)] pub extern "C" fn __floatsitf(i: i32) -> f128 { int_to_float::signed(i, int_to_float::u32_to_f128_bits) } - #[ppc_alias = __floatdikf] + #[ppc_name = __floatdikf] #[cfg(f128_enabled)] pub extern "C" fn __floatditf(i: i64) -> f128 { int_to_float::signed(i, int_to_float::u64_to_f128_bits) } - #[ppc_alias = __floattikf] + #[ppc_name = __floattikf] #[cfg(f128_enabled)] pub extern "C" fn __floattitf(i: i128) -> f128 { int_to_float::signed(i, int_to_float::u128_to_f128_bits) @@ -439,19 +439,19 @@ intrinsics! { float_to_unsigned_int(f) } - #[ppc_alias = __fixunskfsi] + #[ppc_name = __fixunskfsi] #[cfg(f128_enabled)] pub extern "C" fn __fixunstfsi(f: f128) -> u32 { float_to_unsigned_int(f) } - #[ppc_alias = __fixunskfdi] + #[ppc_name = __fixunskfdi] #[cfg(f128_enabled)] pub extern "C" fn __fixunstfdi(f: f128) -> u64 { float_to_unsigned_int(f) } - #[ppc_alias = __fixunskfti] + #[ppc_name = __fixunskfti] #[cfg(f128_enabled)] pub extern "C" fn __fixunstfti(f: f128) -> u128 { float_to_unsigned_int(f) @@ -488,19 +488,19 @@ intrinsics! { float_to_signed_int(f) } - #[ppc_alias = __fixkfsi] + #[ppc_name = __fixkfsi] #[cfg(f128_enabled)] pub extern "C" fn __fixtfsi(f: f128) -> i32 { float_to_signed_int(f) } - #[ppc_alias = __fixkfdi] + #[ppc_name = __fixkfdi] #[cfg(f128_enabled)] pub extern "C" fn __fixtfdi(f: f128) -> i64 { float_to_signed_int(f) } - #[ppc_alias = __fixkfti] + #[ppc_name = __fixkfti] #[cfg(f128_enabled)] pub extern "C" fn __fixtfti(f: f128) -> i128 { float_to_signed_int(f) diff --git a/library/compiler-builtins/compiler-builtins/src/float/div.rs b/library/compiler-builtins/compiler-builtins/src/float/div.rs index 419d8ad5e7061..1438ca687be0d 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/div.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/div.rs @@ -615,7 +615,7 @@ intrinsics! { div(a, b) } - #[ppc_alias = __divkf3] + #[ppc_name = __divkf3] #[cfg(f128_enabled)] pub extern "C" fn __divtf3(a: f128, b: f128) -> f128 { div(a, b) diff --git a/library/compiler-builtins/compiler-builtins/src/float/extend.rs b/library/compiler-builtins/compiler-builtins/src/float/extend.rs index 58038ce57f834..b0f5cdd6534de 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/extend.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/extend.rs @@ -69,7 +69,6 @@ where } intrinsics! { - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_f2d] pub extern "C" fn __extendsfdf2(a: f32) -> f64 { extend(a) @@ -77,7 +76,6 @@ intrinsics! { } intrinsics! { - #[aapcs_on_arm] #[apple_f16_arg_abi] #[arm_aeabi_alias = __aeabi_h2f] #[cfg(f16_enabled)] @@ -85,36 +83,31 @@ intrinsics! { extend(a) } - #[aapcs_on_arm] #[apple_f16_arg_abi] #[cfg(f16_enabled)] pub extern "C" fn __gnu_h2f_ieee(a: f16) -> f32 { extend(a) } - #[aapcs_on_arm] #[apple_f16_arg_abi] #[cfg(f16_enabled)] pub extern "C" fn __extendhfdf2(a: f16) -> f64 { extend(a) } - #[aapcs_on_arm] - #[ppc_alias = __extendhfkf2] + #[ppc_name = __extendhfkf2] #[cfg(all(f16_enabled, f128_enabled))] pub extern "C" fn __extendhftf2(a: f16) -> f128 { extend(a) } - #[aapcs_on_arm] - #[ppc_alias = __extendsfkf2] + #[ppc_name = __extendsfkf2] #[cfg(f128_enabled)] pub extern "C" fn __extendsftf2(a: f32) -> f128 { extend(a) } - #[aapcs_on_arm] - #[ppc_alias = __extenddfkf2] + #[ppc_name = __extenddfkf2] #[cfg(f128_enabled)] pub extern "C" fn __extenddftf2(a: f64) -> f128 { extend(a) diff --git a/library/compiler-builtins/compiler-builtins/src/float/mod.rs b/library/compiler-builtins/compiler-builtins/src/float/mod.rs index 15318c4928804..df45d0603fc14 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/mod.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/mod.rs @@ -1,5 +1,6 @@ pub mod add; pub mod cmp; +pub mod complex; pub mod conv; pub mod div; pub mod extend; diff --git a/library/compiler-builtins/compiler-builtins/src/float/mul.rs b/library/compiler-builtins/compiler-builtins/src/float/mul.rs index ffba2dc41f8a0..1d5eb1a032d29 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/mul.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/mul.rs @@ -184,19 +184,17 @@ intrinsics! { mul(a, b) } - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_fmul] pub extern "C" fn __mulsf3(a: f32, b: f32) -> f32 { mul(a, b) } - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_dmul] pub extern "C" fn __muldf3(a: f64, b: f64) -> f64 { mul(a, b) } - #[ppc_alias = __mulkf3] + #[ppc_name = __mulkf3] #[cfg(f128_enabled)] pub extern "C" fn __multf3(a: f128, b: f128) -> f128 { mul(a, b) diff --git a/library/compiler-builtins/compiler-builtins/src/float/pow.rs b/library/compiler-builtins/compiler-builtins/src/float/pow.rs index 2c92971d31397..50a27055a849f 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/pow.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/pow.rs @@ -29,7 +29,7 @@ intrinsics! { pow(a, b) } - #[ppc_alias = __powikf2] + #[ppc_name = __powikf2] #[cfg(f128_enabled)] pub extern "C" fn __powitf2(a: f128, b: i32) -> f128 { pow(a, b) diff --git a/library/compiler-builtins/compiler-builtins/src/float/sub.rs b/library/compiler-builtins/compiler-builtins/src/float/sub.rs index 11dd3b77d5d1c..7028b2ff8a80c 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/sub.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/sub.rs @@ -16,7 +16,7 @@ intrinsics! { crate::float::add::__adddf3(a, f64::from_bits(b.to_bits() ^ f64::SIGN_MASK)) } - #[ppc_alias = __subkf3] + #[ppc_name = __subkf3] #[cfg(f128_enabled)] pub extern "C" fn __subtf3(a: f128, b: f128) -> f128 { #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] diff --git a/library/compiler-builtins/compiler-builtins/src/float/trunc.rs b/library/compiler-builtins/compiler-builtins/src/float/trunc.rs index 1a88b0649fda3..1bac7b0957cd5 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/trunc.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/trunc.rs @@ -114,7 +114,6 @@ where } intrinsics! { - #[aapcs_on_arm] #[arm_aeabi_alias = __aeabi_d2f] pub extern "C" fn __truncdfsf2(a: f64) -> f32 { trunc(a) @@ -122,7 +121,6 @@ intrinsics! { } intrinsics! { - #[aapcs_on_arm] #[apple_f16_ret_abi] #[arm_aeabi_alias = __aeabi_f2h] #[cfg(f16_enabled)] @@ -130,14 +128,12 @@ intrinsics! { trunc(a) } - #[aapcs_on_arm] #[apple_f16_ret_abi] #[cfg(f16_enabled)] pub extern "C" fn __gnu_f2h_ieee(a: f32) -> f16 { trunc(a) } - #[aapcs_on_arm] #[apple_f16_ret_abi] #[arm_aeabi_alias = __aeabi_d2h] #[cfg(f16_enabled)] @@ -145,22 +141,19 @@ intrinsics! { trunc(a) } - #[aapcs_on_arm] - #[ppc_alias = __trunckfhf2] + #[ppc_name = __trunckfhf2] #[cfg(all(f16_enabled, f128_enabled))] pub extern "C" fn __trunctfhf2(a: f128) -> f16 { trunc(a) } - #[aapcs_on_arm] - #[ppc_alias = __trunckfsf2] + #[ppc_name = __trunckfsf2] #[cfg(f128_enabled)] pub extern "C" fn __trunctfsf2(a: f128) -> f32 { trunc(a) } - #[aapcs_on_arm] - #[ppc_alias = __trunckfdf2] + #[ppc_name = __trunckfdf2] #[cfg(f128_enabled)] pub extern "C" fn __trunctfdf2(a: f128) -> f64 { trunc(a) diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index 0eb9a73b663f6..5dfc6733befec 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -6,6 +6,7 @@ #![feature(asm_experimental_arch)] #![feature(cfg_target_has_atomic)] #![feature(compiler_builtins)] +#![feature(complex_numbers)] #![feature(core_intrinsics)] #![feature(linkage)] #![feature(repr_simd)] diff --git a/library/compiler-builtins/compiler-builtins/src/macros.rs b/library/compiler-builtins/compiler-builtins/src/macros.rs index f6736b7bc7fda..42895773d3d92 100644 --- a/library/compiler-builtins/compiler-builtins/src/macros.rs +++ b/library/compiler-builtins/compiler-builtins/src/macros.rs @@ -38,13 +38,12 @@ /// /// A quick overview of attributes supported right now are: /// +// FIXME: Add missing attributes. /// * `maybe_use_optimized_c_shim` - indicates that the Rust implementation is /// ignored if an optimized C version was compiled. -/// * `aapcs_on_arm` - forces the ABI of the function to be `"aapcs"` on ARM and -/// the specified ABI everywhere else. /// * `arm_aeabi_alias` - handles the "aliasing" of various intrinsics on ARM /// their otherwise typical names to other prefixed ones. -/// * `ppc_alias` - changes the name of the symbol on PowerPC platforms without +/// * `ppc_name` - changes the name of the symbol on PowerPC platforms without /// changing any other behavior. This is mostly for `f128`, which is `tf` on /// most platforms but `kf` on PowerPC. macro_rules! intrinsics { @@ -168,38 +167,7 @@ macro_rules! intrinsics { intrinsics!($($rest)*); ); - // We recognize the `#[aapcs_on_arm]` attribute here and generate the - // same intrinsic but force it to have the `"aapcs"` calling convention on - // ARM and `"C"` elsewhere. - ( - #[aapcs_on_arm] - $(#[$($attr:tt)*])* - pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { - $($body:tt)* - } - - $($rest:tt)* - ) => ( - #[cfg(target_arch = "arm")] - intrinsics! { - $(#[$($attr)*])* - pub extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)? { - $($body)* - } - } - - #[cfg(not(target_arch = "arm"))] - intrinsics! { - $(#[$($attr)*])* - pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { - $($body)* - } - } - - intrinsics!($($rest)*); - ); - - // `arm_aeabi_alias` would conflict with `f16_apple_{arg,ret}_abi` not handled here. Avoid macro ambiguity by combining in a + // `arm_aeabi_alias` would conflict with `apple_f16_{arg,ret}_abi` not handled here. Avoid macro ambiguity by combining in a // single `#[]`. ( #[apple_f16_arg_abi] @@ -350,9 +318,9 @@ macro_rules! intrinsics { ); // PowerPC usually uses `kf` rather than `tf` for `f128`. This is just an easy - // way to add an alias on those targets. + // way to change the name on those targets. ( - #[ppc_alias = $alias:ident] + #[ppc_name = $ppc_name:ident] $(#[$($attr:tt)*])* pub extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* @@ -371,7 +339,7 @@ macro_rules! intrinsics { #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] intrinsics! { $(#[$($attr)*])* - pub extern $abi fn $alias( $($argname: $ty),* ) $(-> $ret)? { + pub extern $abi fn $ppc_name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index 50b42e0c07972..51a3417c8b151 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -72,7 +72,7 @@ cfg_select_nofmt! { pub mod generic; } _ => { - mod generic; + pub(crate) mod generic; } } diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index f802f4be6c2d7..1bded45ea930e 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -153,6 +153,12 @@ pub trait Float: /// Returns true if the value is +inf or -inf. fn is_infinite(self) -> bool; + /// Returns true if this number is neither infinite nor NaN. + #[allow(dead_code)] + fn is_finite(self) -> bool { + self.abs() < Self::INFINITY + } + /// Returns true if the sign is negative. Extracts the sign bit regardless of zero or NaN. fn is_sign_negative(self) -> bool; diff --git a/library/compiler-builtins/libm/src/math/support/hex_float.rs b/library/compiler-builtins/libm/src/math/support/hex_float.rs index 607ba7964023b..5040c3fae7933 100644 --- a/library/compiler-builtins/libm/src/math/support/hex_float.rs +++ b/library/compiler-builtins/libm/src/math/support/hex_float.rs @@ -698,62 +698,48 @@ mod parse_tests { } } } - // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to - // hide them from the AST. + #[test] #[cfg(f16_enabled)] - macro_rules! f16_tests { - () => { - #[test] - fn test_f16() { - let checks = [ - ("0x.1234p+16", (0x1234 as f16).to_bits()), - ("0x1.234p+12", (0x1234 as f16).to_bits()), - ("0x12.34p+8", (0x1234 as f16).to_bits()), - ("0x123.4p+4", (0x1234 as f16).to_bits()), - ("0x1234p+0", (0x1234 as f16).to_bits()), - ("0x1234.p+0", (0x1234 as f16).to_bits()), - ("0x1234.0p+0", (0x1234 as f16).to_bits()), - ("0x1.ffcp+15", f16::MAX.to_bits()), - ("0x1.0p+1", 2.0f16.to_bits()), - ("0x1.0p+0", 1.0f16.to_bits()), - ("0x1.ffp+8", 0x5ffc), - ("+0x1.ffp+8", 0x5ffc), - ("0x1p+0", 0x3c00), - ("0x1.998p-4", 0x2e66), - ("0x1.9p+6", 0x5640), - ("0x0.0p0", 0.0f16.to_bits()), - ("-0x0.0p0", (-0.0f16).to_bits()), - ("0x1.0p0", 1.0f16.to_bits()), - ("0x1.998p-4", (0.1f16).to_bits()), - ("-0x1.998p-4", (-0.1f16).to_bits()), - ("0x0.123p-12", 0x0123), - ("0x1p-24", 0x0001), - ("nan", f16::NAN.to_bits()), - ("-nan", (-f16::NAN).to_bits()), - ("inf", f16::INFINITY.to_bits()), - ("-inf", f16::NEG_INFINITY.to_bits()), - ]; - for (s, exp) in checks { - println!("parsing {s}"); - assert!(rounding_properties(s).is_ok()); - let act = hf16(s).to_bits(); - assert_eq!( - act, exp, - "parsing {s}: {act:#06x} != {exp:#06x}\nact: {act:#018b}\nexp: {exp:#018b}" - ); - } - } - - #[test] - fn test_macros_f16() { - assert_eq!(hf16!("0x1.ffp+8").to_bits(), 0x5ffc_u16); - } - }; + fn test_f16() { + let checks = [ + ("0x.1234p+16", (0x1234 as f16).to_bits()), + ("0x1.234p+12", (0x1234 as f16).to_bits()), + ("0x12.34p+8", (0x1234 as f16).to_bits()), + ("0x123.4p+4", (0x1234 as f16).to_bits()), + ("0x1234p+0", (0x1234 as f16).to_bits()), + ("0x1234.p+0", (0x1234 as f16).to_bits()), + ("0x1234.0p+0", (0x1234 as f16).to_bits()), + ("0x1.ffcp+15", f16::MAX.to_bits()), + ("0x1.0p+1", 2.0f16.to_bits()), + ("0x1.0p+0", 1.0f16.to_bits()), + ("0x1.ffp+8", 0x5ffc), + ("+0x1.ffp+8", 0x5ffc), + ("0x1p+0", 0x3c00), + ("0x1.998p-4", 0x2e66), + ("0x1.9p+6", 0x5640), + ("0x0.0p0", 0.0f16.to_bits()), + ("-0x0.0p0", (-0.0f16).to_bits()), + ("0x1.0p0", 1.0f16.to_bits()), + ("0x1.998p-4", (0.1f16).to_bits()), + ("-0x1.998p-4", (-0.1f16).to_bits()), + ("0x0.123p-12", 0x0123), + ("0x1p-24", 0x0001), + ("nan", f16::NAN.to_bits()), + ("-nan", (-f16::NAN).to_bits()), + ("inf", f16::INFINITY.to_bits()), + ("-inf", f16::NEG_INFINITY.to_bits()), + ]; + for (s, exp) in checks { + println!("parsing {s}"); + assert!(rounding_properties(s).is_ok()); + let act = hf16(s).to_bits(); + assert_eq!( + act, exp, + "parsing {s}: {act:#06x} != {exp:#06x}\nact: {act:#018b}\nexp: {exp:#018b}" + ); + } } - #[cfg(f16_enabled)] - f16_tests!(); - #[test] fn test_f32() { let checks = [ @@ -840,61 +826,56 @@ mod parse_tests { } } - // HACK(msrv): 1.63 rejects unknown width float literals at an AST level, so use a macro to - // hide them from the AST. + #[test] #[cfg(f128_enabled)] - macro_rules! f128_tests { - () => { - #[test] - fn test_f128() { - let checks = [ - ("0x.1234p+16", (0x1234 as f128).to_bits()), - ("0x1.234p+12", (0x1234 as f128).to_bits()), - ("0x12.34p+8", (0x1234 as f128).to_bits()), - ("0x123.4p+4", (0x1234 as f128).to_bits()), - ("0x1234p+0", (0x1234 as f128).to_bits()), - ("0x1234.p+0", (0x1234 as f128).to_bits()), - ("0x1234.0p+0", (0x1234 as f128).to_bits()), - ("0x1.ffffffffffffffffffffffffffffp+16383", f128::MAX.to_bits()), - ("0x1.0p+1", 2.0f128.to_bits()), - ("0x1.0p+0", 1.0f128.to_bits()), - ("0x1.ffep+8", 0x4007ffe0000000000000000000000000), - ("+0x1.ffep+8", 0x4007ffe0000000000000000000000000), - ("0x1p+0", 0x3fff0000000000000000000000000000), - ("0x1.999999999999999999999999999ap-4", 0x3ffb999999999999999999999999999a), - ("0x1.9p+6", 0x40059000000000000000000000000000), - ("0x0.0p0", 0.0f128.to_bits()), - ("-0x0.0p0", (-0.0f128).to_bits()), - ("0x1.0p0", 1.0f128.to_bits()), - ("0x1.999999999999999999999999999ap-4", (0.1f128).to_bits()), - ("-0x1.999999999999999999999999999ap-4", (-0.1f128).to_bits()), - ("0x0.abcdef0123456789abcdef012345p-16382", 0x0000abcdef0123456789abcdef012345), - ("0x1p-16494", 0x00000000000000000000000000000001), - ("nan", f128::NAN.to_bits()), - ("-nan", (-f128::NAN).to_bits()), - ("inf", f128::INFINITY.to_bits()), - ("-inf", f128::NEG_INFINITY.to_bits()), - ]; - for (s, exp) in checks { - println!("parsing {s}"); - let act = hf128(s).to_bits(); - assert_eq!( - act, exp, - "parsing {s}: {act:#034x} != {exp:#034x}\nact: {act:#0130b}\nexp: {exp:#0130b}" - ); - } - } - - #[test] - fn test_macros_f128() { - assert_eq!(hf128!("0x1.ffep+8").to_bits(), 0x4007ffe0000000000000000000000000_u128); - } + fn test_f128() { + let checks = [ + ("0x.1234p+16", (0x1234 as f128).to_bits()), + ("0x1.234p+12", (0x1234 as f128).to_bits()), + ("0x12.34p+8", (0x1234 as f128).to_bits()), + ("0x123.4p+4", (0x1234 as f128).to_bits()), + ("0x1234p+0", (0x1234 as f128).to_bits()), + ("0x1234.p+0", (0x1234 as f128).to_bits()), + ("0x1234.0p+0", (0x1234 as f128).to_bits()), + ( + "0x1.ffffffffffffffffffffffffffffp+16383", + f128::MAX.to_bits(), + ), + ("0x1.0p+1", 2.0f128.to_bits()), + ("0x1.0p+0", 1.0f128.to_bits()), + ("0x1.ffep+8", 0x4007ffe0000000000000000000000000), + ("+0x1.ffep+8", 0x4007ffe0000000000000000000000000), + ("0x1p+0", 0x3fff0000000000000000000000000000), + ( + "0x1.999999999999999999999999999ap-4", + 0x3ffb999999999999999999999999999a, + ), + ("0x1.9p+6", 0x40059000000000000000000000000000), + ("0x0.0p0", 0.0f128.to_bits()), + ("-0x0.0p0", (-0.0f128).to_bits()), + ("0x1.0p0", 1.0f128.to_bits()), + ("0x1.999999999999999999999999999ap-4", (0.1f128).to_bits()), + ("-0x1.999999999999999999999999999ap-4", (-0.1f128).to_bits()), + ( + "0x0.abcdef0123456789abcdef012345p-16382", + 0x0000abcdef0123456789abcdef012345, + ), + ("0x1p-16494", 0x00000000000000000000000000000001), + ("nan", f128::NAN.to_bits()), + ("-nan", (-f128::NAN).to_bits()), + ("inf", f128::INFINITY.to_bits()), + ("-inf", f128::NEG_INFINITY.to_bits()), + ]; + for (s, exp) in checks { + println!("parsing {s}"); + let act = hf128(s).to_bits(); + assert_eq!( + act, exp, + "parsing {s}: {act:#034x} != {exp:#034x}\nact: {act:#0130b}\nexp: {exp:#0130b}" + ); } } - #[cfg(f128_enabled)] - f128_tests!(); - #[test] fn test_macros() { #[cfg(f16_enabled)] diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index 2f175e966812d..6c07d50b9c4b3 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -2c39ff499469be916d4e45506d1afed69bbaddb7 +45f215f136e00d8a74c69afde2f71be3f16837cf