Skip to content

Commit 5766097

Browse files
committed
Auto merge of #80 - japaric:abort, r=<try>
panic! -> abort closes #79
2 parents 1c90948 + 34cd40f commit 5766097

File tree

7 files changed

+162
-55
lines changed

7 files changed

+162
-55
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ compiler-rt = { path = "compiler-rt" }
2525
c = []
2626
weak = ["rlibc/weak"]
2727

28+
[profile.dev]
29+
debug-assertions = false
30+
2831
[workspace]

ci/run.sh

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

31+
# Verify that there are no undefined symbols to `panic` within our implementations
32+
case $1 in
33+
thumb*)
34+
xargo rustc --features c --target $1 --bin intrinsics -- -C lto
35+
xargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
36+
;;
37+
*)
38+
cargo rustc --features c --target $1 --bin intrinsics -- -C lto
39+
cargo rustc --features c --target $1 --bin intrinsics --release -- -C lto
40+
;;
41+
esac
42+
3143
# Look out for duplicated symbols when we include the compiler-rt (C) implementation
3244
PREFIX=$(echo $1 | sed -e 's/unknown-//')-
3345
case $1 in

src/bin/intrinsics.rs

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -302,52 +302,70 @@ mod intrinsics {
302302

303303
#[cfg(feature = "c")]
304304
fn run() {
305+
use core::ptr;
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+
// We use volatile load/stores to prevent LLVM from optimizing away the intrinsics during LTO
309+
macro_rules! arg {
310+
() => {
311+
unsafe {
312+
ptr::read_volatile(0x0 as *const _)
313+
}
314+
}
315+
}
316+
317+
macro_rules! ret {
318+
($e:expr) => {
319+
unsafe {
320+
ptr::write_volatile(0x0 as *mut _, $e)
321+
}
322+
}
323+
}
324+
325+
ret!(aeabi_d2f(arg!()));
326+
ret!(aeabi_d2i(arg!()));
327+
ret!(aeabi_d2l(arg!()));
328+
ret!(aeabi_d2uiz(arg!()));
329+
ret!(aeabi_d2ulz(arg!()));
330+
ret!(aeabi_dadd(arg!(), arg!()));
331+
ret!(aeabi_dcmpeq(arg!(), arg!()));
332+
ret!(aeabi_dcmpgt(arg!(), arg!()));
333+
ret!(aeabi_dcmplt(arg!(), arg!()));
334+
ret!(aeabi_ddiv(arg!(), arg!()));
335+
ret!(aeabi_dmul(arg!(), arg!()));
336+
ret!(aeabi_dsub(arg!(), arg!()));
337+
ret!(aeabi_f2d(arg!()));
338+
ret!(aeabi_f2iz(arg!()));
339+
ret!(aeabi_f2lz(arg!()));
340+
ret!(aeabi_f2uiz(arg!()));
341+
ret!(aeabi_f2ulz(arg!()));
342+
ret!(aeabi_fadd(arg!(), arg!()));
343+
ret!(aeabi_fcmpeq(arg!(), arg!()));
344+
ret!(aeabi_fcmpgt(arg!(), arg!()));
345+
ret!(aeabi_fcmplt(arg!(), arg!()));
346+
ret!(aeabi_fdiv(arg!(), arg!()));
347+
ret!(aeabi_fmul(arg!(), arg!()));
348+
ret!(aeabi_fsub(arg!(), arg!()));
349+
ret!(aeabi_i2d(arg!()));
350+
ret!(aeabi_i2f(arg!()));
351+
ret!(aeabi_idiv(arg!(), arg!()));
352+
ret!(aeabi_idivmod(arg!(), arg!()));
353+
ret!(aeabi_l2d(arg!()));
354+
ret!(aeabi_l2f(arg!()));
355+
ret!(aeabi_ldivmod(arg!(), arg!()));
356+
ret!(aeabi_lmul(arg!(), arg!()));
357+
ret!(aeabi_ui2d(arg!()));
358+
ret!(aeabi_ui2f(arg!()));
359+
ret!(aeabi_uidiv(arg!(), arg!()));
360+
ret!(aeabi_uidivmod(arg!(), arg!()));
361+
ret!(aeabi_ul2d(arg!()));
362+
ret!(aeabi_ul2f(arg!()));
363+
ret!(aeabi_uldivmod(arg!(), arg!()));
364+
ret!(moddi3(arg!(), arg!()));
365+
ret!(mulodi4(arg!(), arg!()));
366+
ret!(powidf2(arg!(), arg!()));
367+
ret!(powisf2(arg!(), arg!()));
368+
ret!(umoddi3(arg!(), arg!()));
351369
}
352370

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

src/float/pow.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use core::intrinsics;
12

23
macro_rules! pow {
3-
($intrinsic:ident: $fty:ty, $ity:ty) => {
4+
($intrinsic:ident: $fty:ty, $ity:ident) => {
45
/// Returns `a` raised to the power `b`
56
#[cfg_attr(not(test), no_mangle)]
67
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
@@ -11,7 +12,7 @@ macro_rules! pow {
1112
if (b & 1) != 0 {
1213
r *= a;
1314
}
14-
b /= 2;
15+
b = sdiv!($ity, b, 2);
1516
if b == 0 {
1617
break;
1718
}

src/int/sdiv.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::intrinsics;
2+
13
use int::Int;
24

35
macro_rules! div {
@@ -10,7 +12,8 @@ macro_rules! div {
1012
let a = (a ^ s_a) - s_a;
1113
let b = (b ^ s_b) - s_b;
1214
let s = s_a ^ s_b;
13-
let r = (a as $uty) / (b as $uty);
15+
16+
let r = udiv!((a as $uty), (b as $uty));
1417
(r as $ty ^ s) - s
1518
}
1619
}
@@ -25,7 +28,8 @@ macro_rules! mod_ {
2528
let b = (b ^ s) - s;
2629
let s = a >> (<$ty>::bits() - 1);
2730
let a = (a ^ s) - s;
28-
let r = (a as $uty) % (b as $uty);
31+
32+
let r = urem!((a as $uty), (b as $uty));
2933
(r as $ty ^ s) - s
3034
}
3135
}

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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,66 @@
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+
macro_rules! udiv {
17+
($a:expr, $b:expr) => {
18+
unsafe {
19+
let a = $a;
20+
let b = $b;
21+
22+
if b == 0 {
23+
intrinsics::abort()
24+
} else {
25+
intrinsics::unchecked_div(a, b)
26+
}
27+
}
28+
}
29+
}
30+
31+
macro_rules! sdiv {
32+
($sty:ident, $a:expr, $b:expr) => {
33+
unsafe {
34+
let a = $a;
35+
let b = $b;
36+
37+
if b == 0 || (b == -1 && a == $sty::min_value()) {
38+
intrinsics::abort()
39+
} else {
40+
intrinsics::unchecked_div(a, b)
41+
}
42+
}
43+
}
44+
}
45+
46+
macro_rules! urem {
47+
($a:expr, $b:expr) => {
48+
unsafe {
49+
let a = $a;
50+
let b = $b;
51+
52+
if b == 0 {
53+
intrinsics::abort()
54+
} else {
55+
intrinsics::unchecked_rem(a, b)
56+
}
57+
}
58+
}
59+
}
60+
61+
macro_rules! srem {
62+
($sty:ty, $a:expr, $b:expr) => {
63+
unsafe {
64+
let a = $a;
65+
let b = $b;
66+
67+
if b == 0 || (b == -1 && a == $sty::min_value()) {
68+
intrinsics::abort()
69+
} else {
70+
intrinsics::unchecked_rem(a, b)
71+
}
72+
}
73+
}
74+
}
75+
1676
#[cfg(test)]
1777
#[macro_use]
1878
extern crate quickcheck;

0 commit comments

Comments
 (0)