mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 16:45:37 +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 {
|
||||
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"]
|
||||
pub trait BitOr<RHS = Self> {
|
||||
type Output;
|
||||
@ -270,6 +302,22 @@ pub trait Neg {
|
||||
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 {
|
||||
type Output = isize;
|
||||
|
||||
|
@ -236,4 +236,21 @@ fn main() {
|
||||
unsafe { assert_eq!(ABC as usize, 0); }
|
||||
|
||||
&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 {
|
||||
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 {
|
||||
@ -948,17 +948,62 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
||||
|
||||
let lhs = in_lhs.load_scalar(fx);
|
||||
let rhs = in_rhs.load_scalar(fx);
|
||||
let res = match bin_op {
|
||||
BinOp::Add => fx.bcx.ins().iadd(lhs, rhs),
|
||||
BinOp::Sub => fx.bcx.ins().isub(lhs, rhs),
|
||||
BinOp::Mul => fx.bcx.ins().imul(lhs, rhs),
|
||||
BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
|
||||
let (res, has_overflow) = match bin_op {
|
||||
BinOp::Add => {
|
||||
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
|
||||
(val, c_out)*/
|
||||
// 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 => {
|
||||
if !signed {
|
||||
let val = if !signed {
|
||||
fx.bcx.ins().ushr(lhs, rhs)
|
||||
} else {
|
||||
fx.bcx.ins().sshr(lhs, rhs)
|
||||
}
|
||||
};
|
||||
// TODO: check for overflow
|
||||
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
|
||||
(val, has_overflow)
|
||||
}
|
||||
_ => bug!(
|
||||
"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().iconst(types::I8, 0);
|
||||
|
||||
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
|
||||
let out_place = CPlace::new_stack_slot(fx, out_ty);
|
||||
let out_layout = out_place.layout();
|
||||
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));
|
||||
|
Loading…
Reference in New Issue
Block a user