Skip to content

Commit

Permalink
Merge #131
Browse files Browse the repository at this point in the history
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 #129

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
  • Loading branch information
bors[bot] and japaric committed Jul 25, 2018
2 parents 861720b + 3c5ba36 commit 96e36ea
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 52 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Expand Up @@ -17,6 +17,9 @@ matrix:
- env: TARGET=x86_64-unknown-linux-gnu
- env: TARGET=cargo-fmt
rust: beta
# no-panic link test
- env: TARGET=armv7-unknown-linux-gnueabihf
rust: nightly

before_install: set -e

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Expand Up @@ -9,5 +9,9 @@ name = "libm"
repository = "https://github.com/japaric/libm"
version = "0.1.2"

[features]
# only used to run our test suite
checked = []

[workspace]
members = ["cb", "test-generator"]
13 changes: 11 additions & 2 deletions ci/script.sh
Expand Up @@ -6,17 +6,26 @@ main() {
return
fi

# test that the functions don't contain invocations of `panic!`
if [ $TRAVIS_RUST_VERSION = nightly ]; then
cross build --release --target $TARGET --example no-panic
return
fi

# quick check
cargo check

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

# run unit tests
cross test --lib --features checked --target $TARGET --release

# generate tests
cargo run --package test-generator --target x86_64-unknown-linux-musl

# run tests
cross test --target $TARGET --release
# run generated tests
cross test --tests --features checked --target $TARGET --release

# TODO need to fix overflow issues (cf. issue #4)
# cross test --target $TARGET
Expand Down
115 changes: 115 additions & 0 deletions examples/no-panic.rs
@@ -0,0 +1,115 @@
#![feature(lang_items)]
#![feature(panic_implementation)]
#![no_main]
#![no_std]

extern crate libm;

use core::panic::PanicInfo;
use core::ptr;

macro_rules! force_eval {
($e:expr) => {
unsafe {
core::ptr::read_volatile(&$e);
}
};
}

#[no_mangle]
pub fn main() {
force_eval!(libm::acos(random()));
force_eval!(libm::acosf(random()));
force_eval!(libm::asin(random()));
force_eval!(libm::asinf(random()));
force_eval!(libm::atan(random()));
force_eval!(libm::atan2(random(), random()));
force_eval!(libm::atan2f(random(), random()));
force_eval!(libm::atanf(random()));
force_eval!(libm::cbrt(random()));
force_eval!(libm::cbrtf(random()));
force_eval!(libm::ceil(random()));
force_eval!(libm::ceilf(random()));
force_eval!(libm::cos(random()));
force_eval!(libm::cosf(random()));
force_eval!(libm::cosh(random()));
force_eval!(libm::coshf(random()));
force_eval!(libm::exp(random()));
force_eval!(libm::exp2(random()));
force_eval!(libm::exp2f(random()));
force_eval!(libm::expf(random()));
force_eval!(libm::expm1(random()));
force_eval!(libm::expm1f(random()));
force_eval!(libm::fabs(random()));
force_eval!(libm::fabsf(random()));
force_eval!(libm::fdim(random(), random()));
force_eval!(libm::fdimf(random(), random()));
force_eval!(libm::floor(random()));
force_eval!(libm::floorf(random()));
force_eval!(libm::fma(random(), random(), random()));
force_eval!(libm::fmaf(random(), random(), random()));
force_eval!(libm::fmod(random(), random()));
force_eval!(libm::fmodf(random(), random()));
force_eval!(libm::hypot(random(), random()));
force_eval!(libm::hypotf(random(), random()));
force_eval!(libm::log(random()));
force_eval!(libm::log2(random()));
force_eval!(libm::log10(random()));
force_eval!(libm::log10f(random()));
force_eval!(libm::log1p(random()));
force_eval!(libm::log1pf(random()));
force_eval!(libm::log2f(random()));
force_eval!(libm::logf(random()));
force_eval!(libm::pow(random(), random()));
force_eval!(libm::powf(random(), random()));
force_eval!(libm::round(random()));
force_eval!(libm::roundf(random()));
force_eval!(libm::scalbn(random(), random()));
force_eval!(libm::scalbnf(random(), random()));
force_eval!(libm::sin(random()));
force_eval!(libm::sinf(random()));
force_eval!(libm::sinh(random()));
force_eval!(libm::sinhf(random()));
force_eval!(libm::sqrt(random()));
force_eval!(libm::sqrtf(random()));
force_eval!(libm::tan(random()));
force_eval!(libm::tanf(random()));
force_eval!(libm::tanh(random()));
force_eval!(libm::tanhf(random()));
force_eval!(libm::trunc(random()));
force_eval!(libm::truncf(random()));
}

fn random<T>() -> T
where
T: Copy,
{
unsafe {
static mut X: usize = 0;
X += 8;
ptr::read_volatile(X as *const T)
}
}

#[panic_implementation]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
// loop {}
extern "C" {
fn thou_shalt_not_panic() -> !;
}

unsafe { thou_shalt_not_panic() }
}

#[link(name = "c")]
extern "C" {}

#[lang = "eh_personality"]
fn eh() {}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() {}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr1() {}
2 changes: 1 addition & 1 deletion src/math/atan.rs
Expand Up @@ -124,7 +124,7 @@ pub fn atan(x: f64) -> f64 {
return x - x * (s1 + s2);
}

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

if sign != 0 {
-z
Expand Down
52 changes: 52 additions & 0 deletions src/math/mod.rs
Expand Up @@ -6,6 +6,58 @@ macro_rules! force_eval {
};
}

#[cfg(not(feature = "checked"))]
macro_rules! i {
($array:expr, $index:expr) => {
unsafe { *$array.get_unchecked($index) }
};
($array:expr, $index:expr, = , $rhs:expr) => {
unsafe {
*$array.get_unchecked_mut($index) = $rhs;
}
};
($array:expr, $index:expr, += , $rhs:expr) => {
unsafe {
*$array.get_unchecked_mut($index) += $rhs;
}
};
($array:expr, $index:expr, -= , $rhs:expr) => {
unsafe {
*$array.get_unchecked_mut($index) -= $rhs;
}
};
($array:expr, $index:expr, &= , $rhs:expr) => {
unsafe {
*$array.get_unchecked_mut($index) &= $rhs;
}
};
($array:expr, $index:expr, == , $rhs:expr) => {
unsafe { *$array.get_unchecked_mut($index) == $rhs }
};
}

#[cfg(feature = "checked")]
macro_rules! i {
($array:expr, $index:expr) => {
*$array.get($index).unwrap()
};
($array:expr, $index:expr, = , $rhs:expr) => {
*$array.get_mut($index).unwrap() = $rhs;
};
($array:expr, $index:expr, -= , $rhs:expr) => {
*$array.get_mut($index).unwrap() -= $rhs;
};
($array:expr, $index:expr, += , $rhs:expr) => {
*$array.get_mut($index).unwrap() += $rhs;
};
($array:expr, $index:expr, &= , $rhs:expr) => {
*$array.get_mut($index).unwrap() &= $rhs;
};
($array:expr, $index:expr, == , $rhs:expr) => {
*$array.get_mut($index).unwrap() == $rhs
};
}

// Public modules
mod acos;
mod acosf;
Expand Down
2 changes: 1 addition & 1 deletion src/math/rem_pio2.rs
Expand Up @@ -177,7 +177,7 @@ pub fn rem_pio2(x: f64) -> (i32, f64, f64) {
tx[2] = z;
/* skip zero terms, first term is non-zero */
let mut i = 2;
while tx[i] == 0.0 {
while i != 0 && tx[i] == 0.0 {
i -= 1;
}
let mut ty = [0.0; 3];
Expand Down

0 comments on commit 96e36ea

Please sign in to comment.