rustc does overflow checking for us, don't duplicate it.
This commit is contained in:
parent
ed4af21605
commit
b9ac85d2a9
3 changed files with 15 additions and 26 deletions
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue