From 5e71218390281a94e86b0bd26c7f1905c89f8c6b Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Nov 2017 04:21:05 -0800 Subject: [PATCH 1/5] Implement all the 128-bit operator lang items from rust PR 46093 --- src/int/add.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++ src/int/mod.rs | 7 +++ src/int/mul.rs | 37 ++++++++++++++++ src/int/sdiv.rs | 11 +++++ src/int/shift.rs | 42 ++++++++++++++++++ src/int/sub.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++ src/int/udiv.rs | 11 +++++ src/lib.rs | 1 + 8 files changed, 329 insertions(+) create mode 100644 src/int/add.rs create mode 100644 src/int/sub.rs diff --git a/src/int/add.rs b/src/int/add.rs new file mode 100644 index 0000000..639d14a --- /dev/null +++ b/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)); +} \ No newline at end of file diff --git a/src/int/mod.rs b/src/int/mod.rs index 37dac8c..c5490cb 100644 --- a/src/int/mod.rs +++ b/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 { ::wrapping_shl(self, other) } + fn overflowing_add(self, other: Self) -> (Self, bool) { + ::overflowing_add(self, other) + } + fn aborting_div(self, other: Self) -> Self { unwrap(::checked_div(self, other)) } diff --git a/src/int/mul.rs b/src/int/mul.rs index a4b2ebd..9d45fa5 100644 --- a/src/int/mul.rs +++ b/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) +} diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index ff8fa61..6fef631 100644 --- a/src/int/sdiv.rs +++ b/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) +} diff --git a/src/int/shift.rs b/src/int/shift.rs index 805d705..de6d06b 100644 --- a/src/int/shift.rs +++ b/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) +} diff --git a/src/int/sub.rs b/src/int/sub.rs new file mode 100644 index 0000000..4d3dfeb --- /dev/null +++ b/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)); +} \ No newline at end of file diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 74a2ac3..0442a8c 100644 --- a/src/int/udiv.rs +++ b/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) +} diff --git a/src/lib.rs b/src/lib.rs index 8bf3230..ff7885b 100644 --- a/src/lib.rs +++ b/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", From 665f268872cdaf5a8cd85aab695ad121c49df887 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Nov 2017 05:26:24 -0800 Subject: [PATCH 2/5] Tweak addo & subo to try and fix MIPS --- src/int/add.rs | 23 ++++++++++++++++++----- src/int/sub.rs | 6 +++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/int/add.rs b/src/int/add.rs index 639d14a..4253b64 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -1,8 +1,8 @@ use int::LargeInt; use int::Int; -trait Add: LargeInt { - fn add(self, other: Self) -> Self { +trait UAdd: LargeInt { + fn uadd(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 }; @@ -10,12 +10,25 @@ trait Add: LargeInt { } } -impl Add for u128 {} +impl UAdd for u128 {} -trait Addo: Int { +trait Add: Int + where ::UnsignedInt: UAdd +{ + fn add(self, other: Self) -> Self { + Self::from_unsigned(self.unsigned().uadd(other.unsigned())) + } +} + +impl Add for u128 {} +impl Add for i128 {} + +trait Addo: Add + where ::UnsignedInt: UAdd +{ fn addo(self, other: Self, overflow: &mut i32) -> Self { *overflow = 0; - let result = self.wrapping_add(other); + let result = Add::add(self, other); if other >= Self::ZERO { if result < self { *overflow = 1; diff --git a/src/int/sub.rs b/src/int/sub.rs index 4d3dfeb..ba29c10 100644 --- a/src/int/sub.rs +++ b/src/int/sub.rs @@ -1,5 +1,4 @@ use int::LargeInt; -use int::Int; trait Sub: LargeInt { fn sub(self, other: Self) -> Self { @@ -8,12 +7,13 @@ trait Sub: LargeInt { } } +impl Sub for i128 {} impl Sub for u128 {} -trait Subo: Int { +trait Subo: Sub { fn subo(self, other: Self, overflow: &mut i32) -> Self { *overflow = 0; - let result = self.wrapping_sub(other); + let result = Sub::sub(self, other); if other >= Self::ZERO { if result > self { *overflow = 1; From ed89a17f25413b5f7a4efa972cf400278a18e5c9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Nov 2017 05:53:53 -0800 Subject: [PATCH 3/5] Make them all `pub` --- src/int/add.rs | 12 ++++-------- src/int/mul.rs | 12 ++++-------- src/int/sdiv.rs | 6 ++---- src/int/shift.rs | 24 ++++++++---------------- src/int/sub.rs | 12 ++++-------- src/int/udiv.rs | 6 ++---- 6 files changed, 24 insertions(+), 48 deletions(-) diff --git a/src/int/add.rs b/src/int/add.rs index 4253b64..b0f7ab6 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -46,25 +46,21 @@ 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 { +pub 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) { +pub 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 { +pub 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) { +pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) { let mut oflow = 0; let r = a.addo(b, &mut oflow); (r, oflow != 0) diff --git a/src/int/mul.rs b/src/int/mul.rs index 9d45fa5..61c379c 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -109,25 +109,21 @@ intrinsics! { } #[cfg_attr(not(stage0), lang = "i128_mul")] -#[allow(dead_code)] -fn rust_i128_mul(a: i128, b: i128) -> i128 { +pub 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) { +pub 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 { +pub 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) { +pub fn rust_u128_mulo(a: u128, b: u128) -> (u128, bool) { let mut oflow = 0; let r = a.mulo(b, &mut oflow); (r, oflow != 0) diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 6fef631..0308664 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -99,12 +99,10 @@ intrinsics! { } #[cfg_attr(not(stage0), lang = "i128_div")] -#[allow(dead_code)] -fn rust_i128_div(a: i128, b: i128) -> i128 { +pub 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 { +pub fn rust_i128_rem(a: i128, b: i128) -> i128 { __modti3(a, b) } diff --git a/src/int/shift.rs b/src/int/shift.rs index de6d06b..f8faad8 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -97,43 +97,35 @@ intrinsics! { } #[cfg_attr(not(stage0), lang = "i128_shl")] -#[allow(dead_code)] -fn rust_i128_shl(a: i128, b: u32) -> i128 { +pub 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) { +pub 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 { +pub 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) { +pub 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 { +pub 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) { +pub 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 { +pub 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) { +pub fn rust_u128_shro(a: u128, b: u128) -> (u128, bool) { (rust_u128_shr(a, b as _), b >= 128) } diff --git a/src/int/sub.rs b/src/int/sub.rs index ba29c10..0b0cbf2 100644 --- a/src/int/sub.rs +++ b/src/int/sub.rs @@ -31,25 +31,21 @@ 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 { +pub 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) { +pub 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 { +pub 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) { +pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) { let mut oflow = 0; let r = a.subo(b, &mut oflow); (r, oflow != 0) diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 0442a8c..6c100f3 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -271,12 +271,10 @@ intrinsics! { } #[cfg_attr(not(stage0), lang = "u128_div")] -#[allow(dead_code)] -fn rust_u128_div(a: u128, b: u128) -> u128 { +pub 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 { +pub fn rust_u128_rem(a: u128, b: u128) -> u128 { __umodti3(a, b) } From bcc41a9b8d05c4c93ecce857fa168ad38d99a1ad Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Nov 2017 06:24:07 -0800 Subject: [PATCH 4/5] Autogenerate the add/sub tests --- build.rs | 484 +++++++++++++++++++++++++++++++++++++++++++++ src/int/add.rs | 53 ----- src/int/sub.rs | 53 ----- tests/i128_add.rs | 8 + tests/i128_addo.rs | 8 + tests/i128_sub.rs | 8 + tests/i128_subo.rs | 8 + tests/u128_add.rs | 8 + tests/u128_addo.rs | 8 + tests/u128_sub.rs | 8 + tests/u128_subo.rs | 8 + 11 files changed, 548 insertions(+), 106 deletions(-) create mode 100644 tests/i128_add.rs create mode 100644 tests/i128_addo.rs create mode 100644 tests/i128_sub.rs create mode 100644 tests/i128_subo.rs create mode 100644 tests/u128_add.rs create mode 100644 tests/u128_addo.rs create mode 100644 tests/u128_sub.rs create mode 100644 tests/u128_subo.rs diff --git a/build.rs b/build.rs index e2a63a6..d7f6c01 100644 --- a/build.rs +++ b/build.rs @@ -129,6 +129,12 @@ mod tests { Divsf3, Divdf3, + // int/add.rs + AddU128, + AddI128, + AddoU128, + AddoI128, + // int/mul.rs Muldi3, Mulodi4, @@ -154,6 +160,12 @@ mod tests { Lshrdi3, Lshrti3, + // int/sub.rs + SubU128, + SubI128, + SuboU128, + SuboI128, + // int/udiv.rs Udivdi3, Udivmoddi4, @@ -341,6 +353,242 @@ fn addsf3() { } } + #[derive(Eq, Hash, PartialEq)] + pub struct AddU128 { + a: u128, + b: u128, + c: u128, + } + + impl TestCase for AddU128 { + fn name() -> &'static str { + "u128_add" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + let c = a.wrapping_add(b); + + Some(AddU128 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::add::rust_u128_add; + +static TEST_CASES: &[((u128, u128), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn u128_add() { + for &((a, b), c) in TEST_CASES { + let c_ = rust_u128_add(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct AddI128 { + a: i128, + b: i128, + c: i128, + } + + impl TestCase for AddI128 { + fn name() -> &'static str { + "i128_add" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let c = a.wrapping_add(b); + + Some(AddI128 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::add::rust_i128_add; + +static TEST_CASES: &[((i128, i128), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn i128_add() { + for &((a, b), c) in TEST_CASES { + let c_ = rust_i128_add(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct AddoU128 { + a: u128, + b: u128, + c: u128, + d: bool, + } + + impl TestCase for AddoU128 { + fn name() -> &'static str { + "u128_addo" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + let (c, d) = a.overflowing_add(b); + + Some(AddoU128 { a, b, c, d }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {d})),", + a = self.a, + b = self.b, + c = self.c, + d = self.d + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::add::rust_u128_addo; + +static TEST_CASES: &[((u128, u128), (u128, bool))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn u128_addo() { + for &((a, b), (c, d)) in TEST_CASES { + let (c_, d_) = rust_u128_addo(a, b); + assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct AddoI128 { + a: i128, + b: i128, + c: i128, + d: bool, + } + + impl TestCase for AddoI128 { + fn name() -> &'static str { + "i128_addo" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let (c, d) = a.overflowing_add(b); + + Some(AddoI128 { a, b, c, d }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {d})),", + a = self.a, + b = self.b, + c = self.c, + d = self.d + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::add::rust_i128_addo; + +static TEST_CASES: &[((i128, i128), (i128, bool))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn i128_addo() { + for &((a, b), (c, d)) in TEST_CASES { + let (c_, d_) = rust_i128_addo(a, b); + assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_))); + } +} +" + } + } + #[derive(Eq, Hash, PartialEq)] pub struct Ashldi3 { a: u64, @@ -3229,6 +3477,242 @@ fn subsf3() { } } + #[derive(Eq, Hash, PartialEq)] + pub struct SubU128 { + a: u128, + b: u128, + c: u128, + } + + impl TestCase for SubU128 { + fn name() -> &'static str { + "u128_sub" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + let c = a.wrapping_sub(b); + + Some(SubU128 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sub::rust_u128_sub; + +static TEST_CASES: &[((u128, u128), u128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn u128_sub() { + for &((a, b), c) in TEST_CASES { + let c_ = rust_u128_sub(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct SubI128 { + a: i128, + b: i128, + c: i128, + } + + impl TestCase for SubI128 { + fn name() -> &'static str { + "i128_sub" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let c = a.wrapping_sub(b); + + Some(SubI128 { a, b, c }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), {c}),", + a = self.a, + b = self.b, + c = self.c + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sub::rust_i128_sub; + +static TEST_CASES: &[((i128, i128), i128)] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn i128_sub() { + for &((a, b), c) in TEST_CASES { + let c_ = rust_i128_sub(a, b); + assert_eq!(((a, b), c), ((a, b), c_)); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct SuboU128 { + a: u128, + b: u128, + c: u128, + d: bool, + } + + impl TestCase for SuboU128 { + fn name() -> &'static str { + "u128_subo" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = gen_u128(rng); + let (c, d) = a.overflowing_sub(b); + + Some(SuboU128 { a, b, c, d }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {d})),", + a = self.a, + b = self.b, + c = self.c, + d = self.d + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sub::rust_u128_subo; + +static TEST_CASES: &[((u128, u128), (u128, bool))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn u128_subo() { + for &((a, b), (c, d)) in TEST_CASES { + let (c_, d_) = rust_u128_subo(a, b); + assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_))); + } +} +" + } + } + + #[derive(Eq, Hash, PartialEq)] + pub struct SuboI128 { + a: i128, + b: i128, + c: i128, + d: bool, + } + + impl TestCase for SuboI128 { + fn name() -> &'static str { + "i128_subo" + } + + fn generate(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = gen_i128(rng); + let (c, d) = a.overflowing_sub(b); + + Some(SuboI128 { a, b, c, d }) + } + + fn to_string(&self, buffer: &mut String) { + writeln!( + buffer, + "(({a}, {b}), ({c}, {d})),", + a = self.a, + b = self.b, + c = self.c, + d = self.d + ) + .unwrap(); + } + + fn prologue() -> &'static str { + " +use compiler_builtins::int::sub::rust_i128_subo; + +static TEST_CASES: &[((i128, i128), (i128, bool))] = &[ +" + } + + fn epilogue() -> &'static str { + " +]; + +#[test] +fn i128_subo() { + for &((a, b), (c, d)) in TEST_CASES { + let (c_, d_) = rust_i128_subo(a, b); + assert_eq!(((a, b), (c, d)), ((a, b), (c_, d_))); + } +} +" + } + } + #[derive(Eq, Hash, PartialEq)] pub struct Mulsf3 { a: u32, // f32 diff --git a/src/int/add.rs b/src/int/add.rs index b0f7ab6..5c746c2 100644 --- a/src/int/add.rs +++ b/src/int/add.rs @@ -65,56 +65,3 @@ pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) { 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)); -} \ No newline at end of file diff --git a/src/int/sub.rs b/src/int/sub.rs index 0b0cbf2..abcb45a 100644 --- a/src/int/sub.rs +++ b/src/int/sub.rs @@ -50,56 +50,3 @@ pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) { 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)); -} \ No newline at end of file diff --git a/tests/i128_add.rs b/tests/i128_add.rs new file mode 100644 index 0000000..13af050 --- /dev/null +++ b/tests/i128_add.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/i128_add.rs")); diff --git a/tests/i128_addo.rs b/tests/i128_addo.rs new file mode 100644 index 0000000..306ffac --- /dev/null +++ b/tests/i128_addo.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/i128_addo.rs")); diff --git a/tests/i128_sub.rs b/tests/i128_sub.rs new file mode 100644 index 0000000..933fe4f --- /dev/null +++ b/tests/i128_sub.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/i128_sub.rs")); diff --git a/tests/i128_subo.rs b/tests/i128_subo.rs new file mode 100644 index 0000000..0c2b67c --- /dev/null +++ b/tests/i128_subo.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/i128_subo.rs")); diff --git a/tests/u128_add.rs b/tests/u128_add.rs new file mode 100644 index 0000000..d4b8f2c --- /dev/null +++ b/tests/u128_add.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/u128_add.rs")); diff --git a/tests/u128_addo.rs b/tests/u128_addo.rs new file mode 100644 index 0000000..caff682 --- /dev/null +++ b/tests/u128_addo.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/u128_addo.rs")); diff --git a/tests/u128_sub.rs b/tests/u128_sub.rs new file mode 100644 index 0000000..024266b --- /dev/null +++ b/tests/u128_sub.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/u128_sub.rs")); diff --git a/tests/u128_subo.rs b/tests/u128_subo.rs new file mode 100644 index 0000000..b3fb4b8 --- /dev/null +++ b/tests/u128_subo.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/u128_subo.rs")); From ba750103a3348080035c7140c416f82e0dbae7fb Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Nov 2017 07:00:26 -0800 Subject: [PATCH 5/5] Another attempt at making MIPS happy (I really don't understand how arithmetic makes it segfault...) --- build.rs | 28 +++++------ src/int/add.rs | 67 ------------------------- src/int/addsub.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++ src/int/mod.rs | 3 +- src/int/sub.rs | 52 -------------------- 5 files changed, 136 insertions(+), 136 deletions(-) delete mode 100644 src/int/add.rs create mode 100644 src/int/addsub.rs delete mode 100644 src/int/sub.rs diff --git a/build.rs b/build.rs index d7f6c01..753978d 100644 --- a/build.rs +++ b/build.rs @@ -129,11 +129,15 @@ mod tests { Divsf3, Divdf3, - // int/add.rs + // int/addsub.rs AddU128, AddI128, AddoU128, AddoI128, + SubU128, + SubI128, + SuboU128, + SuboI128, // int/mul.rs Muldi3, @@ -160,12 +164,6 @@ mod tests { Lshrdi3, Lshrti3, - // int/sub.rs - SubU128, - SubI128, - SuboU128, - SuboI128, - // int/udiv.rs Udivdi3, Udivmoddi4, @@ -390,7 +388,7 @@ fn addsf3() { fn prologue() -> &'static str { " -use compiler_builtins::int::add::rust_u128_add; +use compiler_builtins::int::addsub::rust_u128_add; static TEST_CASES: &[((u128, u128), u128)] = &[ " @@ -448,7 +446,7 @@ fn u128_add() { fn prologue() -> &'static str { " -use compiler_builtins::int::add::rust_i128_add; +use compiler_builtins::int::addsub::rust_i128_add; static TEST_CASES: &[((i128, i128), i128)] = &[ " @@ -508,7 +506,7 @@ fn i128_add() { fn prologue() -> &'static str { " -use compiler_builtins::int::add::rust_u128_addo; +use compiler_builtins::int::addsub::rust_u128_addo; static TEST_CASES: &[((u128, u128), (u128, bool))] = &[ " @@ -568,7 +566,7 @@ fn u128_addo() { fn prologue() -> &'static str { " -use compiler_builtins::int::add::rust_i128_addo; +use compiler_builtins::int::addsub::rust_i128_addo; static TEST_CASES: &[((i128, i128), (i128, bool))] = &[ " @@ -3514,7 +3512,7 @@ fn subsf3() { fn prologue() -> &'static str { " -use compiler_builtins::int::sub::rust_u128_sub; +use compiler_builtins::int::addsub::rust_u128_sub; static TEST_CASES: &[((u128, u128), u128)] = &[ " @@ -3572,7 +3570,7 @@ fn u128_sub() { fn prologue() -> &'static str { " -use compiler_builtins::int::sub::rust_i128_sub; +use compiler_builtins::int::addsub::rust_i128_sub; static TEST_CASES: &[((i128, i128), i128)] = &[ " @@ -3632,7 +3630,7 @@ fn i128_sub() { fn prologue() -> &'static str { " -use compiler_builtins::int::sub::rust_u128_subo; +use compiler_builtins::int::addsub::rust_u128_subo; static TEST_CASES: &[((u128, u128), (u128, bool))] = &[ " @@ -3692,7 +3690,7 @@ fn u128_subo() { fn prologue() -> &'static str { " -use compiler_builtins::int::sub::rust_i128_subo; +use compiler_builtins::int::addsub::rust_i128_subo; static TEST_CASES: &[((i128, i128), (i128, bool))] = &[ " diff --git a/src/int/add.rs b/src/int/add.rs deleted file mode 100644 index 5c746c2..0000000 --- a/src/int/add.rs +++ /dev/null @@ -1,67 +0,0 @@ -use int::LargeInt; -use int::Int; - -trait UAdd: LargeInt { - fn uadd(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 UAdd for u128 {} - -trait Add: Int - where ::UnsignedInt: UAdd -{ - fn add(self, other: Self) -> Self { - Self::from_unsigned(self.unsigned().uadd(other.unsigned())) - } -} - -impl Add for u128 {} -impl Add for i128 {} - -trait Addo: Add - where ::UnsignedInt: UAdd -{ - fn addo(self, other: Self, overflow: &mut i32) -> Self { - *overflow = 0; - let result = Add::add(self, 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")] -pub fn rust_i128_add(a: i128, b: i128) -> i128 { - rust_u128_add(a as _, b as _) as _ -} -#[cfg_attr(not(stage0), lang = "i128_addo")] -pub 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")] -pub fn rust_u128_add(a: u128, b: u128) -> u128 { - a.add(b) -} -#[cfg_attr(not(stage0), lang = "u128_addo")] -pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) { - let mut oflow = 0; - let r = a.addo(b, &mut oflow); - (r, oflow != 0) -} diff --git a/src/int/addsub.rs b/src/int/addsub.rs new file mode 100644 index 0000000..7564d89 --- /dev/null +++ b/src/int/addsub.rs @@ -0,0 +1,122 @@ +use int::LargeInt; +use int::Int; + +trait UAddSub: LargeInt { + fn uadd(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)) + } + fn uadd_one(self) -> Self { + let (low, carry) = self.low().overflowing_add(Self::LowHalf::ONE); + let carry = if carry { Self::HighHalf::ONE } else { Self::HighHalf::ZERO }; + Self::from_parts(low, self.high().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 ::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 ::UnsignedInt: UAddSub +{ + fn addo(self, other: Self, overflow: &mut i32) -> Self { + *overflow = 0; + let result = AddSub::add(self, 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 {} + +trait Subo: AddSub + where ::UnsignedInt: UAddSub +{ + fn subo(self, other: Self, overflow: &mut i32) -> Self { + *overflow = 0; + let result = AddSub::sub(self, 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_add")] +pub fn rust_i128_add(a: i128, b: i128) -> i128 { + rust_u128_add(a as _, b as _) as _ +} +#[cfg_attr(not(stage0), lang = "i128_addo")] +pub 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")] +pub fn rust_u128_add(a: u128, b: u128) -> u128 { + a.add(b) +} +#[cfg_attr(not(stage0), lang = "u128_addo")] +pub fn rust_u128_addo(a: u128, b: u128) -> (u128, bool) { + let mut oflow = 0; + let r = a.addo(b, &mut oflow); + (r, oflow != 0) +} + +#[cfg_attr(not(stage0), lang = "i128_sub")] +pub fn rust_i128_sub(a: i128, b: i128) -> i128 { + rust_u128_sub(a as _, b as _) as _ +} +#[cfg_attr(not(stage0), lang = "i128_subo")] +pub 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")] +pub fn rust_u128_sub(a: u128, b: u128) -> u128 { + a.sub(b) +} +#[cfg_attr(not(stage0), lang = "u128_subo")] +pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) { + let mut oflow = 0; + let r = a.subo(b, &mut oflow); + (r, oflow != 0) +} diff --git a/src/int/mod.rs b/src/int/mod.rs index c5490cb..b645b21 100644 --- a/src/int/mod.rs +++ b/src/int/mod.rs @@ -12,11 +12,10 @@ macro_rules! os_ty { } } -pub mod add; +pub mod addsub; pub mod mul; pub mod sdiv; pub mod shift; -pub mod sub; pub mod udiv; /// Trait for some basic operations on integers diff --git a/src/int/sub.rs b/src/int/sub.rs deleted file mode 100644 index abcb45a..0000000 --- a/src/int/sub.rs +++ /dev/null @@ -1,52 +0,0 @@ -use int::LargeInt; - -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 i128 {} -impl Sub for u128 {} - -trait Subo: Sub { - fn subo(self, other: Self, overflow: &mut i32) -> Self { - *overflow = 0; - let result = Sub::sub(self, 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")] -pub fn rust_i128_sub(a: i128, b: i128) -> i128 { - rust_u128_sub(a as _, b as _) as _ -} -#[cfg_attr(not(stage0), lang = "i128_subo")] -pub 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")] -pub fn rust_u128_sub(a: u128, b: u128) -> u128 { - a.sub(b) -} -#[cfg_attr(not(stage0), lang = "u128_subo")] -pub fn rust_u128_subo(a: u128, b: u128) -> (u128, bool) { - let mut oflow = 0; - let r = a.subo(b, &mut oflow); - (r, oflow != 0) -}