in a Use statement, exploit the fact that type and hence layout are the same for LHS and RHS
This commit is contained in:
parent
8ad40479c5
commit
54c81ac989
3 changed files with 44 additions and 15 deletions
|
@ -189,6 +189,22 @@ impl<'tcx> OpTy<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use the existing layout if given (but sanity check in debug mode),
|
||||||
|
// or compute the layout.
|
||||||
|
#[inline(always)]
|
||||||
|
fn from_known_layout<'tcx>(
|
||||||
|
layout: Option<TyLayout<'tcx>>,
|
||||||
|
compute: impl FnOnce() -> EvalResult<'tcx, TyLayout<'tcx>>
|
||||||
|
) -> EvalResult<'tcx, TyLayout<'tcx>> {
|
||||||
|
match layout {
|
||||||
|
None => compute(),
|
||||||
|
Some(layout) => {
|
||||||
|
debug_assert_eq!(layout.ty, compute()?.ty);
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
/// Try reading a value in memory; this is interesting particularily for ScalarPair.
|
/// Try reading a value in memory; this is interesting particularily for ScalarPair.
|
||||||
/// Return None if the layout does not permit loading this as a value.
|
/// Return None if the layout does not permit loading this as a value.
|
||||||
|
@ -377,21 +393,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate a place with the goal of reading from it. This lets us sometimes
|
// Evaluate a place with the goal of reading from it. This lets us sometimes
|
||||||
// avoid allocations.
|
// avoid allocations. If you already know the layout, you can pass it in
|
||||||
|
// to avoid looking it up again.
|
||||||
fn eval_place_to_op(
|
fn eval_place_to_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
mir_place: &mir::Place<'tcx>,
|
mir_place: &mir::Place<'tcx>,
|
||||||
|
layout: Option<TyLayout<'tcx>>,
|
||||||
) -> EvalResult<'tcx, OpTy<'tcx>> {
|
) -> EvalResult<'tcx, OpTy<'tcx>> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place::*;
|
||||||
Ok(match *mir_place {
|
Ok(match *mir_place {
|
||||||
Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
|
Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
|
||||||
Local(local) => {
|
Local(local) => {
|
||||||
let op = *self.frame().locals[local].access()?;
|
let op = *self.frame().locals[local].access()?;
|
||||||
OpTy { op, layout: self.layout_of_local(self.cur_frame(), local)? }
|
let layout = from_known_layout(layout,
|
||||||
|
|| self.layout_of_local(self.cur_frame(), local))?;
|
||||||
|
OpTy { op, layout }
|
||||||
},
|
},
|
||||||
|
|
||||||
Projection(ref proj) => {
|
Projection(ref proj) => {
|
||||||
let op = self.eval_place_to_op(&proj.base)?;
|
let op = self.eval_place_to_op(&proj.base, None)?;
|
||||||
self.operand_projection(op, &proj.elem)?
|
self.operand_projection(op, &proj.elem)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,17 +426,25 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate the operand, returning a place where you can then find the data.
|
/// Evaluate the operand, returning a place where you can then find the data.
|
||||||
pub fn eval_operand(&mut self, mir_op: &mir::Operand<'tcx>) -> EvalResult<'tcx, OpTy<'tcx>> {
|
/// if you already know the layout, you can save two some table lookups
|
||||||
|
/// by passing it in here.
|
||||||
|
pub fn eval_operand(
|
||||||
|
&mut self,
|
||||||
|
mir_op: &mir::Operand<'tcx>,
|
||||||
|
layout: Option<TyLayout<'tcx>>,
|
||||||
|
) -> EvalResult<'tcx, OpTy<'tcx>> {
|
||||||
use rustc::mir::Operand::*;
|
use rustc::mir::Operand::*;
|
||||||
let op = match *mir_op {
|
let op = match *mir_op {
|
||||||
// FIXME: do some more logic on `move` to invalidate the old location
|
// FIXME: do some more logic on `move` to invalidate the old location
|
||||||
Copy(ref place) |
|
Copy(ref place) |
|
||||||
Move(ref place) =>
|
Move(ref place) =>
|
||||||
self.eval_place_to_op(place)?,
|
self.eval_place_to_op(place, layout)?,
|
||||||
|
|
||||||
Constant(ref constant) => {
|
Constant(ref constant) => {
|
||||||
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
|
let layout = from_known_layout(layout, || {
|
||||||
let layout = self.layout_of(ty)?;
|
let ty = self.monomorphize(mir_op.ty(self.mir(), *self.tcx), self.substs());
|
||||||
|
self.layout_of(ty)
|
||||||
|
})?;
|
||||||
let op = self.const_value_to_op(constant.literal.val)?;
|
let op = self.const_value_to_op(constant.literal.val)?;
|
||||||
OpTy { op, layout }
|
OpTy { op, layout }
|
||||||
}
|
}
|
||||||
|
@ -431,7 +459,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
ops: &[mir::Operand<'tcx>],
|
ops: &[mir::Operand<'tcx>],
|
||||||
) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
|
) -> EvalResult<'tcx, Vec<OpTy<'tcx>>> {
|
||||||
ops.into_iter()
|
ops.into_iter()
|
||||||
.map(|op| self.eval_operand(op))
|
.map(|op| self.eval_operand(op, None))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +501,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
&mut self,
|
&mut self,
|
||||||
op: &mir::Operand<'tcx>,
|
op: &mir::Operand<'tcx>,
|
||||||
) -> EvalResult<'tcx, ValTy<'tcx>> {
|
) -> EvalResult<'tcx, ValTy<'tcx>> {
|
||||||
let op = self.eval_operand(op)?;
|
let op = self.eval_operand(op, None)?;
|
||||||
self.read_value(op)
|
self.read_value(op)
|
||||||
}
|
}
|
||||||
pub fn eval_operand_and_read_scalar(
|
pub fn eval_operand_and_read_scalar(
|
||||||
|
|
|
@ -141,7 +141,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
use rustc::mir::Rvalue::*;
|
use rustc::mir::Rvalue::*;
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
Use(ref operand) => {
|
Use(ref operand) => {
|
||||||
let op = self.eval_operand(operand)?;
|
// Avoid recomputing the layout
|
||||||
|
let op = self.eval_operand(operand, Some(dest.layout))?;
|
||||||
self.copy_op(op, dest)?;
|
self.copy_op(op, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, operand) in operands.iter().enumerate() {
|
for (i, operand) in operands.iter().enumerate() {
|
||||||
let op = self.eval_operand(operand)?;
|
let op = self.eval_operand(operand, None)?;
|
||||||
// Ignore zero-sized fields.
|
// Ignore zero-sized fields.
|
||||||
if !op.layout.is_zst() {
|
if !op.layout.is_zst() {
|
||||||
let field_index = active_field_index.unwrap_or(i);
|
let field_index = active_field_index.unwrap_or(i);
|
||||||
|
@ -198,7 +199,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeat(ref operand, _) => {
|
Repeat(ref operand, _) => {
|
||||||
let op = self.eval_operand(operand)?;
|
let op = self.eval_operand(operand, None)?;
|
||||||
let dest = self.force_allocation(dest)?;
|
let dest = self.force_allocation(dest)?;
|
||||||
let length = dest.len();
|
let length = dest.len();
|
||||||
|
|
||||||
|
@ -260,7 +261,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
|
|
||||||
Cast(kind, ref operand, cast_ty) => {
|
Cast(kind, ref operand, cast_ty) => {
|
||||||
debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
|
debug_assert_eq!(self.monomorphize(cast_ty, self.substs()), dest.layout.ty);
|
||||||
let src = self.eval_operand(operand)?;
|
let src = self.eval_operand(operand, None)?;
|
||||||
self.cast(src, kind, dest)?;
|
self.cast(src, kind, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
ref targets,
|
ref targets,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let discr_val = self.eval_operand(discr)?;
|
let discr_val = self.eval_operand(discr, None)?;
|
||||||
let discr = self.read_value(discr_val)?;
|
let discr = self.read_value(discr_val)?;
|
||||||
trace!("SwitchInt({:?})", *discr);
|
trace!("SwitchInt({:?})", *discr);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let func = self.eval_operand(func)?;
|
let func = self.eval_operand(func, None)?;
|
||||||
let (fn_def, sig) = match func.layout.ty.sty {
|
let (fn_def, sig) = match func.layout.ty.sty {
|
||||||
ty::TyFnPtr(sig) => {
|
ty::TyFnPtr(sig) => {
|
||||||
let fn_ptr = self.read_scalar(func)?.to_ptr()?;
|
let fn_ptr = self.read_scalar(func)?.to_ptr()?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue