mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-13 17:13:48 +00:00
Merge pull request #646 from bjorn3/wip_checked_binops2
Implement checked add and sub
This commit is contained in:
commit
bba11f6172
@ -128,6 +128,14 @@ impl Add for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Add for i8 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self {
|
||||||
|
self + rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Add for usize {
|
impl Add for usize {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -151,6 +159,30 @@ impl Sub for usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sub for u8 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
self - rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for i8 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
self - rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for i16 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
self - rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[lang = "bitor"]
|
#[lang = "bitor"]
|
||||||
pub trait BitOr<RHS = Self> {
|
pub trait BitOr<RHS = Self> {
|
||||||
type Output;
|
type Output;
|
||||||
@ -270,6 +302,22 @@ pub trait Neg {
|
|||||||
fn neg(self) -> Self::Output;
|
fn neg(self) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for i8 {
|
||||||
|
type Output = i8;
|
||||||
|
|
||||||
|
fn neg(self) -> i8 {
|
||||||
|
-self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for i16 {
|
||||||
|
type Output = i16;
|
||||||
|
|
||||||
|
fn neg(self) -> i16 {
|
||||||
|
-self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Neg for isize {
|
impl Neg for isize {
|
||||||
type Output = isize;
|
type Output = isize;
|
||||||
|
|
||||||
|
@ -236,4 +236,21 @@ fn main() {
|
|||||||
unsafe { assert_eq!(ABC as usize, 0); }
|
unsafe { assert_eq!(ABC as usize, 0); }
|
||||||
|
|
||||||
&mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
|
&mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
|
||||||
|
|
||||||
|
// checked binops
|
||||||
|
let zeroi8 = 0i8;
|
||||||
|
let oneu8 = 1u8;
|
||||||
|
let onei8 = 1i8;
|
||||||
|
zeroi8 - 1;
|
||||||
|
oneu8 - 1;
|
||||||
|
zeroi8 - -2i8;
|
||||||
|
#[allow(unreachable_code)]
|
||||||
|
{
|
||||||
|
if false {
|
||||||
|
let minustwoi8 = -2i8;
|
||||||
|
oneu8 + 255;
|
||||||
|
onei8 + 127;
|
||||||
|
minustwoi8 - 127;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
65
src/base.rs
65
src/base.rs
@ -241,7 +241,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>)
|
|||||||
} else {
|
} else {
|
||||||
fx.bcx.ins().brz(cond, target, &[]);
|
fx.bcx.ins().brz(cond, target, &[]);
|
||||||
};
|
};
|
||||||
trap_panic(fx, format!("[panic] Assert {:?} failed.", msg));
|
trap_panic(fx, format!("[panic] Assert {:?} failed at {:?}.", msg, bb_data.terminator().source_info.span));
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::SwitchInt {
|
TerminatorKind::SwitchInt {
|
||||||
@ -948,17 +948,62 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
|||||||
|
|
||||||
let lhs = in_lhs.load_scalar(fx);
|
let lhs = in_lhs.load_scalar(fx);
|
||||||
let rhs = in_rhs.load_scalar(fx);
|
let rhs = in_rhs.load_scalar(fx);
|
||||||
let res = match bin_op {
|
let (res, has_overflow) = match bin_op {
|
||||||
BinOp::Add => fx.bcx.ins().iadd(lhs, rhs),
|
BinOp::Add => {
|
||||||
BinOp::Sub => fx.bcx.ins().isub(lhs, rhs),
|
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
|
||||||
BinOp::Mul => fx.bcx.ins().imul(lhs, rhs),
|
(val, c_out)*/
|
||||||
BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
|
// FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
|
||||||
|
let val = fx.bcx.ins().iadd(lhs, rhs);
|
||||||
|
let has_overflow = if !signed {
|
||||||
|
fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
|
||||||
|
} else {
|
||||||
|
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
|
||||||
|
let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
|
||||||
|
fx.bcx.ins().bxor(rhs_is_negative, slt)
|
||||||
|
};
|
||||||
|
(val, has_overflow)
|
||||||
|
}
|
||||||
|
BinOp::Sub => {
|
||||||
|
/*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
|
||||||
|
(val, b_out)*/
|
||||||
|
// FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
|
||||||
|
let val = fx.bcx.ins().isub(lhs, rhs);
|
||||||
|
let has_overflow = if !signed {
|
||||||
|
fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
|
||||||
|
} else {
|
||||||
|
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
|
||||||
|
let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
|
||||||
|
fx.bcx.ins().bxor(rhs_is_negative, sgt)
|
||||||
|
};
|
||||||
|
(val, has_overflow)
|
||||||
|
}
|
||||||
|
BinOp::Mul => {
|
||||||
|
let val = fx.bcx.ins().imul(lhs, rhs);
|
||||||
|
/*let val_hi = if !signed {
|
||||||
|
fx.bcx.ins().umulhi(lhs, rhs)
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().smulhi(lhs, rhs)
|
||||||
|
};
|
||||||
|
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
|
||||||
|
// TODO: check for overflow
|
||||||
|
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
||||||
|
(val, has_overflow)
|
||||||
|
}
|
||||||
|
BinOp::Shl => {
|
||||||
|
let val = fx.bcx.ins().ishl(lhs, rhs);
|
||||||
|
// TODO: check for overflow
|
||||||
|
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
||||||
|
(val, has_overflow)
|
||||||
|
}
|
||||||
BinOp::Shr => {
|
BinOp::Shr => {
|
||||||
if !signed {
|
let val = if !signed {
|
||||||
fx.bcx.ins().ushr(lhs, rhs)
|
fx.bcx.ins().ushr(lhs, rhs)
|
||||||
} else {
|
} else {
|
||||||
fx.bcx.ins().sshr(lhs, rhs)
|
fx.bcx.ins().sshr(lhs, rhs)
|
||||||
}
|
};
|
||||||
|
// TODO: check for overflow
|
||||||
|
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
||||||
|
(val, has_overflow)
|
||||||
}
|
}
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
|
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
|
||||||
@ -968,9 +1013,7 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check for overflow
|
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
|
||||||
let has_overflow = fx.bcx.ins().iconst(types::I8, 0);
|
|
||||||
|
|
||||||
let out_place = CPlace::new_stack_slot(fx, out_ty);
|
let out_place = CPlace::new_stack_slot(fx, out_ty);
|
||||||
let out_layout = out_place.layout();
|
let out_layout = out_place.layout();
|
||||||
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));
|
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));
|
||||||
|
Loading…
Reference in New Issue
Block a user