Skip to content

Commit c56faf2

Browse files
author
Jorge Aparicio
authored
Merge pull request rust-lang#80 from japaric/abort
panic! -> abort
2 parents 24c2a15 + 96ddd4e commit c56faf2

File tree

7 files changed

+149
-57
lines changed

7 files changed

+149
-57
lines changed

ci/run.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ case $1 in
2828
;;
2929
esac
3030

31+
# Verify that there are no undefined symbols to `panic` within our implementations
32+
# TODO(#79) fix the undefined references problem for debug-assertions+lto
33+
case $1 in
34+
thumb*)
35+
RUSTFLAGS="-C debug-assertions=no -C link-arg=-nostartfiles" xargo rustc --features c --target $1 --bin intrinsics -- -C lto
36+
xargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
37+
;;
38+
*)
39+
RUSTFLAGS="-C debug-assertions=no" cargo rustc --features c --target $1 --bin intrinsics -- -C lto
40+
cargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
41+
;;
42+
esac
43+
3144
# Look out for duplicated symbols when we include the compiler-rt (C) implementation
3245
PREFIX=$(echo $1 | sed -e 's/unknown-//')-
3346
case $1 in

src/bin/intrinsics.rs

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
// to link due to the missing intrinsic (symbol).
55

66
#![allow(unused_features)]
7+
#![cfg_attr(thumb, no_main)]
78
#![deny(dead_code)]
9+
#![feature(asm)]
810
#![feature(core_float)]
911
#![feature(lang_items)]
1012
#![feature(libc)]
1113
#![feature(start)]
1214
#![no_std]
13-
#![cfg_attr(thumb, no_main)]
1415

1516
#[cfg(not(thumb))]
1617
extern crate libc;
@@ -304,50 +305,56 @@ mod intrinsics {
304305
fn run() {
305306
use intrinsics::*;
306307

307-
aeabi_d2f(2.);
308-
aeabi_d2i(2.);
309-
aeabi_d2l(2.);
310-
aeabi_d2uiz(2.);
311-
aeabi_d2ulz(2.);
312-
aeabi_dadd(2., 3.);
313-
aeabi_dcmpeq(2., 3.);
314-
aeabi_dcmpgt(2., 3.);
315-
aeabi_dcmplt(2., 3.);
316-
aeabi_ddiv(2., 3.);
317-
aeabi_dmul(2., 3.);
318-
aeabi_dsub(2., 3.);
319-
aeabi_f2d(2.);
320-
aeabi_f2iz(2.);
321-
aeabi_f2lz(2.);
322-
aeabi_f2uiz(2.);
323-
aeabi_f2ulz(2.);
324-
aeabi_fadd(2., 3.);
325-
aeabi_fcmpeq(2., 3.);
326-
aeabi_fcmpgt(2., 3.);
327-
aeabi_fcmplt(2., 3.);
328-
aeabi_fdiv(2., 3.);
329-
aeabi_fmul(2., 3.);
330-
aeabi_fsub(2., 3.);
331-
aeabi_i2d(2);
332-
aeabi_i2f(2);
333-
aeabi_idiv(2, 3);
334-
aeabi_idivmod(2, 3);
335-
aeabi_l2d(2);
336-
aeabi_l2f(2);
337-
aeabi_ldivmod(2, 3);
338-
aeabi_lmul(2, 3);
339-
aeabi_ui2d(2);
340-
aeabi_ui2f(2);
341-
aeabi_uidiv(2, 3);
342-
aeabi_uidivmod(2, 3);
343-
aeabi_ul2d(2);
344-
aeabi_ul2f(2);
345-
aeabi_uldivmod(2, 3);
346-
moddi3(2, 3);
347-
mulodi4(2, 3);
348-
powidf2(2., 3);
349-
powisf2(2., 3);
350-
umoddi3(2, 3);
308+
// A copy of "test::black_box". Used to prevent LLVM from optimizing away the intrinsics during LTO
309+
fn bb<T>(dummy: T) -> T {
310+
unsafe { asm!("" : : "r"(&dummy)) }
311+
dummy
312+
}
313+
314+
bb(aeabi_d2f(bb(2.)));
315+
bb(aeabi_d2i(bb(2.)));
316+
bb(aeabi_d2l(bb(2.)));
317+
bb(aeabi_d2uiz(bb(2.)));
318+
bb(aeabi_d2ulz(bb(2.)));
319+
bb(aeabi_dadd(bb(2.), bb(3.)));
320+
bb(aeabi_dcmpeq(bb(2.), bb(3.)));
321+
bb(aeabi_dcmpgt(bb(2.), bb(3.)));
322+
bb(aeabi_dcmplt(bb(2.), bb(3.)));
323+
bb(aeabi_ddiv(bb(2.), bb(3.)));
324+
bb(aeabi_dmul(bb(2.), bb(3.)));
325+
bb(aeabi_dsub(bb(2.), bb(3.)));
326+
bb(aeabi_f2d(bb(2.)));
327+
bb(aeabi_f2iz(bb(2.)));
328+
bb(aeabi_f2lz(bb(2.)));
329+
bb(aeabi_f2uiz(bb(2.)));
330+
bb(aeabi_f2ulz(bb(2.)));
331+
bb(aeabi_fadd(bb(2.), bb(3.)));
332+
bb(aeabi_fcmpeq(bb(2.), bb(3.)));
333+
bb(aeabi_fcmpgt(bb(2.), bb(3.)));
334+
bb(aeabi_fcmplt(bb(2.), bb(3.)));
335+
bb(aeabi_fdiv(bb(2.), bb(3.)));
336+
bb(aeabi_fmul(bb(2.), bb(3.)));
337+
bb(aeabi_fsub(bb(2.), bb(3.)));
338+
bb(aeabi_i2d(bb(2)));
339+
bb(aeabi_i2f(bb(2)));
340+
bb(aeabi_idiv(bb(2), bb(3)));
341+
bb(aeabi_idivmod(bb(2), bb(3)));
342+
bb(aeabi_l2d(bb(2)));
343+
bb(aeabi_l2f(bb(2)));
344+
bb(aeabi_ldivmod(bb(2), bb(3)));
345+
bb(aeabi_lmul(bb(2), bb(3)));
346+
bb(aeabi_ui2d(bb(2)));
347+
bb(aeabi_ui2f(bb(2)));
348+
bb(aeabi_uidiv(bb(2), bb(3)));
349+
bb(aeabi_uidivmod(bb(2), bb(3)));
350+
bb(aeabi_ul2d(bb(2)));
351+
bb(aeabi_ul2f(bb(2)));
352+
bb(aeabi_uldivmod(bb(2), bb(3)));
353+
bb(moddi3(bb(2), bb(3)));
354+
bb(mulodi4(bb(2), bb(3)));
355+
bb(powidf2(bb(2.), bb(3)));
356+
bb(powisf2(bb(2.), bb(3)));
357+
bb(umoddi3(bb(2), bb(3)));
351358
}
352359

353360
#[cfg(all(feature = "c", not(thumb)))]

src/float/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::mem;
2+
#[cfg(test)]
23
use core::fmt;
34

45
pub mod add;

src/float/pow.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
21
macro_rules! pow {
3-
($intrinsic:ident: $fty:ty, $ity:ty) => {
2+
($intrinsic:ident: $fty:ty, $ity:ident) => {
43
/// Returns `a` raised to the power `b`
54
#[cfg_attr(not(test), no_mangle)]
65
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
@@ -11,7 +10,7 @@ macro_rules! pow {
1110
if (b & 1) != 0 {
1211
r *= a;
1312
}
14-
b /= 2;
13+
b = sdiv!($ity, b, 2);
1514
if b == 0 {
1615
break;
1716
}

src/int/sdiv.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ macro_rules! div {
1010
let a = (a ^ s_a) - s_a;
1111
let b = (b ^ s_b) - s_b;
1212
let s = s_a ^ s_b;
13-
let r = (a as $uty) / (b as $uty);
13+
14+
let r = udiv!(a as $uty, b as $uty);
1415
(r as $ty ^ s) - s
1516
}
1617
}
@@ -25,7 +26,8 @@ macro_rules! mod_ {
2526
let b = (b ^ s) - s;
2627
let s = a >> (<$ty>::bits() - 1);
2728
let a = (a ^ s) - s;
28-
let r = (a as $uty) % (b as $uty);
29+
30+
let r = urem!(a as $uty, b as $uty);
2931
(r as $ty ^ s) - s
3032
}
3133
}

src/int/udiv.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::mem;
1+
use core::{intrinsics, mem};
22
use int::{Int, LargeInt};
33

44
/// Returns `n / d`
@@ -7,7 +7,11 @@ use int::{Int, LargeInt};
77
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
88
// Special cases
99
if d == 0 {
10-
panic!("Division by zero");
10+
// NOTE This should be unreachable in safe Rust because the program will panic before
11+
// this intrinsic is called
12+
unsafe {
13+
intrinsics::abort()
14+
}
1115
}
1216

1317
if n == 0 {
@@ -105,10 +109,11 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
105109
// 0 X
106110
// ---
107111
// 0 X
112+
108113
if let Some(rem) = rem {
109-
*rem = u64::from(n.low() % d.low());
114+
*rem = u64::from(urem!(n.low(), d.low()));
110115
}
111-
return u64::from(n.low() / d.low());
116+
return u64::from(udiv!(n.low(), d.low()));
112117
} else {
113118
// 0 X
114119
// ---
@@ -129,17 +134,21 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
129134
// K X
130135
// ---
131136
// 0 0
132-
panic!("Division by zero");
137+
// NOTE This should be unreachable in safe Rust because the program will panic before
138+
// this intrinsic is called
139+
unsafe {
140+
intrinsics::abort()
141+
}
133142
}
134143

135144
if n.low() == 0 {
136145
// K 0
137146
// ---
138147
// K 0
139148
if let Some(rem) = rem {
140-
*rem = u64::from_parts(0, n.high() % d.high());
149+
*rem = u64::from_parts(0, urem!(n.high(), d.high()));
141150
}
142-
return u64::from(n.high() / d.high());
151+
return u64::from(udiv!(n.high(), d.high()));
143152
}
144153

145154
// K K

src/lib.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,67 @@
1313
// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
1414
// implementation of that intrinsic and we'll prefer to use that
1515

16+
// TODO(rust-lang/rust#37029) use e.g. checked_div(_).unwrap_or_else(|| abort())
17+
macro_rules! udiv {
18+
($a:expr, $b:expr) => {
19+
unsafe {
20+
let a = $a;
21+
let b = $b;
22+
23+
if b == 0 {
24+
::core::intrinsics::abort()
25+
} else {
26+
::core::intrinsics::unchecked_div(a, b)
27+
}
28+
}
29+
}
30+
}
31+
32+
macro_rules! sdiv {
33+
($sty:ident, $a:expr, $b:expr) => {
34+
unsafe {
35+
let a = $a;
36+
let b = $b;
37+
38+
if b == 0 || (b == -1 && a == $sty::min_value()) {
39+
::core::intrinsics::abort()
40+
} else {
41+
::core::intrinsics::unchecked_div(a, b)
42+
}
43+
}
44+
}
45+
}
46+
47+
macro_rules! urem {
48+
($a:expr, $b:expr) => {
49+
unsafe {
50+
let a = $a;
51+
let b = $b;
52+
53+
if b == 0 {
54+
::core::intrinsics::abort()
55+
} else {
56+
::core::intrinsics::unchecked_rem(a, b)
57+
}
58+
}
59+
}
60+
}
61+
62+
macro_rules! srem {
63+
($sty:ty, $a:expr, $b:expr) => {
64+
unsafe {
65+
let a = $a;
66+
let b = $b;
67+
68+
if b == 0 || (b == -1 && a == $sty::min_value()) {
69+
::core::intrinsics::abort()
70+
} else {
71+
::core::intrinsics::unchecked_rem(a, b)
72+
}
73+
}
74+
}
75+
}
76+
1677
#[cfg(test)]
1778
#[macro_use]
1879
extern crate quickcheck;

0 commit comments

Comments
 (0)