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

Add a bunch of rustc_nounwind for c_unwind #578

Closed
wants to merge 5 commits into from
Closed
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/defined_symbols.txt
/undefined_symbols.txt
/code.tar.gz
/compiler-rt
*.rs.bk
Cargo.lock
target
24 changes: 15 additions & 9 deletions ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not have --release: this test specifically checks that debug builds (-Copt-level=0) do not reference any symbols in core. This is needed for people using -Z build-std without --release.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I understand that we might expect that only compiler-builtins is optimized.

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
Expand Down
6 changes: 6 additions & 0 deletions src/float/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
///
/// The algorithm is explained here: <https://blog.m-ou.se/floats/>
mod int_to_float {
#[rustc_nounwind]
pub fn u32_to_f32_bits(i: u32) -> u32 {
if i == 0 {
return 0;
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions src/float/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,41 +120,51 @@ 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
} else {
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))
| ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK)
| (significand & Self::SIGNIFICAND_MASK),
)
}
#[rustc_nounwind]
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand
.leading_zeros()
Expand All @@ -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
}
Expand Down
12 changes: 12 additions & 0 deletions src/int/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
<Self>::wrapping_neg(self)
}

#[rustc_nounwind]
fn wrapping_add(self, other: Self) -> Self {
<Self>::wrapping_add(self, other)
}

#[rustc_nounwind]
fn wrapping_mul(self, other: Self) -> Self {
<Self>::wrapping_mul(self, other)
}

#[rustc_nounwind]
fn wrapping_sub(self, other: Self) -> Self {
<Self>::wrapping_sub(self, other)
}

#[rustc_nounwind]
fn wrapping_shl(self, other: u32) -> Self {
<Self>::wrapping_shl(self, other)
}

#[rustc_nounwind]
fn wrapping_shr(self, other: u32) -> Self {
<Self>::wrapping_shr(self, other)
}

#[rustc_nounwind]
fn rotate_left(self, other: u32) -> Self {
<Self>::rotate_left(self, other)
}

#[rustc_nounwind]
fn overflowing_add(self, other: Self) -> (Self, bool) {
<Self>::overflowing_add(self, other)
}

#[rustc_nounwind]
fn leading_zeros(self) -> u32 {
<Self>::leading_zeros(self)
}
Expand Down
4 changes: 4 additions & 0 deletions src/int/specialized_div_rem/asymmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions src/int/specialized_div_rem/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 18 additions & 9 deletions src/int/specialized_div_rem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,17 @@ impl_normalization_shift!(
32,
u32,
i32,
allow(dead_code)
allow(dead_code),
rustc_nounwind
);
impl_normalization_shift!(
u64_normalization_shift,
USE_LZ,
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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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`.
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -307,5 +315,6 @@ impl_binary_long!(
32,
u32,
i32,
allow(dead_code)
allow(dead_code),
rustc_nounwind
);
4 changes: 4 additions & 0 deletions src/int/specialized_div_rem/trifecta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![feature(linkage)]
#![feature(naked_functions)]
#![feature(repr_simd)]
#![feature(rustc_attrs)]
#![no_builtins]
#![no_std]
#![allow(unused_features)]
Expand Down
1 change: 1 addition & 0 deletions src/mem/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down