Skip to content

Commit a52b550

Browse files
committed
Use a C-safe return type for __rust_[ui]128_* overflowing intrinsics
Most of our Rust-specific overflowing intrinsics currently return `(i128, bool)`, which is not guaranteed to have a stable ABI. Switch to returning the overflow via a mutable parameter and only directly returning the integer result. `__rust_i128_mulo` now matches the function signature of `__muloti4`, but they do not share the same ABI on Windows so we cannot easily deduplicate them.
1 parent ba84ef8 commit a52b550

File tree

4 files changed

+39
-24
lines changed

4 files changed

+39
-24
lines changed

src/int/addsub.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,39 @@ intrinsics! {
6666
AddSub::add(a,b)
6767
}
6868

69-
pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
70-
a.addo(b)
69+
pub extern "C" fn __rust_i128_addo(a: i128, b: i128, oflow: &mut i32) -> i128 {
70+
let (add, o) = a.addo(b);
71+
*oflow = o.into();
72+
add
7173
}
7274

7375
pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
7476
AddSub::add(a,b)
7577
}
7678

77-
pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
78-
a.addo(b)
79+
pub extern "C" fn __rust_u128_addo(a: u128, b: u128, oflow: &mut i32) -> u128 {
80+
let (add, o) = a.addo(b);
81+
*oflow = o.into();
82+
add
7983
}
8084

8185
pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
8286
AddSub::sub(a,b)
8387
}
8488

85-
pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
86-
a.subo(b)
89+
pub extern "C" fn __rust_i128_subo(a: i128, b: i128, oflow: &mut i32) -> i128 {
90+
let (sub, o) = a.subo(b);
91+
*oflow = o.into();
92+
sub
8793
}
8894

8995
pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
9096
AddSub::sub(a,b)
9197
}
9298

93-
pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
94-
a.subo(b)
99+
pub extern "C" fn __rust_u128_subo(a: u128, b: u128, oflow: &mut i32) -> u128 {
100+
let (sub, o) = a.subo(b);
101+
*oflow = o.into();
102+
sub
95103
}
96104
}

src/int/mul.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,15 @@ intrinsics! {
128128
mul
129129
}
130130

131-
pub extern "C" fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
132-
i128_overflowing_mul(a, b)
131+
pub extern "C" fn __rust_i128_mulo(a: i128, b: i128, oflow: &mut i32) -> i128 {
132+
let (mul, o) = i128_overflowing_mul(a, b);
133+
*oflow = o.into();
134+
mul
133135
}
134136

135-
pub extern "C" fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
136-
a.mulo(b)
137+
pub extern "C" fn __rust_u128_mulo(a: u128, b: u128, oflow: &mut i32) -> u128 {
138+
let (mul, o) = a.mulo(b);
139+
*oflow = o.into();
140+
mul
137141
}
138142
}

testcrate/tests/addsub.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,22 @@ mod int_addsub {
4444
use compiler_builtins::int::addsub::{$fn_add, $fn_sub};
4545

4646
fuzz_2(N, |x: $i, y: $i| {
47-
let add0 = x.overflowing_add(y);
48-
let sub0 = x.overflowing_sub(y);
49-
let add1: ($i, bool) = $fn_add(x, y);
50-
let sub1: ($i, bool) = $fn_sub(x, y);
51-
if add0.0 != add1.0 || add0.1 != add1.1 {
47+
let (add0, add_o0)= x.overflowing_add(y);
48+
let (sub0, sub_o0)= x.overflowing_sub(y);
49+
let mut add_o1 = 0;
50+
let mut sub_o1 = 0;
51+
let add1: $i = $fn_add(x, y, &mut add_o1);
52+
let sub1: $i = $fn_sub(x, y, &mut sub_o1);
53+
if add0 != add1 || i32::from(add_o0) != add_o1 {
5254
panic!(
5355
"{}({}, {}): std: {:?}, builtins: {:?}",
54-
stringify!($fn_add), x, y, add0, add1
56+
stringify!($fn_add), x, y, (add0, add_o0) , (add1, add_o1)
5557
);
5658
}
57-
if sub0.0 != sub1.0 || sub0.1 != sub1.1 {
59+
if sub0 != sub1 || i32::from(sub_o0) != sub_o1 {
5860
panic!(
5961
"{}({}, {}): std: {:?}, builtins: {:?}",
60-
stringify!($fn_sub), x, y, sub0, sub1
62+
stringify!($fn_sub), x, y, (sub0, sub_o0) , (sub1, sub_o1)
6163
);
6264
}
6365
});

testcrate/tests/mul.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ mod int_overflowing_mul {
7373
use compiler_builtins::int::mul::{__rust_i128_mulo, __rust_u128_mulo};
7474

7575
fuzz_2(N, |x: u128, y: u128| {
76+
let mut o1 = 0;
7677
let (mul0, o0) = x.overflowing_mul(y);
77-
let (mul1, o1) = __rust_u128_mulo(x, y);
78-
if mul0 != mul1 || o0 != o1 {
78+
let mul1 = __rust_u128_mulo(x, y, &mut o1);
79+
if mul0 != mul1 || i32::from(o0) != o1 {
7980
panic!(
8081
"__rust_u128_mulo({}, {}): std: ({}, {}), builtins: ({}, {})",
8182
x, y, mul0, o0, mul1, o1
@@ -84,8 +85,8 @@ mod int_overflowing_mul {
8485
let x = x as i128;
8586
let y = y as i128;
8687
let (mul0, o0) = x.overflowing_mul(y);
87-
let (mul1, o1) = __rust_i128_mulo(x, y);
88-
if mul0 != mul1 || o0 != o1 {
88+
let mul1 = __rust_i128_mulo(x, y, &mut o1);
89+
if mul0 != mul1 || i32::from(o0) != o1 {
8990
panic!(
9091
"__rust_i128_mulo({}, {}): std: ({}, {}), builtins: ({}, {})",
9192
x, y, mul0, o0, mul1, o1

0 commit comments

Comments
 (0)