Implement all the 128-bit operator lang items from rust PR 46093
This commit is contained in:
parent
02b3734a5b
commit
5e71218390
|
@ -0,0 +1,111 @@
|
||||||
|
use int::LargeInt;
|
||||||
|
use int::Int;
|
||||||
|
|
||||||
|
trait Add: LargeInt {
|
||||||
|
fn add(self, other: Self) -> Self {
|
||||||
|
let (low, carry) = self.low().overflowing_add(other.low());
|
||||||
|
let high = self.high().wrapping_add(other.high());
|
||||||
|
let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO };
|
||||||
|
Self::from_parts(low, high.wrapping_add(carry))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for u128 {}
|
||||||
|
|
||||||
|
trait Addo: Int {
|
||||||
|
fn addo(self, other: Self, overflow: &mut i32) -> Self {
|
||||||
|
*overflow = 0;
|
||||||
|
let result = self.wrapping_add(other);
|
||||||
|
if other >= Self::ZERO {
|
||||||
|
if result < self {
|
||||||
|
*overflow = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if result >= self {
|
||||||
|
*overflow = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Addo for i128 {}
|
||||||
|
impl Addo for u128 {}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_add")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_add(a: i128, b: i128) -> i128 {
|
||||||
|
rust_u128_add(a as _, b as _) as _
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_addo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = a.addo(b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_add")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_add(a: u128, b: u128) -> u128 {
|
||||||
|
a.add(b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_addo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = a.addo(b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add() {
|
||||||
|
assert_eq!(rust_u128_add(1, 2), 3);
|
||||||
|
assert_eq!(rust_u128_add(!0, 3), 2);
|
||||||
|
assert_eq!(rust_u128_add(1 << 63, 1 << 63), 1 << 64);
|
||||||
|
assert_eq!(rust_u128_add(
|
||||||
|
0x54009B79B43145A0_B781BF1FD491296E_u128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_u128),
|
||||||
|
0xB41A6A66596687B1_3B1C743CE9F12161_u128);
|
||||||
|
assert_eq!(rust_u128_add(
|
||||||
|
0x3AE89C3AACEE47CD_8721275248B38DDB_u128,
|
||||||
|
0xEFDD73C41D344744_B0842900C3352A63_u128),
|
||||||
|
0x2AC60FFECA228F12_37A550530BE8B83E_u128);
|
||||||
|
|
||||||
|
assert_eq!(rust_i128_add(1, 2), 3);
|
||||||
|
assert_eq!(rust_i128_add(-1, 3), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_addo() {
|
||||||
|
assert_eq!(rust_u128_addo(1, 2), (3, false));
|
||||||
|
assert_eq!(rust_u128_addo(!0, 3), (2, true));
|
||||||
|
assert_eq!(rust_u128_addo(1 << 63, 1 << 63), (1 << 64, false));
|
||||||
|
assert_eq!(rust_u128_addo(
|
||||||
|
0x54009B79B43145A0_B781BF1FD491296E_u128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_u128),
|
||||||
|
(0xB41A6A66596687B1_3B1C743CE9F12161_u128, false));
|
||||||
|
assert_eq!(rust_u128_addo(
|
||||||
|
0x3AE89C3AACEE47CD_8721275248B38DDB_u128,
|
||||||
|
0xEFDD73C41D344744_B0842900C3352A63_u128),
|
||||||
|
(0x2AC60FFECA228F12_37A550530BE8B83E_u128, true));
|
||||||
|
|
||||||
|
assert_eq!(rust_i128_addo(1, 2), (3, false));
|
||||||
|
assert_eq!(rust_i128_addo(-1, 3), (2, false));
|
||||||
|
assert_eq!(rust_i128_addo(1 << 63, 1 << 63), (1 << 64, false));
|
||||||
|
assert_eq!(rust_i128_addo(
|
||||||
|
0x54009B79B43145A0_B781BF1FD491296E_i128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_i128),
|
||||||
|
(-0x4BE59599A699784E_C4E38BC3160EDE9F_i128, true));
|
||||||
|
assert_eq!(rust_i128_addo(
|
||||||
|
0x3AE89C3AACEE47CD_8721275248B38DDB_i128,
|
||||||
|
-0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
|
||||||
|
(0x2AC60FFECA228F12_37A550530BE8B83E_i128, false));
|
||||||
|
assert_eq!(rust_i128_addo(
|
||||||
|
-0x54009B79B43145A0_B781BF1FD491296E_i128,
|
||||||
|
-0x6019CEECA5354210_839AB51D155FF7F3_i128),
|
||||||
|
(0x4BE59599A699784E_C4E38BC3160EDE9F_i128, true));
|
||||||
|
assert_eq!(rust_i128_addo(
|
||||||
|
-0x3AE89C3AACEE47CD_8721275248B38DDB_i128,
|
||||||
|
0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
|
||||||
|
(-0x2AC60FFECA228F12_37A550530BE8B83E_i128, false));
|
||||||
|
}
|
|
@ -12,9 +12,11 @@ macro_rules! os_ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod add;
|
||||||
pub mod mul;
|
pub mod mul;
|
||||||
pub mod sdiv;
|
pub mod sdiv;
|
||||||
pub mod shift;
|
pub mod shift;
|
||||||
|
pub mod sub;
|
||||||
pub mod udiv;
|
pub mod udiv;
|
||||||
|
|
||||||
/// Trait for some basic operations on integers
|
/// Trait for some basic operations on integers
|
||||||
|
@ -72,6 +74,7 @@ pub trait Int:
|
||||||
fn wrapping_mul(self, other: Self) -> Self;
|
fn wrapping_mul(self, other: Self) -> Self;
|
||||||
fn wrapping_sub(self, other: Self) -> Self;
|
fn wrapping_sub(self, other: Self) -> Self;
|
||||||
fn wrapping_shl(self, other: u32) -> Self;
|
fn wrapping_shl(self, other: u32) -> Self;
|
||||||
|
fn overflowing_add(self, other: Self) -> (Self, bool);
|
||||||
fn aborting_div(self, other: Self) -> Self;
|
fn aborting_div(self, other: Self) -> Self;
|
||||||
fn aborting_rem(self, other: Self) -> Self;
|
fn aborting_rem(self, other: Self) -> Self;
|
||||||
fn leading_zeros(self) -> u32;
|
fn leading_zeros(self) -> u32;
|
||||||
|
@ -119,6 +122,10 @@ macro_rules! int_impl_common {
|
||||||
<Self>::wrapping_shl(self, other)
|
<Self>::wrapping_shl(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn overflowing_add(self, other: Self) -> (Self, bool) {
|
||||||
|
<Self>::overflowing_add(self, other)
|
||||||
|
}
|
||||||
|
|
||||||
fn aborting_div(self, other: Self) -> Self {
|
fn aborting_div(self, other: Self) -> Self {
|
||||||
unwrap(<Self>::checked_div(self, other))
|
unwrap(<Self>::checked_div(self, other))
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,18 @@ impl Mulo for i32 {}
|
||||||
impl Mulo for i64 {}
|
impl Mulo for i64 {}
|
||||||
impl Mulo for i128 {}
|
impl Mulo for i128 {}
|
||||||
|
|
||||||
|
trait UMulo : Int {
|
||||||
|
fn mulo(self, other: Self, overflow: &mut i32) -> Self {
|
||||||
|
*overflow = 0;
|
||||||
|
let result = self.wrapping_mul(other);
|
||||||
|
if self > Self::max_value().aborting_div(other) {
|
||||||
|
*overflow = 1;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl UMulo for u128 {}
|
||||||
|
|
||||||
intrinsics! {
|
intrinsics! {
|
||||||
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
|
#[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
|
||||||
#[arm_aeabi_alias = __aeabi_lmul]
|
#[arm_aeabi_alias = __aeabi_lmul]
|
||||||
|
@ -95,3 +107,28 @@ intrinsics! {
|
||||||
a.mulo(b, oflow)
|
a.mulo(b, oflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_mul")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_mul(a: i128, b: i128) -> i128 {
|
||||||
|
__multi3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_mulo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_mulo(a: i128, b: i128) -> (i128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = __muloti4(a, b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_mul")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_mul(a: u128, b: u128) -> u128 {
|
||||||
|
__multi3(a as _, b as _) as _
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_mulo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = a.mulo(b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
|
|
@ -97,3 +97,14 @@ intrinsics! {
|
||||||
a.divmod(b, rem, |a, b| __divdi3(a, b))
|
a.divmod(b, rem, |a, b| __divdi3(a, b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_div")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_div(a: i128, b: i128) -> i128 {
|
||||||
|
__divti3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_rem")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_rem(a: i128, b: i128) -> i128 {
|
||||||
|
__modti3(a, b)
|
||||||
|
}
|
||||||
|
|
|
@ -95,3 +95,45 @@ intrinsics! {
|
||||||
a.lshr(b)
|
a.lshr(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_shl")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_shl(a: i128, b: u32) -> i128 {
|
||||||
|
__ashlti3(a as _, b) as _
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_shlo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_shlo(a: i128, b: u128) -> (i128, bool) {
|
||||||
|
(rust_i128_shl(a, b as _), b >= 128)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_shl")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_shl(a: u128, b: u32) -> u128 {
|
||||||
|
__ashlti3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_shlo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_shlo(a: u128, b: u128) -> (u128, bool) {
|
||||||
|
(rust_u128_shl(a, b as _), b >= 128)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_shr")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_shr(a: i128, b: u32) -> i128 {
|
||||||
|
__ashrti3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_shro")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_shro(a: i128, b: u128) -> (i128, bool) {
|
||||||
|
(rust_i128_shr(a, b as _), b >= 128)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_shr")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_shr(a: u128, b: u32) -> u128 {
|
||||||
|
__lshrti3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_shro")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_shro(a: u128, b: u128) -> (u128, bool) {
|
||||||
|
(rust_u128_shr(a, b as _), b >= 128)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
use int::LargeInt;
|
||||||
|
use int::Int;
|
||||||
|
|
||||||
|
trait Sub: LargeInt {
|
||||||
|
fn sub(self, other: Self) -> Self {
|
||||||
|
let neg_other = (!other).wrapping_add(Self::ONE);
|
||||||
|
self.wrapping_add(neg_other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for u128 {}
|
||||||
|
|
||||||
|
trait Subo: Int {
|
||||||
|
fn subo(self, other: Self, overflow: &mut i32) -> Self {
|
||||||
|
*overflow = 0;
|
||||||
|
let result = self.wrapping_sub(other);
|
||||||
|
if other >= Self::ZERO {
|
||||||
|
if result > self {
|
||||||
|
*overflow = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if result <= self {
|
||||||
|
*overflow = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Subo for i128 {}
|
||||||
|
impl Subo for u128 {}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_sub")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_sub(a: i128, b: i128) -> i128 {
|
||||||
|
rust_u128_sub(a as _, b as _) as _
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "i128_subo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = a.subo(b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_sub")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_sub(a: u128, b: u128) -> u128 {
|
||||||
|
a.sub(b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_subo")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
|
||||||
|
let mut oflow = 0;
|
||||||
|
let r = a.subo(b, &mut oflow);
|
||||||
|
(r, oflow != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sub() {
|
||||||
|
assert_eq!(rust_u128_sub(3, 2), 1);
|
||||||
|
assert_eq!(rust_u128_sub(2, 3), !0);
|
||||||
|
assert_eq!(rust_u128_sub(1 << 64, 1 << 63), 1 << 63);
|
||||||
|
assert_eq!(rust_u128_sub(
|
||||||
|
0xB41A6A66596687B1_3B1C743CE9F12161_u128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_u128),
|
||||||
|
0x54009B79B43145A0_B781BF1FD491296E_u128);
|
||||||
|
assert_eq!(rust_u128_sub(
|
||||||
|
0x2AC60FFECA228F12_37A550530BE8B83E_u128,
|
||||||
|
0xEFDD73C41D344744_B0842900C3352A63_u128),
|
||||||
|
0x3AE89C3AACEE47CD_8721275248B38DDB_u128);
|
||||||
|
|
||||||
|
assert_eq!(rust_i128_sub(3, 2), 1);
|
||||||
|
assert_eq!(rust_i128_sub(2, 3), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_subo() {
|
||||||
|
assert_eq!(rust_u128_subo(3, 2), (1, false));
|
||||||
|
assert_eq!(rust_u128_subo(2, 3), (!0, true));
|
||||||
|
assert_eq!(rust_u128_subo(1 << 64, 1 << 63), (1 << 63, false));
|
||||||
|
assert_eq!(rust_u128_subo(
|
||||||
|
0xB41A6A66596687B1_3B1C743CE9F12161_u128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_u128),
|
||||||
|
(0x54009B79B43145A0_B781BF1FD491296E_u128, false));
|
||||||
|
assert_eq!(rust_u128_subo(
|
||||||
|
0x2AC60FFECA228F12_37A550530BE8B83E_u128,
|
||||||
|
0xEFDD73C41D344744_B0842900C3352A63_u128),
|
||||||
|
(0x3AE89C3AACEE47CD_8721275248B38DDB_u128, true));
|
||||||
|
|
||||||
|
assert_eq!(rust_i128_subo(3, 2), (1, false));
|
||||||
|
assert_eq!(rust_i128_subo(2, 3), (-1, false));
|
||||||
|
assert_eq!(rust_i128_subo(1 << 64, 1 << 63), (1 << 63, false));
|
||||||
|
assert_eq!(rust_i128_subo(
|
||||||
|
-0x4BE59599A699784E_C4E38BC3160EDE9F_i128,
|
||||||
|
0x6019CEECA5354210_839AB51D155FF7F3_i128),
|
||||||
|
(0x54009B79B43145A0_B781BF1FD491296E_i128, true));
|
||||||
|
assert_eq!(rust_i128_subo(
|
||||||
|
0x2AC60FFECA228F12_37A550530BE8B83E_i128,
|
||||||
|
-0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
|
||||||
|
(0x3AE89C3AACEE47CD_8721275248B38DDB_i128, false));
|
||||||
|
assert_eq!(rust_i128_subo(
|
||||||
|
0x4BE59599A699784E_C4E38BC3160EDE9F_i128,
|
||||||
|
-0x6019CEECA5354210_839AB51D155FF7F3_i128),
|
||||||
|
(-0x54009B79B43145A0_B781BF1FD491296E_i128, true));
|
||||||
|
assert_eq!(rust_i128_subo(
|
||||||
|
-0x2AC60FFECA228F12_37A550530BE8B83E_i128,
|
||||||
|
0x10228C3BE2CBB8BB_4F7BD6FF3CCAD59D_i128),
|
||||||
|
(-0x3AE89C3AACEE47CD_8721275248B38DDB_i128, false));
|
||||||
|
}
|
|
@ -269,3 +269,14 @@ intrinsics! {
|
||||||
udivmod_inner!(n, d, rem, u128)
|
udivmod_inner!(n, d, rem, u128)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_div")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_div(a: u128, b: u128) -> u128 {
|
||||||
|
__udivti3(a, b)
|
||||||
|
}
|
||||||
|
#[cfg_attr(not(stage0), lang = "u128_rem")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn rust_u128_rem(a: u128, b: u128) -> u128 {
|
||||||
|
__umodti3(a, b)
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#![feature(repr_simd)]
|
#![feature(repr_simd)]
|
||||||
#![feature(abi_unadjusted)]
|
#![feature(abi_unadjusted)]
|
||||||
#![feature(linkage)]
|
#![feature(linkage)]
|
||||||
|
#![feature(lang_items)]
|
||||||
#![allow(unused_features)]
|
#![allow(unused_features)]
|
||||||
#![no_builtins]
|
#![no_builtins]
|
||||||
#![unstable(feature = "compiler_builtins_lib",
|
#![unstable(feature = "compiler_builtins_lib",
|
||||||
|
|
Loading…
Reference in New Issue