From 45de0336a5ca03834f74189af6682462d874f980 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 29 Jun 2019 16:43:20 +0200 Subject: [PATCH] Fix some more stuff --- example/mini_core.rs | 28 +++++++++++++++++ example/mini_core_hello_world.rs | 20 ++++++++++-- src/base.rs | 19 +++++++++-- src/common.rs | 54 +++++++++++++++++++++----------- src/intrinsics.rs | 26 +++++++++++++-- 5 files changed, 121 insertions(+), 26 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 745e86de485..fa47831b648 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -44,10 +44,12 @@ unsafe impl Copy for u8 {} unsafe impl Copy for u16 {} unsafe impl Copy for u32 {} unsafe impl Copy for u64 {} +unsafe impl Copy for u128 {} unsafe impl Copy for usize {} unsafe impl Copy for i8 {} unsafe impl Copy for i16 {} unsafe impl Copy for i32 {} +unsafe impl Copy for i128 {} unsafe impl Copy for isize {} unsafe impl Copy for char {} unsafe impl<'a, T: ?Sized> Copy for &'a T {} @@ -152,6 +154,14 @@ impl Add for u128 { } } +impl Add for i128 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + #[lang = "sub"] pub trait Sub { type Output; @@ -276,6 +286,15 @@ impl PartialEq for i32 { } } +impl PartialEq for i128 { + fn eq(&self, other: &i128) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &i128) -> bool { + (*self) != (*other) + } +} + impl PartialEq for isize { fn eq(&self, other: &isize) -> bool { (*self) == (*other) @@ -322,6 +341,14 @@ impl Neg for i16 { type Output = i16; fn neg(self) -> i16 { + self + } +} + +impl Neg for i128 { + type Output = i128; + + fn neg(self) -> i128 { -self } } @@ -446,6 +473,7 @@ pub mod intrinsics { pub fn needs_drop() -> bool; pub fn bitreverse(x: T) -> T; pub fn bswap(x: T) -> T; + pub fn unchecked_div(lhs: T, rhs: T) -> T; } } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index d435e347005..4a26577af52 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -117,6 +117,22 @@ impl CoerceUnsized> for Unique where T: Unsiz fn take_f32(_f: f32) {} fn take_unique(_u: Unique<()>) {} -fn main() { - +fn checked_div_i128(lhs: i128, rhs: i128) -> Option { + if rhs == 0 || (lhs == -170141183460469231731687303715884105728 && rhs == -1) { + None + } else { + Some(unsafe { intrinsics::unchecked_div(lhs, rhs) }) + } +} + +fn checked_div_u128(lhs: u128, rhs: u128) -> Option { + match rhs { + 0 => None, + rhs => Some(unsafe { intrinsics::unchecked_div(lhs, rhs) }) + } +} + +fn main() { + checked_div_i128(0i128, 2i128); + checked_div_u128(0u128, 2u128); } diff --git a/src/base.rs b/src/base.rs index 7720296cfbf..94ba93de141 100644 --- a/src/base.rs +++ b/src/base.rs @@ -357,15 +357,28 @@ fn trans_stmt<'a, 'tcx: 'a>( let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0); fx.bcx.ins().bint(types::I8, res) } - ty::Uint(_) | ty::Int(_) => fx.bcx.ins().bnot(val), + ty::Uint(_) | ty::Int(_) => { + if fx.bcx.func.dfg.value_type(val) == types::I128 { + let (a, b) = fx.bcx.ins().isplit(val); + let a = fx.bcx.ins().bnot(a); + let b = fx.bcx.ins().bnot(b); + fx.bcx.ins().iconcat(a, b) + } else { + fx.bcx.ins().bnot(val) + } + } _ => unimplemented!("un op Not for {:?}", layout.ty), } } UnOp::Neg => match layout.ty.sty { ty::Int(_) => { let clif_ty = fx.clif_type(layout.ty).unwrap(); - let zero = fx.bcx.ins().iconst(clif_ty, 0); - fx.bcx.ins().isub(zero, val) + if clif_ty == types::I128 { + crate::trap::trap_unreachable_ret_value(fx, layout, "i128 neg is not yet supported").load_scalar(fx) + } else { + let zero = fx.bcx.ins().iconst(clif_ty, 0); + fx.bcx.ins().isub(zero, val) + } } ty::Float(_) => fx.bcx.ins().fneg(val), _ => unimplemented!("un op Neg for {:?}", layout.ty), diff --git a/src/common.rs b/src/common.rs index 57794a66b9c..6c907720477 100644 --- a/src/common.rs +++ b/src/common.rs @@ -82,26 +82,42 @@ pub fn clif_intcast<'a, 'tcx: 'a>( if from == to { return val; } - if to == types::I128 { - let wider = if signed { - fx.bcx.ins().sextend(types::I64, val) - } else { - fx.bcx.ins().uextend(types::I64, val) - }; - let zero = fx.bcx.ins().iconst(types::I64, 0); - return fx.bcx.ins().iconcat(wider, zero); - } - if to.wider_or_equal(from) { - if signed { - fx.bcx.ins().sextend(to, val) - } else { - fx.bcx.ins().uextend(to, val) + match (from, to) { + // equal + (_, _) if from == to => val, + + // extend + (_, types::I128) => { + let wider = if from == types::I64 { + val + } else if signed { + fx.bcx.ins().sextend(types::I64, val) + } else { + fx.bcx.ins().uextend(types::I64, val) + }; + let zero = fx.bcx.ins().iconst(types::I64, 0); + fx.bcx.ins().iconcat(wider, zero) + } + (_, _) if to.wider_or_equal(from) => { + if signed { + fx.bcx.ins().sextend(to, val) + } else { + fx.bcx.ins().uextend(to, val) + } + } + + // reduce + (types::I128, _) => { + let (lsb, _msb) = fx.bcx.ins().isplit(val); + if to == types::I64 { + lsb + } else { + fx.bcx.ins().ireduce(to, lsb) + } + } + (_, _) => { + fx.bcx.ins().ireduce(to, val) } - } else if from == types::I128 { - let (lsb, _msb) = fx.bcx.ins().isplit(val); - fx.bcx.ins().ireduce(to, lsb) - } else { - fx.bcx.ins().ireduce(to, val) } } diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 792d7c99373..aaf46221785 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -390,11 +390,33 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count); }; ctlz | ctlz_nonzero, (v arg) { - let res = CValue::by_val(fx.bcx.ins().clz(arg), fx.layout_of(T)); + let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { + // FIXME verify this algorithm is correct + let (lsb, msb) = fx.bcx.ins().isplit(arg); + let lsb_lz = fx.bcx.ins().clz(lsb); + let msb_lz = fx.bcx.ins().clz(msb); + let msb_lz_is_64 = fx.bcx.ins().icmp_imm(IntCC::Equal, msb_lz, 64); + let lsb_lz_plus_64 = fx.bcx.ins().iadd_imm(lsb_lz, 64); + fx.bcx.ins().select(msb_lz_is_64, lsb_lz_plus_64, msb_lz) + } else { + fx.bcx.ins().clz(arg) + }; + let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; cttz | cttz_nonzero, (v arg) { - let res = CValue::by_val(fx.bcx.ins().ctz(arg), fx.layout_of(T)); + let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { + // FIXME verify this algorithm is correct + let (lsb, msb) = fx.bcx.ins().isplit(arg); + let lsb_tz = fx.bcx.ins().ctz(lsb); + let msb_tz = fx.bcx.ins().ctz(msb); + let lsb_tz_is_64 = fx.bcx.ins().icmp_imm(IntCC::Equal, lsb_tz, 64); + let msb_lz_plus_64 = fx.bcx.ins().iadd_imm(msb_tz, 64); + fx.bcx.ins().select(lsb_tz_is_64, msb_lz_plus_64, lsb_tz) + } else { + fx.bcx.ins().ctz(arg) + }; + let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; ctpop, (v arg) {