diff --git a/.gitignore b/.gitignore
index b203ea61f..3fc2fde3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+/defined_symbols.txt
+/undefined_symbols.txt
+/code.tar.gz
+/compiler-rt
*.rs.bk
Cargo.lock
target
diff --git a/ci/run.sh b/ci/run.sh
index 6376d2216..2e3993a38 100755
--- a/ci/run.sh
+++ b/ci/run.sh
@@ -42,9 +42,9 @@ if [ "$NM" = "" ]; then
fi
if [ -d /target ]; then
- path=/target/${1}/debug/deps/libcompiler_builtins-*.rlib
+ path=/target/${1}/release/deps/libcompiler_builtins-*.rlib
else
- path=target/${1}/debug/deps/libcompiler_builtins-*.rlib
+ path=target/${1}/release/deps/libcompiler_builtins-*.rlib
fi
# Look out for duplicated symbols when we include the compiler-rt (C) implementation
@@ -80,10 +80,13 @@ rm -f $path
# Verify that we haven't drop any intrinsic/symbol
build_intrinsics="$cargo build --target $1 -v --example intrinsics"
-RUSTFLAGS="-C debug-assertions=no" $build_intrinsics
-RUSTFLAGS="-C debug-assertions=no" $build_intrinsics --release
-RUSTFLAGS="-C debug-assertions=no" $build_intrinsics --features c
-RUSTFLAGS="-C debug-assertions=no" $build_intrinsics --features c --release
+# Match the behavior with
+# https://github.com/rust-lang/rust/blob/e49442bf9815a67e68f9d9f2f80560ec1d754b31/Cargo.toml#L66-L86.
+export RUSTFLAGS="-C debug-assertions=no -C overflow-checks=no -C codegen-units=10000"
+$build_intrinsics
+$build_intrinsics --release
+$build_intrinsics --features c
+$build_intrinsics --features c --release
# Verify that there are no undefined symbols to `panic` within our
# implementations
@@ -93,15 +96,18 @@ if [ -z "$DEBUG_LTO_BUILD_DOESNT_WORK" ]; then
RUSTFLAGS="-C debug-assertions=no" \
CARGO_INCREMENTAL=0 \
CARGO_PROFILE_DEV_LTO=true \
- $cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics
+ $cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics --release
fi
CARGO_PROFILE_RELEASE_LTO=true \
$cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics --release
+unset RUSTFLAGS
-# Ensure no references to a panicking function
+# Ensure no references to any symbols from core
for rlib in $(echo $path); do
set +ex
- $NM -u $rlib 2>&1 | grep panicking
+ $NM --quiet -U $rlib | grep 'T _ZN4core' | awk '{print $3}' | sort | uniq > defined_symbols.txt
+ $NM --quiet -u $rlib | grep 'U _ZN4core' | awk '{print $2}' | sort | uniq > undefined_symbols.txt
+ grep -v -F -x -f defined_symbols.txt undefined_symbols.txt
if test $? = 0; then
exit 1
diff --git a/src/float/conv.rs b/src/float/conv.rs
index 790c0ab9f..d74db5e97 100644
--- a/src/float/conv.rs
+++ b/src/float/conv.rs
@@ -5,6 +5,7 @@
///
/// The algorithm is explained here:
mod int_to_float {
+ #[rustc_nounwind]
pub fn u32_to_f32_bits(i: u32) -> u32 {
if i == 0 {
return 0;
@@ -17,6 +18,7 @@ mod int_to_float {
(e << 23) + m // + not |, so the mantissa can overflow into the exponent.
}
+ #[rustc_nounwind]
pub fn u32_to_f64_bits(i: u32) -> u64 {
if i == 0 {
return 0;
@@ -27,6 +29,7 @@ mod int_to_float {
(e << 52) + m // Bit 53 of m will overflow into e.
}
+ #[rustc_nounwind]
pub fn u64_to_f32_bits(i: u64) -> u32 {
let n = i.leading_zeros();
let y = i.wrapping_shl(n);
@@ -37,6 +40,7 @@ mod int_to_float {
(e << 23) + m // + not |, so the mantissa can overflow into the exponent.
}
+ #[rustc_nounwind]
pub fn u64_to_f64_bits(i: u64) -> u64 {
if i == 0 {
return 0;
@@ -49,6 +53,7 @@ mod int_to_float {
(e << 52) + m // + not |, so the mantissa can overflow into the exponent.
}
+ #[rustc_nounwind]
pub fn u128_to_f32_bits(i: u128) -> u32 {
let n = i.leading_zeros();
let y = i.wrapping_shl(n);
@@ -59,6 +64,7 @@ mod int_to_float {
(e << 23) + m // + not |, so the mantissa can overflow into the exponent.
}
+ #[rustc_nounwind]
pub fn u128_to_f64_bits(i: u128) -> u64 {
let n = i.leading_zeros();
let y = i.wrapping_shl(n);
diff --git a/src/float/mod.rs b/src/float/mod.rs
index fdbe9dde3..b9f34389e 100644
--- a/src/float/mod.rs
+++ b/src/float/mod.rs
@@ -120,12 +120,15 @@ macro_rules! float_impl {
const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS;
const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK);
+ #[rustc_nounwind]
fn repr(self) -> Self::Int {
self.to_bits()
}
+ #[rustc_nounwind]
fn signed_repr(self) -> Self::SignedInt {
self.to_bits() as Self::SignedInt
}
+ #[rustc_nounwind]
fn eq_repr(self, rhs: Self) -> bool {
if self.is_nan() && rhs.is_nan() {
true
@@ -133,21 +136,27 @@ macro_rules! float_impl {
self.repr() == rhs.repr()
}
}
+ #[rustc_nounwind]
fn sign(self) -> bool {
self.signed_repr() < Self::SignedInt::ZERO
}
+ #[rustc_nounwind]
fn exp(self) -> Self::ExpInt {
((self.to_bits() & Self::EXPONENT_MASK) >> Self::SIGNIFICAND_BITS) as Self::ExpInt
}
+ #[rustc_nounwind]
fn frac(self) -> Self::Int {
self.to_bits() & Self::SIGNIFICAND_MASK
}
+ #[rustc_nounwind]
fn imp_frac(self) -> Self::Int {
self.frac() | Self::IMPLICIT_BIT
}
+ #[rustc_nounwind]
fn from_repr(a: Self::Int) -> Self {
Self::from_bits(a)
}
+ #[rustc_nounwind]
fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_repr(
((sign as Self::Int) << (Self::BITS - 1))
@@ -155,6 +164,7 @@ macro_rules! float_impl {
| (significand & Self::SIGNIFICAND_MASK),
)
}
+ #[rustc_nounwind]
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand
.leading_zeros()
@@ -164,6 +174,7 @@ macro_rules! float_impl {
significand << shift as Self::Int,
)
}
+ #[rustc_nounwind]
fn is_subnormal(self) -> bool {
(self.repr() & Self::EXPONENT_MASK) == Self::Int::ZERO
}
diff --git a/src/int/mod.rs b/src/int/mod.rs
index 509f9fdae..e355e52bb 100644
--- a/src/int/mod.rs
+++ b/src/int/mod.rs
@@ -151,50 +151,62 @@ macro_rules! int_impl_common {
}
};
+ #[rustc_nounwind]
fn from_bool(b: bool) -> Self {
b as $ty
}
+ #[rustc_nounwind]
fn logical_shr(self, other: u32) -> Self {
Self::from_unsigned(self.unsigned().wrapping_shr(other))
}
+ #[rustc_nounwind]
fn is_zero(self) -> bool {
self == Self::ZERO
}
+ #[rustc_nounwind]
fn wrapping_neg(self) -> Self {
::wrapping_neg(self)
}
+ #[rustc_nounwind]
fn wrapping_add(self, other: Self) -> Self {
::wrapping_add(self, other)
}
+ #[rustc_nounwind]
fn wrapping_mul(self, other: Self) -> Self {
::wrapping_mul(self, other)
}
+ #[rustc_nounwind]
fn wrapping_sub(self, other: Self) -> Self {
::wrapping_sub(self, other)
}
+ #[rustc_nounwind]
fn wrapping_shl(self, other: u32) -> Self {
::wrapping_shl(self, other)
}
+ #[rustc_nounwind]
fn wrapping_shr(self, other: u32) -> Self {
::wrapping_shr(self, other)
}
+ #[rustc_nounwind]
fn rotate_left(self, other: u32) -> Self {
::rotate_left(self, other)
}
+ #[rustc_nounwind]
fn overflowing_add(self, other: Self) -> (Self, bool) {
::overflowing_add(self, other)
}
+ #[rustc_nounwind]
fn leading_zeros(self) -> u32 {
::leading_zeros(self)
}
diff --git a/src/int/specialized_div_rem/asymmetric.rs b/src/int/specialized_div_rem/asymmetric.rs
index 56ce188a3..9398daad0 100644
--- a/src/int/specialized_div_rem/asymmetric.rs
+++ b/src/int/specialized_div_rem/asymmetric.rs
@@ -14,9 +14,13 @@ macro_rules! impl_asymmetric {
$uH:ident, // unsigned integer with half the bit width of $uX
$uX:ident, // unsigned integer with half the bit width of $uD
$uD:ident // unsigned integer type for the inputs and outputs of `$fn`
+ $(, $fun_attr:meta)* // attributes for the function
) => {
/// Computes the quotient and remainder of `duo` divided by `div` and returns them as a
/// tuple.
+ $(
+ #[$fun_attr]
+ )*
pub fn $fn(duo: $uD, div: $uD) -> ($uD, $uD) {
let n: u32 = $n_h * 2;
diff --git a/src/int/specialized_div_rem/delegate.rs b/src/int/specialized_div_rem/delegate.rs
index 330c6e4f8..5e82faa4b 100644
--- a/src/int/specialized_div_rem/delegate.rs
+++ b/src/int/specialized_div_rem/delegate.rs
@@ -14,9 +14,13 @@ macro_rules! impl_delegate {
$uX:ident, // unsigned integer with half the bit width of $uD.
$uD:ident, // unsigned integer type for the inputs and outputs of `$fn`
$iD:ident // signed integer type with the same bitwidth as `$uD`
+ $(, $fun_attr:meta)* // attributes for the function
) => {
/// Computes the quotient and remainder of `duo` divided by `div` and returns them as a
/// tuple.
+ $(
+ #[$fun_attr]
+ )*
pub fn $fn(duo: $uD, div: $uD) -> ($uD, $uD) {
// The two possibility algorithm, undersubtracting long division algorithm, or any kind
// of reciprocal based algorithm will not be fastest, because they involve large
diff --git a/src/int/specialized_div_rem/mod.rs b/src/int/specialized_div_rem/mod.rs
index 760f5f5b7..ad70de380 100644
--- a/src/int/specialized_div_rem/mod.rs
+++ b/src/int/specialized_div_rem/mod.rs
@@ -110,7 +110,8 @@ impl_normalization_shift!(
32,
u32,
i32,
- allow(dead_code)
+ allow(dead_code),
+ rustc_nounwind
);
impl_normalization_shift!(
u64_normalization_shift,
@@ -118,7 +119,8 @@ impl_normalization_shift!(
64,
u64,
i64,
- allow(dead_code)
+ allow(dead_code),
+ rustc_nounwind
);
/// Divides `duo` by `div` and returns a tuple of the quotient and the remainder.
@@ -149,7 +151,8 @@ impl_trifecta!(
32,
u32,
u64,
- u128
+ u128,
+ rustc_nounwind
);
// If the pointer width less than 64, then the target architecture almost certainly does not have
@@ -168,7 +171,8 @@ impl_delegate!(
u32,
u64,
u128,
- i128
+ i128,
+ rustc_nounwind
);
/// Divides `duo` by `div` and returns a tuple of the quotient and the remainder.
@@ -209,7 +213,8 @@ impl_asymmetric!(
32,
u32,
u64,
- u128
+ u128,
+ rustc_nounwind
);
/// Divides `duo` by `div` and returns a tuple of the quotient and the remainder.
@@ -241,7 +246,8 @@ impl_delegate!(
u16,
u32,
u64,
- i64
+ i64,
+ rustc_nounwind
);
// When not on x86 and the pointer width is 64, use `binary_long`.
@@ -255,7 +261,8 @@ impl_binary_long!(
u64_normalization_shift,
64,
u64,
- i64
+ i64,
+ rustc_nounwind
);
/// Divides `duo` by `div` and returns a tuple of the quotient and the remainder.
@@ -296,7 +303,8 @@ impl_asymmetric!(
16,
u16,
u32,
- u64
+ u64,
+ rustc_nounwind
);
// 32 bits is the smallest division used by `compiler-builtins`, so we end with binary long division
@@ -307,5 +315,6 @@ impl_binary_long!(
32,
u32,
i32,
- allow(dead_code)
+ allow(dead_code),
+ rustc_nounwind
);
diff --git a/src/int/specialized_div_rem/trifecta.rs b/src/int/specialized_div_rem/trifecta.rs
index 7e104053b..ecb0bcd74 100644
--- a/src/int/specialized_div_rem/trifecta.rs
+++ b/src/int/specialized_div_rem/trifecta.rs
@@ -12,9 +12,13 @@ macro_rules! impl_trifecta {
$uH:ident, // unsigned integer with half the bit width of $uX
$uX:ident, // unsigned integer with half the bit width of $uD
$uD:ident // unsigned integer type for the inputs and outputs of `$unsigned_name`
+ $(, $fun_attr:meta)* // attributes for the function
) => {
/// Computes the quotient and remainder of `duo` divided by `div` and returns them as a
/// tuple.
+ $(
+ #[$fun_attr]
+ )*
pub fn $fn(duo: $uD, div: $uD) -> ($uD, $uD) {
// This is called the trifecta algorithm because it uses three main algorithms: short
// division for small divisors, the two possibility algorithm for large divisors, and an
diff --git a/src/lib.rs b/src/lib.rs
index 47aef540e..2d2d20d4e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -12,6 +12,7 @@
#![feature(linkage)]
#![feature(naked_functions)]
#![feature(repr_simd)]
+#![feature(rustc_attrs)]
#![no_builtins]
#![no_std]
#![allow(unused_features)]
diff --git a/src/mem/x86_64.rs b/src/mem/x86_64.rs
index 40b67093f..4fa080c1e 100644
--- a/src/mem/x86_64.rs
+++ b/src/mem/x86_64.rs
@@ -304,6 +304,7 @@ pub unsafe fn c_string_length(mut s: *const core::ffi::c_char) -> usize {
}
/// Determine optimal parameters for a `rep` instruction.
+#[rustc_nounwind]
fn rep_param(dest: *mut u8, mut count: usize) -> (usize, usize, usize) {
// Unaligned writes are still slow on modern processors, so align the destination address.
let pre_byte_count = ((8 - (dest as usize & 0b111)) & 0b111).min(count);