summaryrefslogtreecommitdiffstats
path: root/vendor/compiler_builtins/src/int/addsub.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/compiler_builtins/src/int/addsub.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/vendor/compiler_builtins/src/int/addsub.rs b/vendor/compiler_builtins/src/int/addsub.rs
new file mode 100644
index 000000000..f4841e90f
--- /dev/null
+++ b/vendor/compiler_builtins/src/int/addsub.rs
@@ -0,0 +1,96 @@
+use int::{DInt, Int};
+
+trait UAddSub: DInt {
+ fn uadd(self, other: Self) -> Self {
+ let (lo, carry) = self.lo().overflowing_add(other.lo());
+ let hi = self.hi().wrapping_add(other.hi());
+ let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
+ Self::from_lo_hi(lo, hi.wrapping_add(carry))
+ }
+ fn uadd_one(self) -> Self {
+ let (lo, carry) = self.lo().overflowing_add(Self::H::ONE);
+ let carry = if carry { Self::H::ONE } else { Self::H::ZERO };
+ Self::from_lo_hi(lo, self.hi().wrapping_add(carry))
+ }
+ fn usub(self, other: Self) -> Self {
+ let uneg = (!other).uadd_one();
+ self.uadd(uneg)
+ }
+}
+
+impl UAddSub for u128 {}
+
+trait AddSub: Int
+where
+ <Self as Int>::UnsignedInt: UAddSub,
+{
+ fn add(self, other: Self) -> Self {
+ Self::from_unsigned(self.unsigned().uadd(other.unsigned()))
+ }
+ fn sub(self, other: Self) -> Self {
+ Self::from_unsigned(self.unsigned().usub(other.unsigned()))
+ }
+}
+
+impl AddSub for u128 {}
+impl AddSub for i128 {}
+
+trait Addo: AddSub
+where
+ <Self as Int>::UnsignedInt: UAddSub,
+{
+ fn addo(self, other: Self) -> (Self, bool) {
+ let sum = AddSub::add(self, other);
+ (sum, (other < Self::ZERO) != (sum < self))
+ }
+}
+
+impl Addo for i128 {}
+impl Addo for u128 {}
+
+trait Subo: AddSub
+where
+ <Self as Int>::UnsignedInt: UAddSub,
+{
+ fn subo(self, other: Self) -> (Self, bool) {
+ let sum = AddSub::sub(self, other);
+ (sum, (other < Self::ZERO) != (self < sum))
+ }
+}
+
+impl Subo for i128 {}
+impl Subo for u128 {}
+
+intrinsics! {
+ pub extern "C" fn __rust_i128_add(a: i128, b: i128) -> i128 {
+ AddSub::add(a,b)
+ }
+
+ pub extern "C" fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool) {
+ a.addo(b)
+ }
+
+ pub extern "C" fn __rust_u128_add(a: u128, b: u128) -> u128 {
+ AddSub::add(a,b)
+ }
+
+ pub extern "C" fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool) {
+ a.addo(b)
+ }
+
+ pub extern "C" fn __rust_i128_sub(a: i128, b: i128) -> i128 {
+ AddSub::sub(a,b)
+ }
+
+ pub extern "C" fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool) {
+ a.subo(b)
+ }
+
+ pub extern "C" fn __rust_u128_sub(a: u128, b: u128) -> u128 {
+ AddSub::sub(a,b)
+ }
+
+ pub extern "C" fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool) {
+ a.subo(b)
+ }
+}