Move examples/intrinsics.rs to its own crate

Currently there is an interesting situation with the way features get
enabled; `testcrate` enables `mangled-names`, but the `intrinsics.rs`
example requires this feature be disabled (otherwise the test fails with
missing symbols, as expected). This is also the reason that `testcrate`
is not a default workspace member, meaning `cargo test` doesn't actually
run `testcrate`'s tests; making it a default member would mean that
`compiler-builtins/mangled-names` gets enabled when
`examples/intrinsics.rs` gets built, due to the way features get
unified.

Simplify the situation by making moving the example to its own crate as
`builtins-test-intrinsics`. This also means `testcrate` can become a
default member so it is included in `cargo check` or `cargo test` when
run at the workspace root.

`testcrate` and `builtins-test-intrinsics` still can't be built at the
same time since there isn't a straightforward way to have Cargo build
`compiler-builtins` twice with different features. This is a side effect
of us using non-additive features, but there isn't really a better
option since enabling both mangled and unmangled names would render
`builtins-test-intrinsics` useless.
This commit is contained in:
Trevor Gross 2025-03-18 10:13:47 +00:00 committed by Trevor Gross
parent 590a56483c
commit a179959e0b
9 changed files with 69 additions and 32 deletions

View file

@ -71,13 +71,20 @@ rustc-dep-of-std = ['compiler-builtins', 'core']
# are not normally public but are required by the `testcrate`
public-test-deps = []
[[example]]
name = "intrinsics"
required-features = ["compiler-builtins"]
[workspace]
resolver = "2"
members = ["testcrate"]
members = [
# Note that builtins-test-intrinsics cannot be a default member because it
# needs the `mangled-names` feature disabled, while `testcrate` needs it
# enabled.
"builtins-test-intrinsics",
"testcrate",
]
default-members = [
".",
"testcrate",
]
[profile.release]
panic = 'abort'

View file

@ -16,8 +16,8 @@ It is distributed as part of Rust's sysroot.
[C implementation][2] to Rust.
4. Add a test to compare the behavior of the ported intrinsic(s) with their
implementation on the testing host.
5. Add the intrinsic to `examples/intrinsics.rs` to verify it can be linked on
all targets.
5. Add the intrinsic to `builtins-test-intrinsics/src/main.rs` to verify it
can be linked on all targets.
6. Send a Pull Request (PR).
7. Once the PR passes our extensive testing infrastructure, we'll merge it!
8. Celebrate :tada:

View file

@ -2,7 +2,7 @@ use std::{collections::BTreeMap, env, path::PathBuf, sync::atomic::Ordering};
mod configure;
use configure::{configure_f16_f128, Target};
use configure::{configure_aliases, configure_f16_f128, Target};
fn main() {
println!("cargo::rerun-if-changed=build.rs");
@ -13,6 +13,7 @@ fn main() {
configure_check_cfg();
configure_f16_f128(&target);
configure_aliases(&target);
configure_libm(&target);
@ -71,20 +72,6 @@ fn main() {
}
}
// To compile intrinsics.rs for thumb targets, where there is no libc
println!("cargo::rustc-check-cfg=cfg(thumb)");
if llvm_target[0].starts_with("thumb") {
println!("cargo:rustc-cfg=thumb")
}
// compiler-rt `cfg`s away some intrinsics for thumbv6m and thumbv8m.base because
// these targets do not have full Thumb-2 support but only original Thumb-1.
// We have to cfg our code accordingly.
println!("cargo::rustc-check-cfg=cfg(thumb_1)");
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" {
println!("cargo:rustc-cfg=thumb_1")
}
// 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).

View file

@ -0,0 +1,11 @@
[package]
name = "builtins-test-intrinsics"
version = "0.1.0"
edition = "2021"
[dependencies]
compiler_builtins = { path = "../", features = ["compiler-builtins"]}
panic-handler = { path = '../crates/panic-handler' }
[features]
c = ["compiler_builtins/c"]

View file

@ -0,0 +1,11 @@
mod builtins_configure {
include!("../configure.rs");
}
fn main() {
println!("cargo::rerun-if-changed=../configure.rs");
let target = builtins_configure::Target::from_env();
builtins_configure::configure_f16_f128(&target);
builtins_configure::configure_aliases(&target);
}

View file

@ -120,22 +120,22 @@ done
rm -f "${rlib_paths[@]}"
build_intrinsics() {
cargo build --target "$target" -v --example intrinsics "$@"
build_intrinsics_test() {
cargo build --target "$target" -v --package builtins-test-intrinsics "$@"
}
# Verify that we haven't drop any intrinsic/symbol
build_intrinsics
build_intrinsics --release
build_intrinsics --features c
build_intrinsics --features c --release
# Verify that we haven't dropped any intrinsics/symbols
build_intrinsics_test
build_intrinsics_test --release
build_intrinsics_test --features c
build_intrinsics_test --features c --release
# Verify that there are no undefined symbols to `panic` within our
# implementations
CARGO_PROFILE_DEV_LTO=true \
cargo build --target "$target" --example intrinsics
cargo build --target "$target" --package builtins-test-intrinsics
CARGO_PROFILE_RELEASE_LTO=true \
cargo build --target "$target" --example intrinsics --release
cargo build --target "$target" --package builtins-test-intrinsics --release
# Ensure no references to any symbols from core
update_rlib_paths

View file

@ -6,6 +6,7 @@ use std::env;
#[allow(dead_code)]
pub struct Target {
pub triple: String,
pub triple_split: Vec<String>,
pub opt_level: String,
pub cargo_features: Vec<String>,
pub os: String,
@ -19,6 +20,8 @@ pub struct Target {
impl Target {
pub fn from_env() -> Self {
let triple = env::var("TARGET").unwrap();
let triple_split = triple.split('-').map(ToOwned::to_owned).collect();
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
@ -30,7 +33,8 @@ impl Target {
.collect();
Self {
triple: env::var("TARGET").unwrap(),
triple,
triple_split,
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
opt_level: env::var("OPT_LEVEL").unwrap(),
cargo_features,
@ -56,6 +60,22 @@ impl Target {
}
}
pub fn configure_aliases(target: &Target) {
// To compile builtins-test-intrinsics for thumb targets, where there is no libc
println!("cargo::rustc-check-cfg=cfg(thumb)");
if target.triple_split[0].starts_with("thumb") {
println!("cargo:rustc-cfg=thumb")
}
// compiler-rt `cfg`s away some intrinsics for thumbv6m and thumbv8m.base because
// these targets do not have full Thumb-2 support but only original Thumb-1.
// We have to cfg our code accordingly.
println!("cargo::rustc-check-cfg=cfg(thumb_1)");
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
println!("cargo:rustc-cfg=thumb_1")
}
}
/// Configure whether or not `f16` and `f128` support should be enabled.
pub fn configure_f16_f128(target: &Target) {
// Set whether or not `f16` and `f128` are supported at a basic level by LLVM. This only means

View file

@ -115,5 +115,6 @@ fn main() {
println!("cargo:rustc-cfg=feature=\"{name}\"");
}
builtins_configure::configure_aliases(&target);
builtins_configure::configure_f16_f128(&target);
}