Quellcode durchsuchen

Implement all the 128-bit operator lang items from rust PR 46093

Scott McMurray vor 7 Jahren
Ursprung
Commit
5e71218390
8 geänderte Dateien mit 329 neuen und 0 gelöschten Zeilen
  1. 111 0
      src/int/add.rs
  2. 7 0
      src/int/mod.rs
  3. 37 0
      src/int/mul.rs
  4. 11 0
      src/int/sdiv.rs
  5. 42 0
      src/int/shift.rs
  6. 109 0
      src/int/sub.rs
  7. 11 0
      src/int/udiv.rs
  8. 1 0
      src/lib.rs

+ 111 - 0
src/int/add.rs

@@ -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));
+}

+ 7 - 0
src/int/mod.rs

@@ -12,9 +12,11 @@ macro_rules! os_ty {
     }
 }
 
+pub mod add;
 pub mod mul;
 pub mod sdiv;
 pub mod shift;
+pub mod sub;
 pub mod udiv;
 
 /// Trait for some basic operations on integers
@@ -72,6 +74,7 @@ pub trait Int:
     fn wrapping_mul(self, other: Self) -> Self;
     fn wrapping_sub(self, other: Self) -> 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_rem(self, other: Self) -> Self;
     fn leading_zeros(self) -> u32;
@@ -119,6 +122,10 @@ macro_rules! int_impl_common {
                 <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 {
                 unwrap(<Self>::checked_div(self, other))
             }

+ 37 - 0
src/int/mul.rs

@@ -70,6 +70,18 @@ impl Mulo for i32 {}
 impl Mulo for i64 {}
 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! {
     #[use_c_shim_if(all(target_arch = "x86", not(target_env = "msvc")))]
     #[arm_aeabi_alias = __aeabi_lmul]
@@ -95,3 +107,28 @@ intrinsics! {
         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)
+}

+ 11 - 0
src/int/sdiv.rs

@@ -97,3 +97,14 @@ intrinsics! {
         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)
+}

+ 42 - 0
src/int/shift.rs

@@ -95,3 +95,45 @@ intrinsics! {
         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)
+}

+ 109 - 0
src/int/sub.rs

@@ -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));
+}

+ 11 - 0
src/int/udiv.rs

@@ -269,3 +269,14 @@ intrinsics! {
         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)
+}

+ 1 - 0
src/lib.rs

@@ -17,6 +17,7 @@
 #![feature(repr_simd)]
 #![feature(abi_unadjusted)]
 #![feature(linkage)]
+#![feature(lang_items)]
 #![allow(unused_features)]
 #![no_builtins]
 #![unstable(feature = "compiler_builtins_lib",