1
Fork 0

rustc does overflow checking for us, don't duplicate it.

This commit is contained in:
Oliver Schneider 2016-06-20 16:52:43 +02:00
parent ed4af21605
commit b9ac85d2a9
No known key found for this signature in database
GPG key ID: 56D6EEA0FC67AC46
3 changed files with 15 additions and 26 deletions

View file

@ -30,7 +30,6 @@ pub enum EvalError<'tcx> {
ArrayIndexOutOfBounds(Span, u64, u64),
Math(Span, ConstMathErr),
InvalidBitShiftRhs(PrimVal),
Overflow(PrimVal, PrimVal, mir::BinOp, PrimVal),
}
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
@ -71,8 +70,6 @@ impl<'tcx> Error for EvalError<'tcx> {
"mathematical operation failed",
EvalError::InvalidBitShiftRhs(..) =>
"bit shift rhs negative or not an int",
EvalError::Overflow(..) =>
"mathematical operation overflowed",
}
}
@ -92,8 +89,6 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
write!(f, "array index {} out of bounds {} at {:?}", index, len, span),
EvalError::Math(span, ref err) =>
write!(f, "mathematical operation at {:?} failed with {:?}", span, err),
EvalError::Overflow(l, r, op, val) =>
write!(f, "mathematical operation overflowed: {:?} {} {:?} => {:?}", l, op.to_hir_binop().as_str(), r, val),
_ => write!(f, "{}", self.description()),
}
}

View file

@ -688,13 +688,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.memory.write_bool(dest.offset(offset), overflowed)
}
/// extracts the lhs and rhs primval from the operands and applies the binary op
/// Extracts the lhs and rhs primval from the operands and applies the binary op.
/// Returns the result and whether the operation overflowed
fn eval_binop(
&mut self,
op: mir::BinOp,
left: &mir::Operand<'tcx>,
right: &mir::Operand<'tcx>,
) -> EvalResult<'tcx, PrimVal> {
) -> EvalResult<'tcx, (PrimVal, bool)> {
let left_ptr = self.eval_operand(left)?;
let left_ty = self.operand_ty(left);
let left_val = self.read_primval(left_ptr, left_ty)?;
@ -714,18 +715,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
right: &mir::Operand<'tcx>,
dest: Pointer,
) -> EvalResult<'tcx, bool> {
match self.eval_binop(op, left, right) {
Ok(val) => {
self.memory.write_primval(dest, val)?;
Ok(false)
},
Err(EvalError::Overflow(l, r, op, val)) => {
debug!("operation overflowed: {:?} {} {:?} => {:?}", l, op.to_hir_binop().as_str(), r, val);
self.memory.write_primval(dest, val)?;
Ok(true)
},
Err(other) => Err(other),
}
let (val, overflow) = self.eval_binop(op, left, right)?;
self.memory.write_primval(dest, val)?;
Ok(overflow)
}
fn call_intrinsic(
@ -951,7 +943,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
BinaryOp(bin_op, ref left, ref right) => {
let result = self.eval_binop(bin_op, left, right)?;
// ignore overflow bit, rustc inserts check branches for us
let result = self.eval_binop(bin_op, left, right)?.0;
self.memory.write_primval(dest, result)?;
}

View file

@ -14,7 +14,8 @@ pub enum PrimVal {
IntegerPtr(u64),
}
pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> EvalResult<'tcx, PrimVal> {
/// returns the result of the operation and whether the operation overflowed
pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> EvalResult<'tcx, (PrimVal, bool)> {
use rustc::mir::repr::BinOp::*;
use self::PrimVal::*;
@ -22,7 +23,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
($v:ident, $v2:ident, $l:ident, $op:ident, $r:ident) => ({
let (val, of) = $l.$op($r);
if of {
return Err(EvalError::Overflow($v($l), $v2($r), bin_op, $v(val)));
return Ok(($v(val), true));
} else {
$v(val)
}
@ -99,7 +100,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
U64(l) => shift!(U64, l, r),
_ => unreachable!(),
};
return Ok(val);
return Ok((val, false));
},
_ => {},
}
@ -137,7 +138,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
(AbstractPtr(_), FnPtr(_)) |
(FnPtr(_), IntegerPtr(_)) |
(IntegerPtr(_), FnPtr(_)) =>
return unrelated_ptr_ops(bin_op),
unrelated_ptr_ops(bin_op)?,
(FnPtr(l_ptr), FnPtr(r_ptr)) => match bin_op {
Eq => Bool(l_ptr == r_ptr),
@ -147,7 +148,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
(AbstractPtr(l_ptr), AbstractPtr(r_ptr)) => {
if l_ptr.alloc_id != r_ptr.alloc_id {
return unrelated_ptr_ops(bin_op);
return Ok((unrelated_ptr_ops(bin_op)?, false));
}
let l = l_ptr.offset;
@ -167,7 +168,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
(l, r) => return Err(EvalError::Unimplemented(format!("unimplemented binary op: {:?}, {:?}, {:?}", l, r, bin_op))),
};
Ok(val)
Ok((val, false))
}
pub fn unary_op<'tcx>(un_op: mir::UnOp, val: PrimVal) -> EvalResult<'tcx, PrimVal> {