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

Commit 5eda282

Browse files
committed
Expose C versions of libm functions in the cb crate
`compiler_builtins` exposes an `extern "C"` version of `libm` routines, so add the same here. There really isn't much to test here (unless we later add tests against C `libm` suites), but one nice benefit is this gives us a library with unmangled names that is easy to `objdump`. In accordance with that, also update `cb` to be a `staticlib`. Unfortunately this also means we have to remove it from the workspace, since Cargo doesn't allow setting `panic = "abort"` for a single crate.
1 parent 233700c commit 5eda282

File tree

6 files changed

+200
-6
lines changed

6 files changed

+200
-6
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ jobs:
144144
- name: Install Rust
145145
run: rustup update nightly --no-self-update && rustup default nightly
146146
- uses: Swatinem/rust-cache@v2
147-
- run: cargo build -p cb
147+
- run: cargo test --manifest-path crates/compiler-builtins-smoke-test/Cargo.toml
148148

149149
benchmarks:
150150
name: Benchmarks

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
.#*
33
/bin
44
/math/src
5-
/math/target
6-
/target
5+
target
76
Cargo.lock
87
musl/
98
**.tar.gz

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ force-soft-floats = []
4343
[workspace]
4444
resolver = "2"
4545
members = [
46-
"crates/compiler-builtins-smoke-test",
4746
"crates/libm-macros",
4847
"crates/libm-test",
4948
"crates/musl-math-sys",
@@ -53,6 +52,10 @@ default-members = [
5352
"crates/libm-macros",
5453
"crates/libm-test",
5554
]
55+
exclude = [
56+
# Requires `panic = abort` so can't be a member of the workspace
57+
"crates/compiler-builtins-smoke-test",
58+
]
5659

5760
[dev-dependencies]
5861
no-panic = "0.1.30"

crates/compiler-builtins-smoke-test/Cargo.toml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,33 @@ edition = "2021"
66
publish = false
77

88
[lib]
9+
crate-type = ["staticlib"]
910
test = false
1011
bench = false
1112

13+
[features]
14+
default = ["arch", "unstable-float"]
15+
16+
# Copied from `libm`'s root `Cargo.toml`'
17+
unstable-float = []
18+
arch = []
19+
1220
[lints.rust]
1321
unexpected_cfgs = { level = "warn", check-cfg = [
1422
"cfg(arch_enabled)",
1523
"cfg(assert_no_panic)",
16-
"cfg(f128_enabled)",
17-
"cfg(f16_enabled)",
1824
"cfg(intrinsics_enabled)",
1925
'cfg(feature, values("checked"))',
2026
'cfg(feature, values("force-soft-floats"))',
2127
'cfg(feature, values("unstable"))',
2228
'cfg(feature, values("unstable-intrinsics"))',
2329
'cfg(feature, values("unstable-public-internals"))',
2430
] }
31+
32+
[profile.dev]
33+
panic = "abort"
34+
35+
[profile.release]
36+
panic = "abort"
37+
codegen-units = 1
38+
lto = "fat"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[path = "../../configure.rs"]
2+
mod configure;
3+
4+
fn main() {
5+
let cfg = configure::Config::from_env();
6+
configure::emit_libm_config(&cfg);
7+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,183 @@
11
//! Fake compiler-builtins crate
22
//!
33
//! This is used to test that we can source import `libm` into the compiler-builtins crate.
4+
//! Additionally, it provides a `#[no_mangle]` C API that can be easier to inspect than the
5+
//! default `.rlib`.
46
57
#![feature(core_intrinsics)]
8+
#![feature(f16)]
9+
#![feature(f128)]
610
#![allow(internal_features)]
711
#![no_std]
812

913
#[allow(dead_code)]
1014
#[allow(clippy::all)] // We don't get `libm`'s list of `allow`s, so just ignore Clippy.
1115
#[path = "../../../src/math/mod.rs"]
1216
pub mod libm;
17+
18+
use core::ffi::c_int;
19+
20+
/// Mark functions `#[no_mangle]` and with the C ABI.
21+
macro_rules! no_mangle {
22+
($( $name:ident( $($tt:tt)+ ) -> $ret:ty; )+) => {
23+
$( no_mangle!(@inner $name( $($tt)+ ) -> $ret); )+
24+
};
25+
26+
// Handle simple functions with single return types
27+
(@inner $name:ident( $($arg:ident: $aty:ty),+ ) -> $ret:ty) => {
28+
#[no_mangle]
29+
extern "C" fn $name($($arg: $aty),+) -> $ret {
30+
libm::$name($($arg),+)
31+
}
32+
};
33+
34+
35+
// Functions with `&mut` return values need to be handled differently, use `|` to
36+
// separate inputs vs. outputs.
37+
(
38+
@inner $name:ident( $($arg:ident: $aty:ty),+ | $($rarg:ident: $rty:ty),+) -> $ret:ty
39+
) => {
40+
#[no_mangle]
41+
extern "C" fn $name($($arg: $aty,)+ $($rarg: $rty),+) -> $ret {
42+
let ret;
43+
(ret, $(*$rarg),+) = libm::$name($($arg),+);
44+
ret
45+
}
46+
};
47+
}
48+
49+
no_mangle! {
50+
frexp(x: f64 | y: &mut c_int) -> f64;
51+
frexpf(x: f32 | y: &mut c_int) -> f32;
52+
acos(x: f64) -> f64;
53+
acosf(x: f32) -> f32;
54+
acosh(x: f64) -> f64;
55+
acoshf(x: f32) -> f32;
56+
asin(x: f64) -> f64;
57+
asinf(x: f32) -> f32;
58+
asinh(x: f64) -> f64;
59+
asinhf(x: f32) -> f32;
60+
atan(x: f64) -> f64;
61+
atan2(x: f64, y: f64) -> f64;
62+
atan2f(x: f32, y: f32) -> f32;
63+
atanf(x: f32) -> f32;
64+
atanh(x: f64) -> f64;
65+
atanhf(x: f32) -> f32;
66+
cbrt(x: f64) -> f64;
67+
cbrtf(x: f32) -> f32;
68+
ceil(x: f64) -> f64;
69+
ceilf(x: f32) -> f32;
70+
copysign(x: f64, y: f64) -> f64;
71+
copysignf(x: f32, y: f32) -> f32;
72+
copysignf128(x: f128, y: f128) -> f128;
73+
copysignf16(x: f16, y: f16) -> f16;
74+
cos(x: f64) -> f64;
75+
cosf(x: f32) -> f32;
76+
cosh(x: f64) -> f64;
77+
coshf(x: f32) -> f32;
78+
erf(x: f64) -> f64;
79+
erfc(x: f64) -> f64;
80+
erfcf(x: f32) -> f32;
81+
erff(x: f32) -> f32;
82+
exp(x: f64) -> f64;
83+
exp10(x: f64) -> f64;
84+
exp10f(x: f32) -> f32;
85+
exp2(x: f64) -> f64;
86+
exp2f(x: f32) -> f32;
87+
expf(x: f32) -> f32;
88+
expm1(x: f64) -> f64;
89+
expm1f(x: f32) -> f32;
90+
fabs(x: f64) -> f64;
91+
fabsf(x: f32) -> f32;
92+
fabsf128(x: f128) -> f128;
93+
fabsf16(x: f16) -> f16;
94+
fdim(x: f64, y: f64) -> f64;
95+
fdimf(x: f32, y: f32) -> f32;
96+
floor(x: f64) -> f64;
97+
floorf(x: f32) -> f32;
98+
fma(x: f64, y: f64, z: f64) -> f64;
99+
fmaf(x: f32, y: f32, z: f32) -> f32;
100+
fmax(x: f64, y: f64) -> f64;
101+
fmaxf(x: f32, y: f32) -> f32;
102+
fmin(x: f64, y: f64) -> f64;
103+
fminf(x: f32, y: f32) -> f32;
104+
fmod(x: f64, y: f64) -> f64;
105+
fmodf(x: f32, y: f32) -> f32;
106+
hypot(x: f64, y: f64) -> f64;
107+
hypotf(x: f32, y: f32) -> f32;
108+
ilogb(x: f64) -> c_int;
109+
ilogbf(x: f32) -> c_int;
110+
j0(x: f64) -> f64;
111+
j0f(x: f32) -> f32;
112+
j1(x: f64) -> f64;
113+
j1f(x: f32) -> f32;
114+
jn(x: c_int, y: f64) -> f64;
115+
jnf(x: c_int, y: f32) -> f32;
116+
ldexp(x: f64, y: c_int) -> f64;
117+
ldexpf(x: f32, y: c_int) -> f32;
118+
lgamma(x: f64) -> f64;
119+
lgamma_r(x: f64 | r: &mut c_int) -> f64;
120+
lgammaf(x: f32) -> f32;
121+
lgammaf_r(x: f32 | r: &mut c_int) -> f32;
122+
log(x: f64) -> f64;
123+
log10(x: f64) -> f64;
124+
log10f(x: f32) -> f32;
125+
log1p(x: f64) -> f64;
126+
log1pf(x: f32) -> f32;
127+
log2(x: f64) -> f64;
128+
log2f(x: f32) -> f32;
129+
logf(x: f32) -> f32;
130+
modf(x: f64 | r: &mut f64) -> f64;
131+
modff(x: f32 | r: &mut f32) -> f32;
132+
nextafter(x: f64, y: f64) -> f64;
133+
nextafterf(x: f32, y: f32) -> f32;
134+
pow(x: f64, y: f64) -> f64;
135+
powf(x: f32, y: f32) -> f32;
136+
remainder(x: f64, y: f64) -> f64;
137+
remainderf(x: f32, y: f32) -> f32;
138+
remquo(x: f64, y: f64 | q: &mut c_int) -> f64;
139+
remquof(x: f32, y: f32 | q: &mut c_int) -> f32;
140+
rint(x: f64) -> f64;
141+
rintf(x: f32) -> f32;
142+
round(x: f64) -> f64;
143+
roundf(x: f32) -> f32;
144+
scalbn(x: f64, y: c_int) -> f64;
145+
scalbnf(x: f32, y: c_int) -> f32;
146+
sin(x: f64) -> f64;
147+
sinf(x: f32) -> f32;
148+
sinh(x: f64) -> f64;
149+
sinhf(x: f32) -> f32;
150+
sqrt(x: f64) -> f64;
151+
sqrtf(x: f32) -> f32;
152+
tan(x: f64) -> f64;
153+
tanf(x: f32) -> f32;
154+
tanh(x: f64) -> f64;
155+
tanhf(x: f32) -> f32;
156+
tgamma(x: f64) -> f64;
157+
tgammaf(x: f32) -> f32;
158+
trunc(x: f64) -> f64;
159+
truncf(x: f32) -> f32;
160+
y0(x: f64) -> f64;
161+
y0f(x: f32) -> f32;
162+
y1(x: f64) -> f64;
163+
y1f(x: f32) -> f32;
164+
yn(x: c_int, y: f64) -> f64;
165+
ynf(x: c_int, y: f32) -> f32;
166+
}
167+
168+
/* sincos has no direct return type, not worth handling in the macro */
169+
170+
#[no_mangle]
171+
extern "C" fn sincos(x: f64, s: &mut f64, c: &mut f64) {
172+
(*s, *c) = libm::sincos(x);
173+
}
174+
175+
#[no_mangle]
176+
extern "C" fn sincosf(x: f32, s: &mut f32, c: &mut f32) {
177+
(*s, *c) = libm::sincosf(x);
178+
}
179+
180+
#[panic_handler]
181+
fn panic(_info: &core::panic::PanicInfo) -> ! {
182+
loop {}
183+
}

0 commit comments

Comments
 (0)