Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix nm #84

Merged
merged 6 commits into from
Oct 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ install:
script:
- cargo generate-lockfile
- if [[ $TRAVIS_OS_NAME = "linux" ]]; then
sudo apt-get remove -y qemu-user-static &&
sudo apt-get install -y qemu-user-static &&
sh ci/run-docker.sh $TARGET;
else
cargo test --target $TARGET &&
Expand Down
2 changes: 2 additions & 0 deletions ci/docker/thumbv6m-none-eabi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev
RUN curl -sf "https://raw.githubusercontent.com/japaric/rust-everywhere/master/install.sh" | \
bash -s -- --at /usr/bin --from japaric/xargo --for x86_64-unknown-linux-gnu --tag v0.1.10
ENV AR_thumbv6m_none_eabi=arm-none-eabi-ar \
CARGO_TARGET_THUMBV6M_NONE_EABI_LINKER=arm-none-eabi-gcc \
CC_thumbv6m_none_eabi=arm-none-eabi-gcc \
2 changes: 2 additions & 0 deletions ci/docker/thumbv7em-none-eabi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev
RUN curl -sf "https://raw.githubusercontent.com/japaric/rust-everywhere/master/install.sh" | \
bash -s -- --at /usr/bin --from japaric/xargo --for x86_64-unknown-linux-gnu --tag v0.1.10
ENV AR_thumbv7em_none_eabi=arm-none-eabi-ar \
CARGO_TARGET_THUMBV7EM_NONE_EABI_LINKER=arm-none-eabi-gcc \
CC_thumbv7em_none_eabi=arm-none-eabi-gcc \
2 changes: 2 additions & 0 deletions ci/docker/thumbv7em-none-eabihf/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev
RUN curl -sf "https://raw.githubusercontent.com/japaric/rust-everywhere/master/install.sh" | \
bash -s -- --at /usr/bin --from japaric/xargo --for x86_64-unknown-linux-gnu --tag v0.1.10
ENV AR_thumbv7em_none_eabihf=arm-none-eabi-ar \
CARGO_TARGET_THUMBV7EM_NONE_EABIHF_LINKER=arm-none-eabi-gcc \
CC_thumbv7em_none_eabihf=arm-none-eabi-gcc \
2 changes: 2 additions & 0 deletions ci/docker/thumbv7m-none-eabi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev
RUN curl -sf "https://raw.githubusercontent.com/japaric/rust-everywhere/master/install.sh" | \
bash -s -- --at /usr/bin --from japaric/xargo --for x86_64-unknown-linux-gnu --tag v0.1.10
ENV AR_thumbv7m_none_eabi=arm-none-eabi-ar \
CARGO_TARGET_THUMBV7M_NONE_EABI_LINKER=arm-none-eabi-gcc \
CC_thumbv7m_none_eabi=arm-none-eabi-gcc \
2 changes: 1 addition & 1 deletion ci/run-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ run() {
-v `rustc --print sysroot`:/rust:ro \
-w /checkout \
-it $target \
sh -c "PATH=\$PATH:/rust/bin ci/run.sh $target"
sh -c "HOME=/tmp PATH=\$PATH:/rust/bin ci/run.sh $target"
}

if [ -z "$1" ]; then
Expand Down
12 changes: 7 additions & 5 deletions ci/run.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
set -e

# Test our implementation
case $1 in
thumb*)
curl -sf "https://raw.githubusercontent.com/japaric/rust-everywhere/master/install.sh" | \
bash -s -- --at /usr/bin --from japaric/xargo --tag v0.1.10
xargo build --target $1
xargo build --target $1 --release
;;
Expand All @@ -29,7 +29,7 @@ case $1 in
esac

# 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
armv7-*)
PREFIX=arm-linux-gnueabihf-
Expand All @@ -55,8 +55,10 @@ case $TRAVIS_OS_NAME in
esac

# NOTE On i586, It's normal that the get_pc_thunk symbol appears several times so ignore it
$PREFIX$NM -g --defined-only /target/${1}/debug/librustc_builtins.rlib | \
sort | uniq -d | grep -v __x86.get_pc_thunk | grep 'T __'
stdout=$($PREFIX$NM -g --defined-only /target/${1}/debug/librustc_builtins.rlib)

set +e
echo $stdout | sort | uniq -d | grep -v __x86.get_pc_thunk | grep 'T __'

if test $? = 0; then
exit 1
Expand Down
145 changes: 117 additions & 28 deletions src/float/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@ macro_rules! add {
#[allow(unused_parens)]
#[cfg_attr(not(test), no_mangle)]
pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
let one = Wrapping(1 as <$ty as Float>::Int);
let zero = Wrapping(0 as <$ty as Float>::Int);

let bits = Wrapping(<$ty>::bits() as <$ty as Float>::Int);
let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int);
let exponent_bits = Wrapping(<$ty>::exponent_bits() as <$ty as Float>::Int);
let max_exponent = (one << exponent_bits.0 as usize) - one;

let implicit_bit = one << significand_bits.0 as usize;
let significand_mask = implicit_bit - one;
let sign_bit = one << (significand_bits + exponent_bits).0 as usize;
let abs_mask = sign_bit - one;
let exponent_mask = abs_mask ^ significand_mask;
let inf_rep = exponent_mask;
let quiet_bit = implicit_bit >> 1;
let qnan_rep = exponent_mask | quiet_bit;

let mut a_rep = Wrapping(a.repr());
let mut b_rep = Wrapping(b.repr());
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;
let one = Wrapping(1 as <$ty as Float>::Int);
let zero = Wrapping(0 as <$ty as Float>::Int);

let bits = Wrapping(<$ty>::bits() as <$ty as Float>::Int);
let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int);
let exponent_bits = bits - significand_bits - one;
let max_exponent = (one << exponent_bits.0 as usize) - one;

let implicit_bit = one << significand_bits.0 as usize;
let significand_mask = implicit_bit - one;
let sign_bit = one << (significand_bits + exponent_bits).0 as usize;
let abs_mask = sign_bit - one;
let exponent_mask = abs_mask ^ significand_mask;
let inf_rep = exponent_mask;
let quiet_bit = implicit_bit >> 1;
let qnan_rep = exponent_mask | quiet_bit;

let mut a_rep = Wrapping(a.repr());
let mut b_rep = Wrapping(b.repr());
let a_abs = a_rep & abs_mask;
let b_abs = b_rep & abs_mask;

// Detect if a or b is zero, infinity, or NaN.
if a_abs - one >= inf_rep - one ||
Expand Down Expand Up @@ -188,7 +188,7 @@ mod tests {
use core::{f32, f64};

use float::Float;
use qc::{F32, F64};
use qc::{U32, U64};

// NOTE The tests below have special handing for NaN values.
// Because NaN != NaN, the floating-point representations must be used
Expand All @@ -212,18 +212,107 @@ mod tests {
}
}

// TODO: Add F32/F64 to qc so that they print the right values (at the very least)
check! {
fn __addsf3(f: extern fn(f32, f32) -> f32,
a: F32,
b: F32)
a: U32,
b: U32)
-> Option<FRepr<f32> > {
Some(FRepr(f(a.0, b.0)))
let (a, b) = (f32::from_repr(a.0), f32::from_repr(b.0));
Some(FRepr(f(a, b)))
}

fn __adddf3(f: extern fn(f64, f64) -> f64,
a: F64,
b: F64) -> Option<FRepr<f64> > {
Some(FRepr(f(a.0, b.0)))
a: U64,
b: U64) -> Option<FRepr<f64> > {
let (a, b) = (f64::from_repr(a.0), f64::from_repr(b.0));
Some(FRepr(f(a, b)))
}
}

// More tests for special float values

#[test]
fn test_float_tiny_plus_tiny() {
let tiny = f32::from_repr(1);
let r = super::__addsf3(tiny, tiny);
assert!(r.eq_repr(tiny + tiny));
}

#[test]
fn test_double_tiny_plus_tiny() {
let tiny = f64::from_repr(1);
let r = super::__adddf3(tiny, tiny);
assert!(r.eq_repr(tiny + tiny));
}

#[test]
fn test_float_small_plus_small() {
let a = f32::from_repr(327);
let b = f32::from_repr(256);
let r = super::__addsf3(a, b);
assert!(r.eq_repr(a + b));
}

#[test]
fn test_double_small_plus_small() {
let a = f64::from_repr(327);
let b = f64::from_repr(256);
let r = super::__adddf3(a, b);
assert!(r.eq_repr(a + b));
}

#[test]
fn test_float_one_plus_one() {
let r = super::__addsf3(1f32, 1f32);
assert!(r.eq_repr(1f32 + 1f32));
}

#[test]
fn test_double_one_plus_one() {
let r = super::__adddf3(1f64, 1f64);
assert!(r.eq_repr(1f64 + 1f64));
}

#[test]
fn test_float_different_nan() {
let a = f32::from_repr(1);
let b = f32::from_repr(0b11111111100100010001001010101010);
let x = super::__addsf3(a, b);
let y = a + b;
assert!(x.eq_repr(y));
}

#[test]
fn test_double_different_nan() {
let a = f64::from_repr(1);
let b = f64::from_repr(0b1111111111110010001000100101010101001000101010000110100011101011);
let x = super::__adddf3(a, b);
let y = a + b;
assert!(x.eq_repr(y));
}

#[test]
fn test_float_nan() {
let r = super::__addsf3(f32::NAN, 1.23);
assert_eq!(r.repr(), f32::NAN.repr());
}

#[test]
fn test_double_nan() {
let r = super::__adddf3(f64::NAN, 1.23);
assert_eq!(r.repr(), f64::NAN.repr());
}

#[test]
fn test_float_inf() {
let r = super::__addsf3(f32::INFINITY, -123.4);
assert_eq!(r, f32::INFINITY);
}

#[test]
fn test_double_inf() {
let r = super::__adddf3(f64::INFINITY, -123.4);
assert_eq!(r, f64::INFINITY);
}
}
79 changes: 1 addition & 78 deletions src/float/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,21 @@ pub trait Float: Sized + Copy {
/// Returns the bitwidth of the float type
fn bits() -> u32;

/// Returns the bitwidth of the exponent
fn exponent_bits() -> u32;

/// Returns the bitwidth of the significand
fn significand_bits() -> u32;

/// Returns a mask for the sign bit of `self`
fn sign_mask() -> Self::Int;

/// Returns a mask for the exponent portion of `self`
fn exponent_mask() -> Self::Int;

/// Returns a mask for the significand portion of `self`
fn significand_mask() -> Self::Int;

/// Returns the sign bit of `self`
fn sign(self) -> bool;

/// Returns the exponent portion of `self`, shifted to the right
fn exponent(self) -> Self::Int;

/// Returns the significand portion of `self`
fn significand(self) -> Self::Int;

/// Returns `self` transmuted to `Self::Int`
fn repr(self) -> Self::Int;

#[cfg(test)]
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
/// represented in multiple different ways. This method returns `true` if two NaNs are
/// represented in multiple different ways. This methods returns `true` if two NaNs are
/// compared.
fn eq_repr(self, rhs: Self) -> bool;

/// Returns a `Self::Int` transmuted back to `Self`
fn from_repr(a: Self::Int) -> Self;

/// Constructs a `Self` from its parts
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self;

/// Returns (normalized exponent, normalized significand)
fn normalize(significand: Self::Int) -> (i32, Self::Int);
}
Expand All @@ -58,21 +34,9 @@ impl Float for f32 {
fn bits() -> u32 {
32
}
fn exponent_bits() -> u32 {
8
}
fn significand_bits() -> u32 {
23
}
fn sign_mask() -> Self::Int {
1 << (Self::bits() - 1)
}
fn exponent_mask() -> Self::Int {
((1 << Self::exponent_bits()) - 1) << Self::significand_bits()
}
fn significand_mask() -> Self::Int {
(1 << Self::significand_bits()) - 1
}
fn repr(self) -> Self::Int {
unsafe { mem::transmute(self) }
}
Expand All @@ -87,21 +51,6 @@ impl Float for f32 {
fn from_repr(a: Self::Int) -> Self {
unsafe { mem::transmute(a) }
}

fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
exponent & Self::exponent_mask() |
significand & Self::significand_mask())
}
fn sign(self) -> bool {
(self.repr() & Self::sign_mask()) != 0
}
fn exponent(self) -> Self::Int {
self.repr() >> Self::significand_bits() & Self::exponent_mask()
}
fn significand(self) -> Self::Int {
self.repr() & Self::significand_mask()
}
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand.leading_zeros()
.wrapping_sub((1u32 << Self::significand_bits()).leading_zeros());
Expand All @@ -113,21 +62,9 @@ impl Float for f64 {
fn bits() -> u32 {
64
}
fn exponent_bits() -> u32 {
11
}
fn significand_bits() -> u32 {
52
}
fn sign_mask() -> Self::Int {
1 << (Self::bits() - 1)
}
fn exponent_mask() -> Self::Int {
((1 << Self::exponent_bits()) - 1) << Self::significand_bits()
}
fn significand_mask() -> Self::Int {
(1 << Self::significand_bits()) - 1
}
fn repr(self) -> Self::Int {
unsafe { mem::transmute(self) }
}
Expand All @@ -142,20 +79,6 @@ impl Float for f64 {
fn from_repr(a: Self::Int) -> Self {
unsafe { mem::transmute(a) }
}
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_repr(((sign as Self::Int) << (Self::bits() - 1)) |
exponent & Self::exponent_mask() |
significand & Self::significand_mask())
}
fn sign(self) -> bool {
(self.repr() & Self::sign_mask()) != 0
}
fn exponent(self) -> Self::Int {
self.repr() >> Self::significand_bits() & Self::exponent_mask()
}
fn significand(self) -> Self::Int {
self.repr() & Self::significand_mask()
}
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand.leading_zeros()
.wrapping_sub((1u64 << Self::significand_bits()).leading_zeros());
Expand Down
Loading