Skip to content

Commit 5e71218

Browse files
committed
Implement all the 128-bit operator lang items from rust PR 46093
1 parent 02b3734 commit 5e71218

File tree

8 files changed

+329
-0
lines changed

8 files changed

+329
-0
lines changed

src/int/add.rs

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use int::LargeInt;
2+
use int::Int;
3+
4+
trait Add: LargeInt {
5+
fn add(self, other: Self) -> Self {
6+
let (low, carry) = self.low().overflowing_add(other.low());
7+
let high = self.high().wrapping_add(other.high());
8+
let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO };
9+
Self::from_parts(low, high.wrapping_add(carry))
10+
}
11+
}
12+
13+
impl Add for u128 {}
14+
15+
trait Addo: Int {
16+
fn addo(self, other: Self, overflow: &mut i32) -> Self {
17+
*overflow = 0;
18+
let result = self.wrapping_add(other);
19+
if other >= Self::ZERO {
20+
if result < self {
21+
*overflow = 1;
22+
}
23+
} else {
24+
if result >= self {
25+
*overflow = 1;
26+
}
27+
}
28+
result
29+
}
30+
}
31+
32+
impl Addo for i128 {}
33+
impl Addo for u128 {}
34+
35+
#[cfg_attr(not(stage0), lang = "i128_add")]
36+
#[allow(dead_code)]
37+
fn rust_i128_add(a: i128, b: i128) -> i128 {
38+
rust_u128_add(a as _, b as _) as _
39+
}
40+
#[cfg_attr(not(stage0), lang = "i128_addo")]
41+
#[allow(dead_code)]
42+
fn rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
43+
let mut oflow = 0;
44+
let r = a.addo(b, &mut oflow);
45+
(r, oflow != 0)
46+
}
47+
#[cfg_attr(not(stage0), lang = "u128_add")]
48+
#[allow(dead_code)]
49+
fn rust_u128_add(a: u128, b: u128) -> u128 {
50+
a.add(b)
51+
}
52+
#[cfg_attr(not(stage0), lang = "u128_addo")]
53+
#[allow(dead_code)]
54+
fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
55+
let mut oflow = 0;
56+
let r = a.addo(b, &mut oflow);
57+
(r, oflow != 0)
58+
}
59+
60+
#[test]
61+
fn test_add() {
62+
assert_eq!(rust_u128_add(1, 2), 3);
63+
assert_eq!(rust_u128_add(!0, 3), 2);
64+
assert_eq!(rust_u128_add(1 << 63, 1 << 63), 1 << 64);
65+
assert_eq!(rust_u128_add(
66+
0x54009B79B43145A0_B781BF1FD491296E_u128,
67+
0x6019CEECA5354210_839AB51D155FF7F3_u128),
68+
0xB41A6A66596687B1_3B1C743CE9F12161_u128);
69+
assert_eq!(rust_u128_add(
70+
0x3AE89C3AACEE47CD_8721275248B38DDB_u128,
71+
0xEFDD73C41D344744_B0842900C3352A63_u128),
72+
0x2AC60FFECA228F12_37A550530BE8B83E_u128);
73+
74+
assert_eq!(rust_i128_add(1, 2), 3);
75+
assert_eq!(rust_i128_add(-1, 3), 2);
76+
}
77+
78+
#[test]
79+
fn test_addo() {
80+
assert_eq!(rust_u128_addo(1, 2), (3, false));
81+
assert_eq!(rust_u128_addo(!0, 3), (2, true));
82+
assert_eq!(rust_u128_addo(1 << 63, 1 << 63), (1 << 64, false));
83+
assert_eq!(rust_u128_addo(
84+
0x54009B79B43145A0_B781BF1FD491296E_u128,
85+
0x6019CEECA5354210_839AB51D155FF7F3_u128),
86+
(0xB41A6A66596687B1_3B1C743CE9F12161_u128, false));
87+
assert_eq!(rust_u128_addo(
88+
0x3AE89C3AACEE47CD_8721275248B38DDB_u128,
89+
0xEFDD73C41D344744_B0842900C3352A63_u128),
90+
(0x2AC60FFECA228F12_37A550530BE8B83E_u128, true));
91+
92+
assert_eq!(rust_i128_addo(1, 2), (3, false));
93+
assert_eq!(rust_i128_addo(-1, 3), (2, false));
94+
assert_eq!(rust_i128_addo(1 << 63, 1 << 63), (1 << 64, false));
95+
assert_eq!(rust_i128_addo(
96+
0x54009B79B43145A0_B781BF1FD491296E_i128,
97+
0x6019CEECA5354210_839AB51D155FF7F3_i128),
98+
(-0x4BE59599A699784E_C4E38BC3160EDE9F_i128, true));
99+
assert_eq!(rust_i128_addo(
100+
0x3AE89C3AACEE47CD_8721275248B38DDB_i128,
101+
-0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
102+
(0x2AC60FFECA228F12_37A550530BE8B83E_i128, false));
103+
assert_eq!(rust_i128_addo(
104+
-0x54009B79B43145A0_B781BF1FD491296E_i128,
105+
-0x6019CEECA5354210_839AB51D155FF7F3_i128),
106+
(0x4BE59599A699784E_C4E38BC3160EDE9F_i128, true));
107+
assert_eq!(rust_i128_addo(
108+
-0x3AE89C3AACEE47CD_8721275248B38DDB_i128,
109+
0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
110+
(-0x2AC60FFECA228F12_37A550530BE8B83E_i128, false));
111+
}

src/int/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ macro_rules! os_ty {
1212
}
1313
}
1414

15+
pub mod add;
1516
pub mod mul;
1617
pub mod sdiv;
1718
pub mod shift;
19+
pub mod sub;
1820
pub mod udiv;
1921

2022
/// Trait for some basic operations on integers
@@ -72,6 +74,7 @@ pub trait Int:
7274
fn wrapping_mul(self, other: Self) -> Self;
7375
fn wrapping_sub(self, other: Self) -> Self;
7476
fn wrapping_shl(self, other: u32) -> Self;
77+
fn overflowing_add(self, other: Self) -> (Self, bool);
7578
fn aborting_div(self, other: Self) -> Self;
7679
fn aborting_rem(self, other: Self) -> Self;
7780
fn leading_zeros(self) -> u32;
@@ -119,6 +122,10 @@ macro_rules! int_impl_common {
119122
<Self>::wrapping_shl(self, other)
120123
}
121124

125+
fn overflowing_add(self, other: Self) -> (Self, bool) {
126+
<Self>::overflowing_add(self, other)
127+
}
128+
122129
fn aborting_div(self, other: Self) -> Self {
123130
unwrap(<Self>::checked_div(self, other))
124131
}

src/int/mul.rs

+37
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ impl Mulo for i32 {}
7070
impl Mulo for i64 {}
7171
impl Mulo for i128 {}
7272

73+
trait UMulo : Int {
74+
fn mulo(self, other: Self, overflow: &mut i32) -> Self {
75+
*overflow = 0;
76+
let result = self.wrapping_mul(other);
77+
if self > Self::max_value().aborting_div(other) {
78+
*overflow = 1;
79+
}
80+
result
81+
}
82+
}
83+
impl UMulo for u128 {}
84+
7385
intrinsics! {
7486
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
7587
#[arm_aeabi_alias = __aeabi_lmul]
@@ -95,3 +107,28 @@ intrinsics! {
95107
a.mulo(b, oflow)
96108
}
97109
}
110+
111+
#[cfg_attr(not(stage0), lang = "i128_mul")]
112+
#[allow(dead_code)]
113+
fn rust_i128_mul(a: i128, b: i128) -> i128 {
114+
__multi3(a, b)
115+
}
116+
#[cfg_attr(not(stage0), lang = "i128_mulo")]
117+
#[allow(dead_code)]
118+
fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
119+
let mut oflow = 0;
120+
let r = __muloti4(a, b, &mut oflow);
121+
(r, oflow != 0)
122+
}
123+
#[cfg_attr(not(stage0), lang = "u128_mul")]
124+
#[allow(dead_code)]
125+
fn rust_u128_mul(a: u128, b: u128) -> u128 {
126+
__multi3(a as _, b as _) as _
127+
}
128+
#[cfg_attr(not(stage0), lang = "u128_mulo")]
129+
#[allow(dead_code)]
130+
fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
131+
let mut oflow = 0;
132+
let r = a.mulo(b, &mut oflow);
133+
(r, oflow != 0)
134+
}

src/int/sdiv.rs

+11
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,14 @@ intrinsics! {
9797
a.divmod(b, rem, |a, b| __divdi3(a, b))
9898
}
9999
}
100+
101+
#[cfg_attr(not(stage0), lang = "i128_div")]
102+
#[allow(dead_code)]
103+
fn rust_i128_div(a: i128, b: i128) -> i128 {
104+
__divti3(a, b)
105+
}
106+
#[cfg_attr(not(stage0), lang = "i128_rem")]
107+
#[allow(dead_code)]
108+
fn rust_i128_rem(a: i128, b: i128) -> i128 {
109+
__modti3(a, b)
110+
}

src/int/shift.rs

+42
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,45 @@ intrinsics! {
9595
a.lshr(b)
9696
}
9797
}
98+
99+
#[cfg_attr(not(stage0), lang = "i128_shl")]
100+
#[allow(dead_code)]
101+
fn rust_i128_shl(a: i128, b: u32) -> i128 {
102+
__ashlti3(a as _, b) as _
103+
}
104+
#[cfg_attr(not(stage0), lang = "i128_shlo")]
105+
#[allow(dead_code)]
106+
fn rust_i128_shlo(a: i128, b: u128) -> (i128, bool) {
107+
(rust_i128_shl(a, b as _), b >= 128)
108+
}
109+
#[cfg_attr(not(stage0), lang = "u128_shl")]
110+
#[allow(dead_code)]
111+
fn rust_u128_shl(a: u128, b: u32) -> u128 {
112+
__ashlti3(a, b)
113+
}
114+
#[cfg_attr(not(stage0), lang = "u128_shlo")]
115+
#[allow(dead_code)]
116+
fn rust_u128_shlo(a: u128, b: u128) -> (u128, bool) {
117+
(rust_u128_shl(a, b as _), b >= 128)
118+
}
119+
120+
#[cfg_attr(not(stage0), lang = "i128_shr")]
121+
#[allow(dead_code)]
122+
fn rust_i128_shr(a: i128, b: u32) -> i128 {
123+
__ashrti3(a, b)
124+
}
125+
#[cfg_attr(not(stage0), lang = "i128_shro")]
126+
#[allow(dead_code)]
127+
fn rust_i128_shro(a: i128, b: u128) -> (i128, bool) {
128+
(rust_i128_shr(a, b as _), b >= 128)
129+
}
130+
#[cfg_attr(not(stage0), lang = "u128_shr")]
131+
#[allow(dead_code)]
132+
fn rust_u128_shr(a: u128, b: u32) -> u128 {
133+
__lshrti3(a, b)
134+
}
135+
#[cfg_attr(not(stage0), lang = "u128_shro")]
136+
#[allow(dead_code)]
137+
fn rust_u128_shro(a: u128, b: u128) -> (u128, bool) {
138+
(rust_u128_shr(a, b as _), b >= 128)
139+
}

src/int/sub.rs

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
use int::LargeInt;
2+
use int::Int;
3+
4+
trait Sub: LargeInt {
5+
fn sub(self, other: Self) -> Self {
6+
let neg_other = (!other).wrapping_add(Self::ONE);
7+
self.wrapping_add(neg_other)
8+
}
9+
}
10+
11+
impl Sub for u128 {}
12+
13+
trait Subo: Int {
14+
fn subo(self, other: Self, overflow: &mut i32) -> Self {
15+
*overflow = 0;
16+
let result = self.wrapping_sub(other);
17+
if other >= Self::ZERO {
18+
if result > self {
19+
*overflow = 1;
20+
}
21+
} else {
22+
if result <= self {
23+
*overflow = 1;
24+
}
25+
}
26+
result
27+
}
28+
}
29+
30+
impl Subo for i128 {}
31+
impl Subo for u128 {}
32+
33+
#[cfg_attr(not(stage0), lang = "i128_sub")]
34+
#[allow(dead_code)]
35+
fn rust_i128_sub(a: i128, b: i128) -> i128 {
36+
rust_u128_sub(a as _, b as _) as _
37+
}
38+
#[cfg_attr(not(stage0), lang = "i128_subo")]
39+
#[allow(dead_code)]
40+
fn rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
41+
let mut oflow = 0;
42+
let r = a.subo(b, &mut oflow);
43+
(r, oflow != 0)
44+
}
45+
#[cfg_attr(not(stage0), lang = "u128_sub")]
46+
#[allow(dead_code)]
47+
fn rust_u128_sub(a: u128, b: u128) -> u128 {
48+
a.sub(b)
49+
}
50+
#[cfg_attr(not(stage0), lang = "u128_subo")]
51+
#[allow(dead_code)]
52+
fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
53+
let mut oflow = 0;
54+
let r = a.subo(b, &mut oflow);
55+
(r, oflow != 0)
56+
}
57+
58+
#[test]
59+
fn test_sub() {
60+
assert_eq!(rust_u128_sub(3, 2), 1);
61+
assert_eq!(rust_u128_sub(2, 3), !0);
62+
assert_eq!(rust_u128_sub(1 << 64, 1 << 63), 1 << 63);
63+
assert_eq!(rust_u128_sub(
64+
0xB41A6A66596687B1_3B1C743CE9F12161_u128,
65+
0x6019CEECA5354210_839AB51D155FF7F3_u128),
66+
0x54009B79B43145A0_B781BF1FD491296E_u128);
67+
assert_eq!(rust_u128_sub(
68+
0x2AC60FFECA228F12_37A550530BE8B83E_u128,
69+
0xEFDD73C41D344744_B0842900C3352A63_u128),
70+
0x3AE89C3AACEE47CD_8721275248B38DDB_u128);
71+
72+
assert_eq!(rust_i128_sub(3, 2), 1);
73+
assert_eq!(rust_i128_sub(2, 3), -1);
74+
}
75+
76+
#[test]
77+
fn test_subo() {
78+
assert_eq!(rust_u128_subo(3, 2), (1, false));
79+
assert_eq!(rust_u128_subo(2, 3), (!0, true));
80+
assert_eq!(rust_u128_subo(1 << 64, 1 << 63), (1 << 63, false));
81+
assert_eq!(rust_u128_subo(
82+
0xB41A6A66596687B1_3B1C743CE9F12161_u128,
83+
0x6019CEECA5354210_839AB51D155FF7F3_u128),
84+
(0x54009B79B43145A0_B781BF1FD491296E_u128, false));
85+
assert_eq!(rust_u128_subo(
86+
0x2AC60FFECA228F12_37A550530BE8B83E_u128,
87+
0xEFDD73C41D344744_B0842900C3352A63_u128),
88+
(0x3AE89C3AACEE47CD_8721275248B38DDB_u128, true));
89+
90+
assert_eq!(rust_i128_subo(3, 2), (1, false));
91+
assert_eq!(rust_i128_subo(2, 3), (-1, false));
92+
assert_eq!(rust_i128_subo(1 << 64, 1 << 63), (1 << 63, false));
93+
assert_eq!(rust_i128_subo(
94+
-0x4BE59599A699784E_C4E38BC3160EDE9F_i128,
95+
0x6019CEECA5354210_839AB51D155FF7F3_i128),
96+
(0x54009B79B43145A0_B781BF1FD491296E_i128, true));
97+
assert_eq!(rust_i128_subo(
98+
0x2AC60FFECA228F12_37A550530BE8B83E_i128,
99+
-0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
100+
(0x3AE89C3AACEE47CD_8721275248B38DDB_i128, false));
101+
assert_eq!(rust_i128_subo(
102+
0x4BE59599A699784E_C4E38BC3160EDE9F_i128,
103+
-0x6019CEECA5354210_839AB51D155FF7F3_i128),
104+
(-0x54009B79B43145A0_B781BF1FD491296E_i128, true));
105+
assert_eq!(rust_i128_subo(
106+
-0x2AC60FFECA228F12_37A550530BE8B83E_i128,
107+
0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
108+
(-0x3AE89C3AACEE47CD_8721275248B38DDB_i128, false));
109+
}

src/int/udiv.rs

+11
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,14 @@ intrinsics! {
269269
udivmod_inner!(n, d, rem, u128)
270270
}
271271
}
272+
273+
#[cfg_attr(not(stage0), lang = "u128_div")]
274+
#[allow(dead_code)]
275+
fn rust_u128_div(a: u128, b: u128) -> u128 {
276+
__udivti3(a, b)
277+
}
278+
#[cfg_attr(not(stage0), lang = "u128_rem")]
279+
#[allow(dead_code)]
280+
fn rust_u128_rem(a: u128, b: u128) -> u128 {
281+
__umodti3(a, b)
282+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#![feature(repr_simd)]
1818
#![feature(abi_unadjusted)]
1919
#![feature(linkage)]
20+
#![feature(lang_items)]
2021
#![allow(unused_features)]
2122
#![no_builtins]
2223
#![unstable(feature = "compiler_builtins_lib",

0 commit comments

Comments
 (0)