Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 5dfa781

Browse files
committed
WIP
wip Fixup features Fix things that should be cfg disabled
1 parent ce482e5 commit 5dfa781

File tree

18 files changed

+280
-58
lines changed

18 files changed

+280
-58
lines changed

Cargo.toml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,6 @@ unstable-float = []
4040
# hard float operations.
4141
force-soft-floats = []
4242

43-
# Workaround for codegen backends which haven't yet implemented `f16` and
44-
# `f128` support. Disables any functions which use those types.
45-
#
46-
# HACK: like the above, this is a negative feature that we would rather not
47-
# have, but we need to be consistent with compiler-builtins.
48-
no-f16-f128 = []
49-
5043
[workspace]
5144
resolver = "2"
5245
members = [

ci/run.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export RUST_BACKTRACE="${RUST_BACKTRACE:-full}"
66
# Needed for no-panic to correct detect a lack of panics
77
export RUSTFLAGS="${RUSTFLAGS:-} -Ccodegen-units=1"
88

9+
# MPFR tests consume a lot of stack and often overflow. Default to 20 MiB (10x
10+
# the default)
11+
export RUST_MIN_STACK="${RUST_MIN_STACK:-20971520}"
12+
913
target="${1:-}"
1014

1115
if [ -z "$target" ]; then
@@ -57,7 +61,7 @@ case "$target" in
5761
*windows-gnu) extra_flags="$extra_flags --exclude libm-macros" ;;
5862
esac
5963

60-
# Make sure we can build with overriding features. We test the indibidual
64+
# Make sure we can build with overriding features. We test the individual
6165
# features it controls separately.
6266
cargo check --no-default-features
6367
cargo check --features "force-soft-floats"
@@ -69,6 +73,10 @@ if [ "${BUILD_ONLY:-}" = "1" ]; then
6973

7074
echo "can't run tests on $target; skipping"
7175
else
76+
# Check `force-soft-floats` again, this time including test crates.
77+
cargo check --all --target "$target" $extra_flags \
78+
--features "force-soft-floats" --all-targets
79+
7280
cmd="cargo test --all --target $target $extra_flags"
7381

7482
# stable by default

configure.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ impl Config {
4343
pub fn emit_libm_config(cfg: &Config) {
4444
emit_intrinsics_cfg();
4545
emit_arch_cfg();
46-
emit_optimization_cfg(&cfg);
47-
emit_cfg_shorthands(&cfg);
48-
emit_f16_f128_cfg(&cfg);
46+
emit_optimization_cfg(cfg);
47+
emit_cfg_shorthands(cfg);
48+
emit_f16_f128_cfg(cfg);
4949
}
5050

5151
/// Tests don't need most feature-related config.
5252
#[allow(dead_code)]
5353
pub fn emit_test_config(cfg: &Config) {
54-
emit_optimization_cfg(&cfg);
55-
emit_cfg_shorthands(&cfg);
56-
emit_f16_f128_cfg(&cfg);
54+
emit_optimization_cfg(cfg);
55+
emit_cfg_shorthands(cfg);
56+
emit_f16_f128_cfg(cfg);
5757
}
5858

5959
/// Simplify the feature logic for enabling intrinsics so code only needs to use
@@ -102,11 +102,8 @@ fn emit_f16_f128_cfg(cfg: &Config) {
102102
println!("cargo:rustc-check-cfg=cfg(f16_enabled)");
103103
println!("cargo:rustc-check-cfg=cfg(f128_enabled)");
104104

105-
// `unstable-float` enables these features. Either `no-f16-f128` or `force-soft-floats`
106-
// will disable them.
107-
if !cfg!(feature = "unstable-float")
108-
&& (cfg!(feature = "no-f16-f128") || cfg!(feature = "force-soft-floats"))
109-
{
105+
// `unstable-float` enables these features.
106+
if !cfg!(feature = "unstable-float") {
110107
return;
111108
}
112109

crates/libm-macros/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@ heck = "0.5.0"
1212
proc-macro2 = "1.0.88"
1313
quote = "1.0.37"
1414
syn = { version = "2.0.79", features = ["full", "extra-traits", "visit-mut"] }
15+
16+
[lints.rust]
17+
# Values used during testing
18+
unexpected_cfgs = { level = "warn", check-cfg = [
19+
'cfg(f16_enabled)',
20+
'cfg(f128_enabled)',
21+
] }

crates/libm-macros/src/lib.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ const KNOWN_TYPES: &[&str] = &["FTy", "CFn", "CArgs", "CRet", "RustFn", "RustArg
218218

219219
/// A type used in a function signature.
220220
#[allow(dead_code)]
221-
#[derive(Debug, Clone, Copy)]
221+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
222222
enum Ty {
223223
F16,
224224
F32,
@@ -359,7 +359,7 @@ pub fn base_name_enum(attributes: pm::TokenStream, tokens: pm::TokenStream) -> p
359359
/// // The Rust version's return type (e.g. `(f32, f32)`)
360360
/// RustRet: $RustRet:ty,
361361
/// // Attributes for the current function, if any
362-
/// attrs: [$($meta:meta)*]
362+
/// attrs: [$($meta:meta),*],
363363
/// // Extra tokens passed directly (if any)
364364
/// extra: [$extra:ident],
365365
/// // Extra function-tokens passed directly (if any)
@@ -377,6 +377,8 @@ pub fn base_name_enum(attributes: pm::TokenStream, tokens: pm::TokenStream) -> p
377377
/// skip: [sin, cos],
378378
/// // Attributes passed as `attrs` for specific functions. For example, here the invocation
379379
/// // with `sinf` and that with `cosf` will both get `meta1` and `meta2`, but no others will.
380+
/// // Note that `f16_enabled` and `f128_enabled` will always get emitted regardless of whether
381+
/// // or not this is specified.
380382
/// attributes: [
381383
/// #[meta1]
382384
/// #[meta2]
@@ -535,16 +537,28 @@ fn expand(input: StructuredInput, fn_list: &[&FunctionInfo]) -> syn::Result<pm2:
535537
let fn_name = Ident::new(func.name, Span::call_site());
536538

537539
// Prepare attributes in an `attrs: ...` field
538-
let meta_field = match &input.attributes {
539-
Some(attrs) => {
540-
let meta = attrs
541-
.iter()
542-
.filter(|map| map.names.contains(&fn_name))
543-
.flat_map(|map| &map.meta);
544-
quote! { attrs: [ #( #meta )* ] }
545-
}
546-
None => pm2::TokenStream::new(),
547-
};
540+
let mut meta_fields = Vec::new();
541+
if let Some(attrs) = &input.attributes {
542+
let meta_iter = attrs
543+
.iter()
544+
.filter(|map| map.names.contains(&fn_name))
545+
.flat_map(|map| &map.meta)
546+
.map(|v| v.into_token_stream());
547+
548+
meta_fields.extend(meta_iter);
549+
}
550+
551+
// Always emit f16 and f128 meta so this doesn't need to be repeated everywhere
552+
if func.rust_sig.args.contains(&Ty::F16) || func.rust_sig.returns.contains(&Ty::F16) {
553+
let ts = quote! { cfg(f16_enabled) };
554+
meta_fields.push(ts);
555+
}
556+
if func.rust_sig.args.contains(&Ty::F128) || func.rust_sig.returns.contains(&Ty::F128) {
557+
let ts = quote! { cfg(f128_enabled) };
558+
meta_fields.push(ts);
559+
}
560+
561+
let meta_field = quote! { attrs: [ #( #meta_fields ),* ], };
548562

549563
// Prepare extra in an `extra: ...` field, running the replacer
550564
let extra_field = match input.extra.clone() {

crates/libm-macros/tests/basic.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// `STATUS_DLL_NOT_FOUND` on i686 MinGW, not worth looking into.
2+
#![feature(f16)]
3+
#![feature(f128)]
24
#![cfg(not(all(target_arch = "x86", target_os = "windows", target_env = "gnu")))]
35

46
macro_rules! basic {
@@ -11,7 +13,7 @@ macro_rules! basic {
1113
RustFn: $RustFn:ty,
1214
RustArgs: $RustArgs:ty,
1315
RustRet: $RustRet:ty,
14-
attrs: [$($meta:meta)*]
16+
attrs: [$($meta:meta),*],
1517
extra: [$($extra_tt:tt)*],
1618
fn_extra: $fn_extra:expr,
1719
) => {
@@ -60,6 +62,7 @@ mod test_basic {
6062
macro_rules! basic_no_extra {
6163
(
6264
fn_name: $fn_name:ident,
65+
attrs: [$($meta:meta),*],
6366
) => {
6467
mod $fn_name {}
6568
};
@@ -85,6 +88,7 @@ macro_rules! specified_types {
8588
fn_name: $fn_name:ident,
8689
RustFn: $RustFn:ty,
8790
RustArgs: $RustArgs:ty,
91+
attrs: [$($meta:meta),*],
8892
) => {
8993
mod $fn_name {
9094
#[allow(unused)]

crates/libm-test/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish = false
88
default = ["unstable-float"]
99

1010
# Propagated from libm because this affects which functions we test.
11-
unstable-float = ["libm/unstable-float"]
11+
unstable-float = ["libm/unstable-float", "rug?/nightly-float"]
1212

1313
# Generate tests which are random inputs and the outputs are calculated with
1414
# musl libc.
@@ -51,5 +51,5 @@ harness = false
5151
[lints.rust]
5252
# Values from the chared config.rs used by `libm` but not the test crate
5353
unexpected_cfgs = { level = "warn", check-cfg = [
54-
'cfg(feature, values("arch", "force-soft-floats", "no-f16-f128", "unstable-intrinsics"))',
54+
'cfg(feature, values("arch", "force-soft-floats", "unstable-intrinsics"))',
5555
] }

crates/libm-test/benches/random.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ struct MuslExtra<F> {
1818
macro_rules! musl_rand_benches {
1919
(
2020
fn_name: $fn_name:ident,
21-
fn_extra: $skip_on_i586:expr,
21+
attrs: [$($meta:meta)*],
22+
fn_extra: ($skip_on_i586:expr, $musl_fn:expr),
2223
) => {
2324
paste::paste! {
2425
fn [< musl_bench_ $fn_name >](c: &mut Criterion) {
2526
type Op = libm_test::op::$fn_name::Routine;
2627

2728
#[cfg(feature = "build-musl")]
2829
let musl_extra = MuslExtra {
29-
musl_fn: Some(musl_math_sys::$fn_name as libm_test::OpCFn<Op>),
30+
musl_fn: $musl_fn,
3031
skip_on_i586: $skip_on_i586
3132
};
3233

@@ -64,7 +65,10 @@ where
6465
break;
6566
}
6667

67-
let musl_res = input.call(musl_extra.musl_fn.unwrap());
68+
let Some(musl_fn) = musl_extra.musl_fn else {
69+
continue;
70+
};
71+
let musl_res = input.call(musl_fn);
6872
let crate_res = input.call(Op::ROUTINE);
6973

7074
crate_res.validate(musl_res, input, &ctx).context(name).unwrap();
@@ -88,31 +92,39 @@ where
8892
// Don't test against musl if it is not available
8993
#[cfg(feature = "build-musl")]
9094
{
91-
let musl_fn = musl_extra.musl_fn.unwrap();
92-
group.bench_function("musl", |b| {
93-
b.iter(|| {
94-
let f = black_box(musl_fn);
95-
for input in benchvec.iter().copied() {
96-
input.call(f);
97-
}
98-
})
99-
});
95+
if let Some(musl_fn) = musl_extra.musl_fn {
96+
group.bench_function("musl", |b| {
97+
b.iter(|| {
98+
let f = black_box(musl_fn);
99+
for input in benchvec.iter().copied() {
100+
input.call(f);
101+
}
102+
})
103+
});
104+
}
100105
}
101106
}
102107

103108
libm_macros::for_each_function! {
104109
callback: musl_rand_benches,
105110
skip: [],
106111
fn_extra: match MACRO_FN_NAME {
107-
// FIXME(correctness): wrong result on i586
108-
exp10 | exp10f | exp2 | exp2f => true,
109-
_ => false
112+
// We pass a tuple of `(skip_on_i586, musl_fn)`. By default we never skip (false) and
113+
// we do pass a function, but there are a couple exceptions.
114+
// FIXME(correctness): exp functions have the wrong result on i586
115+
exp10 | exp10f | exp2 | exp2f => (
116+
true, Some(musl_math_sys::MACRO_FN_NAME as <Op as MathOp>::CFn)
117+
),
118+
// Musl does not provide `f16` and `f128` functions
119+
copysignf16 | copysignf128 | fabsf16 | fabsf128 => (false, None),
120+
_ => (false, Some(musl_math_sys::MACRO_FN_NAME as <Op as MathOp>::CFn))
110121
}
111122
}
112123

113124
macro_rules! run_callback {
114125
(
115126
fn_name: $fn_name:ident,
127+
attrs: [$($meta:meta)*],
116128
extra: [$criterion:ident],
117129
) => {
118130
paste::paste! {

crates/libm-test/src/gen.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,29 @@ pub mod random;
66
/// Helper type to turn any reusable input into a generator.
77
#[derive(Clone, Debug, Default)]
88
pub struct CachedInput {
9+
#[cfg(f16_enabled)]
10+
pub inputs_f16: Vec<(f16, f16, f16)>,
911
pub inputs_f32: Vec<(f32, f32, f32)>,
1012
pub inputs_f64: Vec<(f64, f64, f64)>,
13+
#[cfg(f128_enabled)]
14+
pub inputs_f128: Vec<(f128, f128, f128)>,
1115
pub inputs_i32: Vec<(i32, i32, i32)>,
1216
}
1317

18+
#[cfg(f16_enabled)]
19+
impl GenerateInput<(f16,)> for CachedInput {
20+
fn get_cases(&self) -> impl Iterator<Item = (f16,)> {
21+
self.inputs_f16.iter().map(|f| (f.0,))
22+
}
23+
}
24+
25+
#[cfg(f16_enabled)]
26+
impl GenerateInput<(f16, f16)> for CachedInput {
27+
fn get_cases(&self) -> impl Iterator<Item = (f16, f16)> {
28+
self.inputs_f16.iter().map(|f| (f.0, f.1))
29+
}
30+
}
31+
1432
impl GenerateInput<(f32,)> for CachedInput {
1533
fn get_cases(&self) -> impl Iterator<Item = (f32,)> {
1634
self.inputs_f32.iter().map(|f| (f.0,))
@@ -70,3 +88,17 @@ impl GenerateInput<(f64, f64, f64)> for CachedInput {
7088
self.inputs_f64.iter().copied()
7189
}
7290
}
91+
92+
#[cfg(f128_enabled)]
93+
impl GenerateInput<(f128,)> for CachedInput {
94+
fn get_cases(&self) -> impl Iterator<Item = (f128,)> {
95+
self.inputs_f128.iter().map(|f| (f.0,))
96+
}
97+
}
98+
99+
#[cfg(f128_enabled)]
100+
impl GenerateInput<(f128, f128)> for CachedInput {
101+
fn get_cases(&self) -> impl Iterator<Item = (f128, f128)> {
102+
self.inputs_f128.iter().map(|f| (f.0, f.1))
103+
}
104+
}

0 commit comments

Comments
 (0)