Skip to content

Commit 96e36ea

Browse files
bors[bot]japaric
andcommitted
131: omit bounds check in release mode r=japaric a=japaric this eliminates panicking branches in the optimized version of the functions. We keep the bounds checks when running the test suite to check that we never do an out of bounds access. This commit also adds a "must link" test that ensures that future changes in our implementation won't add panicking branches. closes rust-lang#129 Co-authored-by: Jorge Aparicio <[email protected]>
2 parents 861720b + 3c5ba36 commit 96e36ea

File tree

8 files changed

+243
-52
lines changed

8 files changed

+243
-52
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ matrix:
1717
- env: TARGET=x86_64-unknown-linux-gnu
1818
- env: TARGET=cargo-fmt
1919
rust: beta
20+
# no-panic link test
21+
- env: TARGET=armv7-unknown-linux-gnueabihf
22+
rust: nightly
2023

2124
before_install: set -e
2225

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@ name = "libm"
99
repository = "https://github.com/japaric/libm"
1010
version = "0.1.2"
1111

12+
[features]
13+
# only used to run our test suite
14+
checked = []
15+
1216
[workspace]
1317
members = ["cb", "test-generator"]

ci/script.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,26 @@ main() {
66
return
77
fi
88

9+
# test that the functions don't contain invocations of `panic!`
10+
if [ $TRAVIS_RUST_VERSION = nightly ]; then
11+
cross build --release --target $TARGET --example no-panic
12+
return
13+
fi
14+
915
# quick check
1016
cargo check
1117

1218
# check that we can source import libm into compiler-builtins
1319
cargo check --package cb
1420

21+
# run unit tests
22+
cross test --lib --features checked --target $TARGET --release
23+
1524
# generate tests
1625
cargo run --package test-generator --target x86_64-unknown-linux-musl
1726

18-
# run tests
19-
cross test --target $TARGET --release
27+
# run generated tests
28+
cross test --tests --features checked --target $TARGET --release
2029

2130
# TODO need to fix overflow issues (cf. issue #4)
2231
# cross test --target $TARGET

examples/no-panic.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#![feature(lang_items)]
2+
#![feature(panic_implementation)]
3+
#![no_main]
4+
#![no_std]
5+
6+
extern crate libm;
7+
8+
use core::panic::PanicInfo;
9+
use core::ptr;
10+
11+
macro_rules! force_eval {
12+
($e:expr) => {
13+
unsafe {
14+
core::ptr::read_volatile(&$e);
15+
}
16+
};
17+
}
18+
19+
#[no_mangle]
20+
pub fn main() {
21+
force_eval!(libm::acos(random()));
22+
force_eval!(libm::acosf(random()));
23+
force_eval!(libm::asin(random()));
24+
force_eval!(libm::asinf(random()));
25+
force_eval!(libm::atan(random()));
26+
force_eval!(libm::atan2(random(), random()));
27+
force_eval!(libm::atan2f(random(), random()));
28+
force_eval!(libm::atanf(random()));
29+
force_eval!(libm::cbrt(random()));
30+
force_eval!(libm::cbrtf(random()));
31+
force_eval!(libm::ceil(random()));
32+
force_eval!(libm::ceilf(random()));
33+
force_eval!(libm::cos(random()));
34+
force_eval!(libm::cosf(random()));
35+
force_eval!(libm::cosh(random()));
36+
force_eval!(libm::coshf(random()));
37+
force_eval!(libm::exp(random()));
38+
force_eval!(libm::exp2(random()));
39+
force_eval!(libm::exp2f(random()));
40+
force_eval!(libm::expf(random()));
41+
force_eval!(libm::expm1(random()));
42+
force_eval!(libm::expm1f(random()));
43+
force_eval!(libm::fabs(random()));
44+
force_eval!(libm::fabsf(random()));
45+
force_eval!(libm::fdim(random(), random()));
46+
force_eval!(libm::fdimf(random(), random()));
47+
force_eval!(libm::floor(random()));
48+
force_eval!(libm::floorf(random()));
49+
force_eval!(libm::fma(random(), random(), random()));
50+
force_eval!(libm::fmaf(random(), random(), random()));
51+
force_eval!(libm::fmod(random(), random()));
52+
force_eval!(libm::fmodf(random(), random()));
53+
force_eval!(libm::hypot(random(), random()));
54+
force_eval!(libm::hypotf(random(), random()));
55+
force_eval!(libm::log(random()));
56+
force_eval!(libm::log2(random()));
57+
force_eval!(libm::log10(random()));
58+
force_eval!(libm::log10f(random()));
59+
force_eval!(libm::log1p(random()));
60+
force_eval!(libm::log1pf(random()));
61+
force_eval!(libm::log2f(random()));
62+
force_eval!(libm::logf(random()));
63+
force_eval!(libm::pow(random(), random()));
64+
force_eval!(libm::powf(random(), random()));
65+
force_eval!(libm::round(random()));
66+
force_eval!(libm::roundf(random()));
67+
force_eval!(libm::scalbn(random(), random()));
68+
force_eval!(libm::scalbnf(random(), random()));
69+
force_eval!(libm::sin(random()));
70+
force_eval!(libm::sinf(random()));
71+
force_eval!(libm::sinh(random()));
72+
force_eval!(libm::sinhf(random()));
73+
force_eval!(libm::sqrt(random()));
74+
force_eval!(libm::sqrtf(random()));
75+
force_eval!(libm::tan(random()));
76+
force_eval!(libm::tanf(random()));
77+
force_eval!(libm::tanh(random()));
78+
force_eval!(libm::tanhf(random()));
79+
force_eval!(libm::trunc(random()));
80+
force_eval!(libm::truncf(random()));
81+
}
82+
83+
fn random<T>() -> T
84+
where
85+
T: Copy,
86+
{
87+
unsafe {
88+
static mut X: usize = 0;
89+
X += 8;
90+
ptr::read_volatile(X as *const T)
91+
}
92+
}
93+
94+
#[panic_implementation]
95+
#[no_mangle]
96+
pub fn panic(_info: &PanicInfo) -> ! {
97+
// loop {}
98+
extern "C" {
99+
fn thou_shalt_not_panic() -> !;
100+
}
101+
102+
unsafe { thou_shalt_not_panic() }
103+
}
104+
105+
#[link(name = "c")]
106+
extern "C" {}
107+
108+
#[lang = "eh_personality"]
109+
fn eh() {}
110+
111+
#[no_mangle]
112+
pub extern "C" fn __aeabi_unwind_cpp_pr0() {}
113+
114+
#[no_mangle]
115+
pub extern "C" fn __aeabi_unwind_cpp_pr1() {}

src/math/atan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn atan(x: f64) -> f64 {
124124
return x - x * (s1 + s2);
125125
}
126126

127-
let z = ATANHI[id as usize] - (x * (s1 + s2) - ATANLO[id as usize] - x);
127+
let z = i!(ATANHI, id as usize) - (x * (s1 + s2) - i!(ATANLO, id as usize) - x);
128128

129129
if sign != 0 {
130130
-z

src/math/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,58 @@ macro_rules! force_eval {
66
};
77
}
88

9+
#[cfg(not(feature = "checked"))]
10+
macro_rules! i {
11+
($array:expr, $index:expr) => {
12+
unsafe { *$array.get_unchecked($index) }
13+
};
14+
($array:expr, $index:expr, = , $rhs:expr) => {
15+
unsafe {
16+
*$array.get_unchecked_mut($index) = $rhs;
17+
}
18+
};
19+
($array:expr, $index:expr, += , $rhs:expr) => {
20+
unsafe {
21+
*$array.get_unchecked_mut($index) += $rhs;
22+
}
23+
};
24+
($array:expr, $index:expr, -= , $rhs:expr) => {
25+
unsafe {
26+
*$array.get_unchecked_mut($index) -= $rhs;
27+
}
28+
};
29+
($array:expr, $index:expr, &= , $rhs:expr) => {
30+
unsafe {
31+
*$array.get_unchecked_mut($index) &= $rhs;
32+
}
33+
};
34+
($array:expr, $index:expr, == , $rhs:expr) => {
35+
unsafe { *$array.get_unchecked_mut($index) == $rhs }
36+
};
37+
}
38+
39+
#[cfg(feature = "checked")]
40+
macro_rules! i {
41+
($array:expr, $index:expr) => {
42+
*$array.get($index).unwrap()
43+
};
44+
($array:expr, $index:expr, = , $rhs:expr) => {
45+
*$array.get_mut($index).unwrap() = $rhs;
46+
};
47+
($array:expr, $index:expr, -= , $rhs:expr) => {
48+
*$array.get_mut($index).unwrap() -= $rhs;
49+
};
50+
($array:expr, $index:expr, += , $rhs:expr) => {
51+
*$array.get_mut($index).unwrap() += $rhs;
52+
};
53+
($array:expr, $index:expr, &= , $rhs:expr) => {
54+
*$array.get_mut($index).unwrap() &= $rhs;
55+
};
56+
($array:expr, $index:expr, == , $rhs:expr) => {
57+
*$array.get_mut($index).unwrap() == $rhs
58+
};
59+
}
60+
961
// Public modules
1062
mod acos;
1163
mod acosf;

src/math/rem_pio2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ pub fn rem_pio2(x: f64) -> (i32, f64, f64) {
177177
tx[2] = z;
178178
/* skip zero terms, first term is non-zero */
179179
let mut i = 2;
180-
while tx[i] == 0.0 {
180+
while i != 0 && tx[i] == 0.0 {
181181
i -= 1;
182182
}
183183
let mut ty = [0.0; 3];

0 commit comments

Comments
 (0)