commit
c56faf22ab
13
ci/run.sh
13
ci/run.sh
|
@ -28,6 +28,19 @@ case $1 in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# Verify that there are no undefined symbols to `panic` within our implementations
|
||||||
|
# TODO(#79) fix the undefined references problem for debug-assertions+lto
|
||||||
|
case $1 in
|
||||||
|
thumb*)
|
||||||
|
RUSTFLAGS="-C debug-assertions=no -C link-arg=-nostartfiles" xargo rustc --features c --target $1 --bin intrinsics -- -C lto
|
||||||
|
xargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
RUSTFLAGS="-C debug-assertions=no" cargo rustc --features c --target $1 --bin intrinsics -- -C lto
|
||||||
|
cargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# Look out for duplicated symbols when we include the compiler-rt (C) implementation
|
# Look out for duplicated symbols when we include the compiler-rt (C) implementation
|
||||||
PREFIX=$(echo $1 | sed -e 's/unknown-//')-
|
PREFIX=$(echo $1 | sed -e 's/unknown-//')-
|
||||||
case $1 in
|
case $1 in
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
// to link due to the missing intrinsic (symbol).
|
// to link due to the missing intrinsic (symbol).
|
||||||
|
|
||||||
#![allow(unused_features)]
|
#![allow(unused_features)]
|
||||||
|
#![cfg_attr(thumb, no_main)]
|
||||||
#![deny(dead_code)]
|
#![deny(dead_code)]
|
||||||
|
#![feature(asm)]
|
||||||
#![feature(core_float)]
|
#![feature(core_float)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![cfg_attr(thumb, no_main)]
|
|
||||||
|
|
||||||
#[cfg(not(thumb))]
|
#[cfg(not(thumb))]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
@ -304,50 +305,56 @@ mod intrinsics {
|
||||||
fn run() {
|
fn run() {
|
||||||
use intrinsics::*;
|
use intrinsics::*;
|
||||||
|
|
||||||
aeabi_d2f(2.);
|
// A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO
|
||||||
aeabi_d2i(2.);
|
fn bb<T>(dummy: T) -> T {
|
||||||
aeabi_d2l(2.);
|
unsafe { asm!("" : : "r"(&dummy)) }
|
||||||
aeabi_d2uiz(2.);
|
dummy
|
||||||
aeabi_d2ulz(2.);
|
}
|
||||||
aeabi_dadd(2., 3.);
|
|
||||||
aeabi_dcmpeq(2., 3.);
|
bb(aeabi_d2f(bb(2.)));
|
||||||
aeabi_dcmpgt(2., 3.);
|
bb(aeabi_d2i(bb(2.)));
|
||||||
aeabi_dcmplt(2., 3.);
|
bb(aeabi_d2l(bb(2.)));
|
||||||
aeabi_ddiv(2., 3.);
|
bb(aeabi_d2uiz(bb(2.)));
|
||||||
aeabi_dmul(2., 3.);
|
bb(aeabi_d2ulz(bb(2.)));
|
||||||
aeabi_dsub(2., 3.);
|
bb(aeabi_dadd(bb(2.), bb(3.)));
|
||||||
aeabi_f2d(2.);
|
bb(aeabi_dcmpeq(bb(2.), bb(3.)));
|
||||||
aeabi_f2iz(2.);
|
bb(aeabi_dcmpgt(bb(2.), bb(3.)));
|
||||||
aeabi_f2lz(2.);
|
bb(aeabi_dcmplt(bb(2.), bb(3.)));
|
||||||
aeabi_f2uiz(2.);
|
bb(aeabi_ddiv(bb(2.), bb(3.)));
|
||||||
aeabi_f2ulz(2.);
|
bb(aeabi_dmul(bb(2.), bb(3.)));
|
||||||
aeabi_fadd(2., 3.);
|
bb(aeabi_dsub(bb(2.), bb(3.)));
|
||||||
aeabi_fcmpeq(2., 3.);
|
bb(aeabi_f2d(bb(2.)));
|
||||||
aeabi_fcmpgt(2., 3.);
|
bb(aeabi_f2iz(bb(2.)));
|
||||||
aeabi_fcmplt(2., 3.);
|
bb(aeabi_f2lz(bb(2.)));
|
||||||
aeabi_fdiv(2., 3.);
|
bb(aeabi_f2uiz(bb(2.)));
|
||||||
aeabi_fmul(2., 3.);
|
bb(aeabi_f2ulz(bb(2.)));
|
||||||
aeabi_fsub(2., 3.);
|
bb(aeabi_fadd(bb(2.), bb(3.)));
|
||||||
aeabi_i2d(2);
|
bb(aeabi_fcmpeq(bb(2.), bb(3.)));
|
||||||
aeabi_i2f(2);
|
bb(aeabi_fcmpgt(bb(2.), bb(3.)));
|
||||||
aeabi_idiv(2, 3);
|
bb(aeabi_fcmplt(bb(2.), bb(3.)));
|
||||||
aeabi_idivmod(2, 3);
|
bb(aeabi_fdiv(bb(2.), bb(3.)));
|
||||||
aeabi_l2d(2);
|
bb(aeabi_fmul(bb(2.), bb(3.)));
|
||||||
aeabi_l2f(2);
|
bb(aeabi_fsub(bb(2.), bb(3.)));
|
||||||
aeabi_ldivmod(2, 3);
|
bb(aeabi_i2d(bb(2)));
|
||||||
aeabi_lmul(2, 3);
|
bb(aeabi_i2f(bb(2)));
|
||||||
aeabi_ui2d(2);
|
bb(aeabi_idiv(bb(2), bb(3)));
|
||||||
aeabi_ui2f(2);
|
bb(aeabi_idivmod(bb(2), bb(3)));
|
||||||
aeabi_uidiv(2, 3);
|
bb(aeabi_l2d(bb(2)));
|
||||||
aeabi_uidivmod(2, 3);
|
bb(aeabi_l2f(bb(2)));
|
||||||
aeabi_ul2d(2);
|
bb(aeabi_ldivmod(bb(2), bb(3)));
|
||||||
aeabi_ul2f(2);
|
bb(aeabi_lmul(bb(2), bb(3)));
|
||||||
aeabi_uldivmod(2, 3);
|
bb(aeabi_ui2d(bb(2)));
|
||||||
moddi3(2, 3);
|
bb(aeabi_ui2f(bb(2)));
|
||||||
mulodi4(2, 3);
|
bb(aeabi_uidiv(bb(2), bb(3)));
|
||||||
powidf2(2., 3);
|
bb(aeabi_uidivmod(bb(2), bb(3)));
|
||||||
powisf2(2., 3);
|
bb(aeabi_ul2d(bb(2)));
|
||||||
umoddi3(2, 3);
|
bb(aeabi_ul2f(bb(2)));
|
||||||
|
bb(aeabi_uldivmod(bb(2), bb(3)));
|
||||||
|
bb(moddi3(bb(2), bb(3)));
|
||||||
|
bb(mulodi4(bb(2), bb(3)));
|
||||||
|
bb(powidf2(bb(2.), bb(3)));
|
||||||
|
bb(powisf2(bb(2.), bb(3)));
|
||||||
|
bb(umoddi3(bb(2), bb(3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "c", not(thumb)))]
|
#[cfg(all(feature = "c", not(thumb)))]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
#[cfg(test)]
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
pub mod add;
|
pub mod add;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
macro_rules! pow {
|
macro_rules! pow {
|
||||||
($intrinsic:ident: $fty:ty, $ity:ty) => {
|
($intrinsic:ident: $fty:ty, $ity:ident) => {
|
||||||
/// Returns `a` raised to the power `b`
|
/// Returns `a` raised to the power `b`
|
||||||
#[cfg_attr(not(test), no_mangle)]
|
#[cfg_attr(not(test), no_mangle)]
|
||||||
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
|
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
|
||||||
|
@ -11,7 +10,7 @@ macro_rules! pow {
|
||||||
if (b & 1) != 0 {
|
if (b & 1) != 0 {
|
||||||
r *= a;
|
r *= a;
|
||||||
}
|
}
|
||||||
b /= 2;
|
b = sdiv!($ity, b, 2);
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ macro_rules! div {
|
||||||
let a = (a ^ s_a) - s_a;
|
let a = (a ^ s_a) - s_a;
|
||||||
let b = (b ^ s_b) - s_b;
|
let b = (b ^ s_b) - s_b;
|
||||||
let s = s_a ^ s_b;
|
let s = s_a ^ s_b;
|
||||||
let r = (a as $uty) / (b as $uty);
|
|
||||||
|
let r = udiv!(a as $uty, b as $uty);
|
||||||
(r as $ty ^ s) - s
|
(r as $ty ^ s) - s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +26,8 @@ macro_rules! mod_ {
|
||||||
let b = (b ^ s) - s;
|
let b = (b ^ s) - s;
|
||||||
let s = a >> (<$ty>::bits() - 1);
|
let s = a >> (<$ty>::bits() - 1);
|
||||||
let a = (a ^ s) - s;
|
let a = (a ^ s) - s;
|
||||||
let r = (a as $uty) % (b as $uty);
|
|
||||||
|
let r = urem!(a as $uty, b as $uty);
|
||||||
(r as $ty ^ s) - s
|
(r as $ty ^ s) - s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use core::mem;
|
use core::{intrinsics, mem};
|
||||||
use int::{Int, LargeInt};
|
use int::{Int, LargeInt};
|
||||||
|
|
||||||
/// Returns `n / d`
|
/// Returns `n / d`
|
||||||
|
@ -7,7 +7,11 @@ use int::{Int, LargeInt};
|
||||||
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
|
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
|
||||||
// Special cases
|
// Special cases
|
||||||
if d == 0 {
|
if d == 0 {
|
||||||
panic!("Division by zero");
|
// NOTE This should be unreachable in safe Rust because the program will panic before
|
||||||
|
// this intrinsic is called
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
@ -105,10 +109,11 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
|
||||||
// 0 X
|
// 0 X
|
||||||
// ---
|
// ---
|
||||||
// 0 X
|
// 0 X
|
||||||
|
|
||||||
if let Some(rem) = rem {
|
if let Some(rem) = rem {
|
||||||
*rem = u64::from(n.low() % d.low());
|
*rem = u64::from(urem!(n.low(), d.low()));
|
||||||
}
|
}
|
||||||
return u64::from(n.low() / d.low());
|
return u64::from(udiv!(n.low(), d.low()));
|
||||||
} else {
|
} else {
|
||||||
// 0 X
|
// 0 X
|
||||||
// ---
|
// ---
|
||||||
|
@ -129,7 +134,11 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
|
||||||
// K X
|
// K X
|
||||||
// ---
|
// ---
|
||||||
// 0 0
|
// 0 0
|
||||||
panic!("Division by zero");
|
// NOTE This should be unreachable in safe Rust because the program will panic before
|
||||||
|
// this intrinsic is called
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.low() == 0 {
|
if n.low() == 0 {
|
||||||
|
@ -137,9 +146,9 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
|
||||||
// ---
|
// ---
|
||||||
// K 0
|
// K 0
|
||||||
if let Some(rem) = rem {
|
if let Some(rem) = rem {
|
||||||
*rem = u64::from_parts(0, n.high() % d.high());
|
*rem = u64::from_parts(0, urem!(n.high(), d.high()));
|
||||||
}
|
}
|
||||||
return u64::from(n.high() / d.high());
|
return u64::from(udiv!(n.high(), d.high()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// K K
|
// K K
|
||||||
|
|
61
src/lib.rs
61
src/lib.rs
|
@ -13,6 +13,67 @@
|
||||||
// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
|
// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
|
||||||
// implementation of that intrinsic and we'll prefer to use that
|
// implementation of that intrinsic and we'll prefer to use that
|
||||||
|
|
||||||
|
// TODO(rust-lang/rust#37029) use e.g. checked_div(_).unwrap_or_else(|| abort())
|
||||||
|
macro_rules! udiv {
|
||||||
|
($a:expr, $b:expr) => {
|
||||||
|
unsafe {
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
|
||||||
|
if b == 0 {
|
||||||
|
::core::intrinsics::abort()
|
||||||
|
} else {
|
||||||
|
::core::intrinsics::unchecked_div(a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! sdiv {
|
||||||
|
($sty:ident, $a:expr, $b:expr) => {
|
||||||
|
unsafe {
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
|
||||||
|
if b == 0 || (b == -1 && a == $sty::min_value()) {
|
||||||
|
::core::intrinsics::abort()
|
||||||
|
} else {
|
||||||
|
::core::intrinsics::unchecked_div(a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! urem {
|
||||||
|
($a:expr, $b:expr) => {
|
||||||
|
unsafe {
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
|
||||||
|
if b == 0 {
|
||||||
|
::core::intrinsics::abort()
|
||||||
|
} else {
|
||||||
|
::core::intrinsics::unchecked_rem(a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! srem {
|
||||||
|
($sty:ty, $a:expr, $b:expr) => {
|
||||||
|
unsafe {
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
|
||||||
|
if b == 0 || (b == -1 && a == $sty::min_value()) {
|
||||||
|
::core::intrinsics::abort()
|
||||||
|
} else {
|
||||||
|
::core::intrinsics::unchecked_rem(a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quickcheck;
|
extern crate quickcheck;
|
||||||
|
|
Loading…
Reference in New Issue