Skip to content

Commit 60d949b

Browse files
authored
Merge pull request #210 from scottmcm/add-128bit-lang-items
Implement all the 128-bit operator lang items (Rust 45676 part 2)
2 parents 02b3734 + ba75010 commit 60d949b

16 files changed

+760
-0
lines changed

build.rs

+482
Large diffs are not rendered by default.

src/int/addsub.rs

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use int::LargeInt;
2+
use int::Int;
3+
4+
trait UAddSub: LargeInt {
5+
fn uadd(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+
fn uadd_one(self) -> Self {
12+
let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE);
13+
let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO };
14+
Self::from_parts(low, self.high().wrapping_add(carry))
15+
}
16+
fn usub(self, other: Self) -> Self {
17+
let uneg = (!other).uadd_one();
18+
self.uadd(uneg)
19+
}
20+
}
21+
22+
impl UAddSub for u128 {}
23+
24+
trait AddSub: Int
25+
where <Self as Int>::UnsignedInt: UAddSub
26+
{
27+
fn add(self, other: Self) -> Self {
28+
Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
29+
}
30+
fn sub(self, other: Self) -> Self {
31+
Self::from_unsigned(self.unsigned().usub(other.unsigned()))
32+
}
33+
}
34+
35+
impl AddSub for u128 {}
36+
impl AddSub for i128 {}
37+
38+
trait Addo: AddSub
39+
where <Self as Int>::UnsignedInt: UAddSub
40+
{
41+
fn addo(self, other: Self, overflow: &mut i32) -> Self {
42+
*overflow = 0;
43+
let result = AddSub::add(self, other);
44+
if other >= Self::ZERO {
45+
if result < self {
46+
*overflow = 1;
47+
}
48+
} else {
49+
if result >= self {
50+
*overflow = 1;
51+
}
52+
}
53+
result
54+
}
55+
}
56+
57+
impl Addo for i128 {}
58+
impl Addo for u128 {}
59+
60+
trait Subo: AddSub
61+
where <Self as Int>::UnsignedInt: UAddSub
62+
{
63+
fn subo(self, other: Self, overflow: &mut i32) -> Self {
64+
*overflow = 0;
65+
let result = AddSub::sub(self, other);
66+
if other >= Self::ZERO {
67+
if result > self {
68+
*overflow = 1;
69+
}
70+
} else {
71+
if result <= self {
72+
*overflow = 1;
73+
}
74+
}
75+
result
76+
}
77+
}
78+
79+
impl Subo for i128 {}
80+
impl Subo for u128 {}
81+
82+
#[cfg_attr(not(stage0), lang = "i128_add")]
83+
pub fn rust_i128_add(a: i128, b: i128) -> i128 {
84+
rust_u128_add(a as _, b as _) as _
85+
}
86+
#[cfg_attr(not(stage0), lang = "i128_addo")]
87+
pub fn rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
88+
let mut oflow = 0;
89+
let r = a.addo(b, &mut oflow);
90+
(r, oflow != 0)
91+
}
92+
#[cfg_attr(not(stage0), lang = "u128_add")]
93+
pub fn rust_u128_add(a: u128, b: u128) -> u128 {
94+
a.add(b)
95+
}
96+
#[cfg_attr(not(stage0), lang = "u128_addo")]
97+
pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
98+
let mut oflow = 0;
99+
let r = a.addo(b, &mut oflow);
100+
(r, oflow != 0)
101+
}
102+
103+
#[cfg_attr(not(stage0), lang = "i128_sub")]
104+
pub fn rust_i128_sub(a: i128, b: i128) -> i128 {
105+
rust_u128_sub(a as _, b as _) as _
106+
}
107+
#[cfg_attr(not(stage0), lang = "i128_subo")]
108+
pub fn rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
109+
let mut oflow = 0;
110+
let r = a.subo(b, &mut oflow);
111+
(r, oflow != 0)
112+
}
113+
#[cfg_attr(not(stage0), lang = "u128_sub")]
114+
pub fn rust_u128_sub(a: u128, b: u128) -> u128 {
115+
a.sub(b)
116+
}
117+
#[cfg_attr(not(stage0), lang = "u128_subo")]
118+
pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
119+
let mut oflow = 0;
120+
let r = a.subo(b, &mut oflow);
121+
(r, oflow != 0)
122+
}

src/int/mod.rs

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

15+
pub mod addsub;
1516
pub mod mul;
1617
pub mod sdiv;
1718
pub mod shift;
@@ -72,6 +73,7 @@ pub trait Int:
7273
fn wrapping_mul(self, other: Self) -> Self;
7374
fn wrapping_sub(self, other: Self) -> Self;
7475
fn wrapping_shl(self, other: u32) -> Self;
76+
fn overflowing_add(self, other: Self) -> (Self, bool);
7577
fn aborting_div(self, other: Self) -> Self;
7678
fn aborting_rem(self, other: Self) -> Self;
7779
fn leading_zeros(self) -> u32;
@@ -119,6 +121,10 @@ macro_rules! int_impl_common {
119121
<Self>::wrapping_shl(self, other)
120122
}
121123

124+
fn overflowing_add(self, other: Self) -> (Self, bool) {
125+
<Self>::overflowing_add(self, other)
126+
}
127+
122128
fn aborting_div(self, other: Self) -> Self {
123129
unwrap(<Self>::checked_div(self, other))
124130
}

src/int/mul.rs

+33
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,24 @@ intrinsics! {
95107
a.mulo(b, oflow)
96108
}
97109
}
110+
111+
#[cfg_attr(not(stage0), lang = "i128_mul")]
112+
pub fn rust_i128_mul(a: i128, b: i128) -> i128 {
113+
__multi3(a, b)
114+
}
115+
#[cfg_attr(not(stage0), lang = "i128_mulo")]
116+
pub fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
117+
let mut oflow = 0;
118+
let r = __muloti4(a, b, &mut oflow);
119+
(r, oflow != 0)
120+
}
121+
#[cfg_attr(not(stage0), lang = "u128_mul")]
122+
pub fn rust_u128_mul(a: u128, b: u128) -> u128 {
123+
__multi3(a as _, b as _) as _
124+
}
125+
#[cfg_attr(not(stage0), lang = "u128_mulo")]
126+
pub fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
127+
let mut oflow = 0;
128+
let r = a.mulo(b, &mut oflow);
129+
(r, oflow != 0)
130+
}

src/int/sdiv.rs

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

src/int/shift.rs

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

src/int/udiv.rs

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

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",

tests/i128_add.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/i128_add.rs"));

tests/i128_addo.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/i128_addo.rs"));

tests/i128_sub.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/i128_sub.rs"));

tests/i128_subo.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/i128_subo.rs"));

tests/u128_add.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/u128_add.rs"));

tests/u128_addo.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/u128_addo.rs"));

tests/u128_sub.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/u128_sub.rs"));

tests/u128_subo.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(compiler_builtins_lib)]
2+
#![feature(i128_type)]
3+
#![cfg_attr(all(target_arch = "arm",
4+
not(any(target_env = "gnu", target_env = "musl")),
5+
target_os = "linux",
6+
test), no_std)]
7+
8+
include!(concat!(env!("OUT_DIR"), "/u128_subo.rs"));

0 commit comments

Comments
 (0)