提交 128c634c 编写于 作者: R Ralf Jung

also avoid recomputing the layout for unary and binary ops, where possible

上级 54c81ac9
......@@ -497,19 +497,15 @@ pub(super) fn global_to_op(&mut self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, O
/// We cannot do self.read_value(self.eval_operand) due to eval_operand taking &mut self,
/// so this helps avoid unnecessary let.
pub fn eval_operand_and_read_valty(
#[inline]
pub fn eval_operand_and_read_value(
&mut self,
op: &mir::Operand<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, ValTy<'tcx>> {
let op = self.eval_operand(op, None)?;
let op = self.eval_operand(op, layout)?;
self.read_value(op)
}
pub fn eval_operand_and_read_scalar(
&mut self,
op: &mir::Operand<'tcx>,
) -> EvalResult<'tcx, ScalarMaybeUndef> {
Ok(self.eval_operand_and_read_valty(op)?.to_scalar_or_undef())
}
/// reads a tag and produces the corresponding variant index
pub fn read_discriminant_as_variant_index(
......
......@@ -8,6 +8,33 @@
use super::{EvalContext, Machine};
/// Classify whether an operator is "left-homogeneous", i.e. the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
use rustc::mir::BinOp::*;
match op {
Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
Offset | Shl | Shr =>
true,
Eq | Ne | Lt | Le | Gt | Ge =>
false,
}
}
/// Classify whether an operator is "right-homogeneous", i.e. the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
use rustc::mir::BinOp::*;
match op {
Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
Eq | Ne | Lt | Le | Gt | Ge =>
true,
Offset | Shl | Shr =>
false,
}
}
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
pub fn inc_step_counter_and_detect_loops(&mut self) -> EvalResult<'tcx, ()> {
/// The number of steps between loop detector snapshots.
......@@ -147,8 +174,10 @@ fn eval_rvalue_into_place(
}
BinaryOp(bin_op, ref left, ref right) => {
let left = self.eval_operand_and_read_valty(left)?;
let right = self.eval_operand_and_read_valty(right)?;
let layout = if binop_left_homogeneous(bin_op) { Some(dest.layout) } else { None };
let left = self.eval_operand_and_read_value(left, layout)?;
let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
let right = self.eval_operand_and_read_value(right, layout)?;
self.binop_ignore_overflow(
bin_op,
left,
......@@ -158,8 +187,10 @@ fn eval_rvalue_into_place(
}
CheckedBinaryOp(bin_op, ref left, ref right) => {
let left = self.eval_operand_and_read_valty(left)?;
let right = self.eval_operand_and_read_valty(right)?;
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.eval_operand_and_read_value(left, None)?;
let layout = if binop_right_homogeneous(bin_op) { Some(left.layout) } else { None };
let right = self.eval_operand_and_read_value(right, layout)?;
self.binop_with_overflow(
bin_op,
left,
......@@ -169,8 +200,9 @@ fn eval_rvalue_into_place(
}
UnaryOp(un_op, ref operand) => {
let val = self.eval_operand_and_read_scalar(operand)?;
let val = self.unary_op(un_op, val.not_undef()?, dest.layout)?;
// The operand always has the same type as the result.
let val = self.eval_operand_and_read_value(operand, Some(dest.layout))?;
let val = self.unary_op(un_op, val.to_scalar()?, dest.layout)?;
self.write_scalar(val, dest)?;
}
......
......@@ -144,18 +144,18 @@ pub(super) fn eval_terminator(
target,
..
} => {
let cond_val = self.eval_operand_and_read_scalar(cond)?.not_undef()?.to_bool()?;
let cond_val = self.eval_operand_and_read_value(cond, None)?.to_scalar()?.to_bool()?;
if expected == cond_val {
self.goto_block(target);
} else {
use rustc::mir::interpret::EvalErrorKind::*;
return match *msg {
BoundsCheck { ref len, ref index } => {
let len = self.eval_operand_and_read_scalar(len)
.expect("can't eval len")
let len = self.eval_operand_and_read_value(len, None)
.expect("can't eval len").to_scalar()?
.to_bits(self.memory().pointer_size())? as u64;
let index = self.eval_operand_and_read_scalar(index)
.expect("can't eval index")
let index = self.eval_operand_and_read_value(index, None)
.expect("can't eval index").to_scalar()?
.to_bits(self.memory().pointer_size())? as u64;
err!(BoundsCheck { len, index })
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册