From 23567698971accae711fa3514f95c996ecba2abf Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 4 Jun 2025 20:56:35 +0000 Subject: [PATCH 1/7] Use the in-tree `compiler-builtins` Many of `std`'s dependency have a dependency on the crates.io `compiler-builtins` when used with the feature `rustc-std-workspace-core`. Use a Cargo patch to select the in-tree version instead. `compiler-builtins` is also added as a dependency of `rustc-std-workspace-core` so these crates can remove their crates.io dependency in the future. --- compiler-builtins/Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler-builtins/Cargo.toml b/compiler-builtins/Cargo.toml index 11ee9195..df8e9648 100644 --- a/compiler-builtins/Cargo.toml +++ b/compiler-builtins/Cargo.toml @@ -17,9 +17,7 @@ doctest = false test = false [dependencies] -# For more information on this dependency see -# https://github.com/rust-lang/rust/tree/master/library/rustc-std-workspace-core -core = { version = "1.0.1", optional = true, package = "rustc-std-workspace-core" } +core = { path = "../../core", optional = true } [build-dependencies] cc = { optional = true, version = "1.2" } From 8f802ae454432a8cd30df5d376dbd29694e6bb71 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 5 Jun 2025 06:00:54 +0000 Subject: [PATCH 2/7] compiler-builtins: Fix a `rustdoc::bare-urls` error --- compiler-builtins/src/aarch64_linux.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-builtins/src/aarch64_linux.rs b/compiler-builtins/src/aarch64_linux.rs index e238d023..22612123 100644 --- a/compiler-builtins/src/aarch64_linux.rs +++ b/compiler-builtins/src/aarch64_linux.rs @@ -4,7 +4,7 @@ //! To avoid breaking backwards compat, C toolchains introduced a concept of "outlined atomics", //! where atomic operations call into the compiler runtime to dispatch between two depending on //! which is supported on the current CPU. -//! See https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/making-the-most-of-the-arm-architecture-in-gcc-10#:~:text=out%20of%20line%20atomics for more discussion. +//! See for more discussion. //! //! Currently we only support LL/SC, because LSE requires `getauxval` from libc in order to do runtime detection. //! Use the `compiler-rt` intrinsics if you want LSE support. From 714314f48b9c0b23c083b0840930f6b000b9cc2a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 8 Jun 2025 10:21:57 +0000 Subject: [PATCH 3/7] compiler-builtins: Resolve `unsafe_op_in_unsafe_fn` on Arm32 Android There are a few places that violate this lint, which showed up in rust-lang/rust CI (the relevent module is gated behind `kernel_user_helpers` which is only set for `armv4t`, `armv5te`, and `arm-linux-androideabi`; none of these are tested in compiler-builtins CI). Add new `unsafe { /* ... */ }` blocks where needed to address this. Some blocks should get a more thorough review of their preconditions, so their safety comments are left as `FIXME`s. --- compiler-builtins/src/arm_linux.rs | 40 ++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/compiler-builtins/src/arm_linux.rs b/compiler-builtins/src/arm_linux.rs index 6ce67ba7..ab9f8680 100644 --- a/compiler-builtins/src/arm_linux.rs +++ b/compiler-builtins/src/arm_linux.rs @@ -4,12 +4,17 @@ use core::{arch, mem}; // Kernel-provided user-mode helper functions: // https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt unsafe fn __kuser_cmpxchg(oldval: u32, newval: u32, ptr: *mut u32) -> bool { - let f: extern "C" fn(u32, u32, *mut u32) -> u32 = mem::transmute(0xffff0fc0usize as *const ()); + // FIXME(volatile): the third parameter is a volatile pointer + // SAFETY: kernel docs specify a known address with the given signature + let f = unsafe { + mem::transmute::<_, extern "C" fn(u32, u32, *mut u32) -> u32>(0xffff0fc0usize as *const ()) + }; f(oldval, newval, ptr) == 0 } unsafe fn __kuser_memory_barrier() { - let f: extern "C" fn() = mem::transmute(0xffff0fa0usize as *const ()); + // SAFETY: kernel docs specify a known address with the given signature + let f = unsafe { mem::transmute::<_, extern "C" fn()>(0xffff0fa0usize as *const ()) }; f(); } @@ -67,8 +72,10 @@ fn insert_aligned(aligned: u32, val: u32, shift: u32, mask: u32) -> u32 { /// - if `size_of::() == 2`, `ptr` or `ptr` offset by 2 bytes must be valid for a relaxed atomic /// read of 2 bytes. /// - if `size_of::() == 4`, `ptr` must be valid for a relaxed atomic read of 4 bytes. +// FIXME: assert some of the preconditions in debug mode unsafe fn atomic_load_aligned(ptr: *mut u32) -> u32 { - if mem::size_of::() == 4 { + const { assert!(size_of::() <= 4) }; + if size_of::() == 4 { // SAFETY: As `T` has a size of 4, the caller garantees this is sound. unsafe { AtomicU32::from_ptr(ptr).load(Ordering::Relaxed) } } else { @@ -100,11 +107,13 @@ unsafe fn atomic_rmw u32, G: Fn(u32, u32) -> u32>(ptr: *mut T, let (shift, mask) = get_shift_mask(ptr); loop { - let curval_aligned = atomic_load_aligned::(aligned_ptr); + // FIXME(safety): preconditions review needed + let curval_aligned = unsafe { atomic_load_aligned::(aligned_ptr) }; let curval = extract_aligned(curval_aligned, shift, mask); let newval = f(curval); let newval_aligned = insert_aligned(curval_aligned, newval, shift, mask); - if __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) { + // FIXME(safety): preconditions review needed + if unsafe { __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) } { return g(curval, newval); } } @@ -116,13 +125,15 @@ unsafe fn atomic_cmpxchg(ptr: *mut T, oldval: u32, newval: u32) -> u32 { let (shift, mask) = get_shift_mask(ptr); loop { - let curval_aligned = atomic_load_aligned::(aligned_ptr); + // FIXME(safety): preconditions review needed + let curval_aligned = unsafe { atomic_load_aligned::(aligned_ptr) }; let curval = extract_aligned(curval_aligned, shift, mask); if curval != oldval { return curval; } let newval_aligned = insert_aligned(curval_aligned, newval, shift, mask); - if __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) { + // FIXME(safety): preconditions review needed + if unsafe { __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) } { return oldval; } } @@ -132,7 +143,14 @@ macro_rules! atomic_rmw { ($name:ident, $ty:ty, $op:expr, $fetch:expr) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { - atomic_rmw(ptr, |x| $op(x as $ty, val) as u32, |old, new| $fetch(old, new)) as $ty + // FIXME(safety): preconditions review needed + unsafe { + atomic_rmw( + ptr, + |x| $op(x as $ty, val) as u32, + |old, new| $fetch(old, new) + ) as $ty + } } } }; @@ -149,7 +167,8 @@ macro_rules! atomic_cmpxchg { ($name:ident, $ty:ty) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { - atomic_cmpxchg(ptr, oldval as u32, newval as u32) as $ty + // FIXME(safety): preconditions review needed + unsafe { atomic_cmpxchg(ptr, oldval as u32, newval as u32) as $ty } } } }; @@ -285,6 +304,7 @@ atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32); intrinsics! { pub unsafe extern "C" fn __sync_synchronize() { - __kuser_memory_barrier(); + // SAFETY: preconditions are the same as the calling function. + unsafe { __kuser_memory_barrier() }; } } From d17f101f0d5eba57120ad60358c478442c284303 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 8 Jun 2025 17:13:18 +0000 Subject: [PATCH 4/7] compiler-builtins: Specify `:r` registers for `usize` On the ILP32 `x86_64-unknown-linux-gnux32` target, `usize` is 32 bits so there is a sub-register alignment warning. Specify the 64-bit `r` registers, which matches the current default as well as the size of the other operands in the routines. --- compiler-builtins/src/mem/x86_64.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler-builtins/src/mem/x86_64.rs b/compiler-builtins/src/mem/x86_64.rs index 5cbe83ab..fb29eb11 100644 --- a/compiler-builtins/src/mem/x86_64.rs +++ b/compiler-builtins/src/mem/x86_64.rs @@ -69,7 +69,7 @@ pub unsafe fn copy_backward(dest: *mut u8, src: *const u8, count: usize) { "rep movsb", "sub $7, %rsi", "sub $7, %rdi", - "mov {qword_count}, %rcx", + "mov {qword_count:r}, %rcx", "rep movsq", "test {pre_byte_count:e}, {pre_byte_count:e}", "add $7, %rsi", @@ -212,7 +212,7 @@ pub unsafe fn c_string_length(mut s: *const core::ffi::c_char) -> usize { let x = { let r; asm!( - "movdqa ({addr}), {dest}", + "movdqa ({addr:r}), {dest}", addr = in(reg) s, dest = out(xmm_reg) r, options(att_syntax, nostack), @@ -232,7 +232,7 @@ pub unsafe fn c_string_length(mut s: *const core::ffi::c_char) -> usize { let x = { let r; asm!( - "movdqa ({addr}), {dest}", + "movdqa ({addr:r}), {dest}", addr = in(reg) s, dest = out(xmm_reg) r, options(att_syntax, nostack), From d1d8fb29fe06adb56176d45c2dd810153a5ce006 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 9 Jun 2025 04:10:24 +0000 Subject: [PATCH 5/7] compiler-builtins: Emit `rustc-check-cfg` earlier The `build.rs` entrypoint returns early for some targets, so emscripten and OpenBSD were not getting check-cfg set. Emit these earlier to avoid the `unexpected_cfgs` lint. --- compiler-builtins/build.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler-builtins/build.rs b/compiler-builtins/build.rs index d37fdc5d..7c8da02f 100644 --- a/compiler-builtins/build.rs +++ b/compiler-builtins/build.rs @@ -22,6 +22,9 @@ fn main() { println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display()); + println!("cargo::rustc-check-cfg=cfg(kernel_user_helpers)"); + println!("cargo::rustc-check-cfg=cfg(feature, values(\"mem-unaligned\"))"); + // Emscripten's runtime includes all the builtins if target.os == "emscripten" { return; @@ -47,7 +50,6 @@ fn main() { } // These targets have hardware unaligned access support. - println!("cargo::rustc-check-cfg=cfg(feature, values(\"mem-unaligned\"))"); if target.arch.contains("x86_64") || target.arch.contains("x86") || target.arch.contains("aarch64") @@ -78,7 +80,6 @@ fn main() { // Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This // includes the old androideabi. It is deprecated but it is available as a // rustc target (arm-linux-androideabi). - println!("cargo::rustc-check-cfg=cfg(kernel_user_helpers)"); if llvm_target[0] == "armv4t" || llvm_target[0] == "armv5te" || target.triple == "arm-linux-androideabi" From d4c404dc82abbe74f7da491ad02e2a7d8fc9ad0e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 9 Jun 2025 21:50:42 +0000 Subject: [PATCH 6/7] Update the upstream Rust version To prepare for merging from rust-lang/rust, set the version file to: d13a431a6c Auto merge of #142253 - tgross35:rollup-img49op, r=tgross35 --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index e05aaa05..ffedaae0 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -df8102fe5f24f28a918660b0cd918d7331c3896e +d13a431a6cc69cd65efe7c3eb7808251d6fd7a46 From a320965a7537d3ca1b4ad6e253aeca9de2378674 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 10 Jun 2025 06:45:31 +0000 Subject: [PATCH 7/7] Move the builtins for in-tree use to a separate crate --- Cargo.toml | 3 +- compiler-builtins/Cargo.toml | 5 +- .../Cargo.toml | 56 +++++++++++++++++++ .../src/lib.rs | 14 +++++ 4 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 rustc-std-workspace-compiler-builtins/Cargo.toml create mode 100644 rustc-std-workspace-compiler-builtins/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index fb638f2f..ac289eb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ "crates/symbol-check", "crates/util", "libm", - "libm-test", + "libm-test" ] default-members = [ @@ -26,6 +26,7 @@ exclude = [ # and `mangled-names` disabled, which is the opposite of what is needed for # other tests, so it makes sense to keep it out of the workspace. "builtins-test-intrinsics", + "rustc-std-workspace-compiler-builtins", ] [profile.release] diff --git a/compiler-builtins/Cargo.toml b/compiler-builtins/Cargo.toml index df8e9648..5205fbd3 100644 --- a/compiler-builtins/Cargo.toml +++ b/compiler-builtins/Cargo.toml @@ -16,9 +16,6 @@ bench = false doctest = false test = false -[dependencies] -core = { path = "../../core", optional = true } - [build-dependencies] cc = { optional = true, version = "1.2" } @@ -48,7 +45,7 @@ mem = [] mangled-names = [] # Only used in the compiler's build system -rustc-dep-of-std = ["compiler-builtins", "dep:core"] +rustc-dep-of-std = ["compiler-builtins"] # This makes certain traits and function specializations public that # are not normally public but are required by the `builtins-test` diff --git a/rustc-std-workspace-compiler-builtins/Cargo.toml b/rustc-std-workspace-compiler-builtins/Cargo.toml new file mode 100644 index 00000000..b7e86cb7 --- /dev/null +++ b/rustc-std-workspace-compiler-builtins/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "compiler_builtins" +version = "0.1.160" +license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" +edition = "2024" +publish = false +links = "compiler-rt" +include = ["../compiler-builtins/src"] +build = "../compiler-builtins/build.rs" + +[lib] +bench = false +doctest = false +test = false + +[dependencies] +core = { path = "../../core", optional = true } + +[build-dependencies] +cc = { optional = true, version = "1.2" } + +[features] +default = ["compiler-builtins"] + +# Enable compilation of C code in compiler-rt, filling in some more optimized +# implementations and also filling in unimplemented intrinsics +c = ["dep:cc"] + +# Workaround for the Cranelift codegen backend. Disables any implementations +# which use inline assembly and fall back to pure Rust versions (if available). +no-asm = [] + +# Workaround for codegen backends which haven't yet implemented `f16` and +# `f128` support. Disabled any intrinsics which use those types. +no-f16-f128 = [] + +# Flag this library as the unstable compiler-builtins lib +compiler-builtins = [] + +# Generate memory-related intrinsics like memcpy +mem = [] + +# Mangle all names so this can be linked in with other versions or other +# compiler-rt implementations. Also used for testing +mangled-names = [] + +# Only used in the compiler's build system +rustc-dep-of-std = ["compiler-builtins"] + +# This makes certain traits and function specializations public that +# are not normally public but are required by the `builtins-test` +unstable-public-internals = [] + +[lints.rust] +# The cygwin config can be dropped after our benchmark toolchain is bumped +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)', 'cfg(target_os, values("cygwin"))'] } diff --git a/rustc-std-workspace-compiler-builtins/src/lib.rs b/rustc-std-workspace-compiler-builtins/src/lib.rs new file mode 100644 index 00000000..b93cf3ff --- /dev/null +++ b/rustc-std-workspace-compiler-builtins/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +}