Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make miri value visitor useful for mutation #55916

Merged
merged 3 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,34 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}

Misc => {
let src_layout = src.layout;
let src = self.read_immediate(src)?;

if self.type_is_fat_ptr(src.layout.ty) {
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
// There are no casts to references
assert!(!dest.layout.ty.is_region_ptr());
// Hence we make all casts erase the tag
let src = src.erase_tag().with_default_tag();

if self.type_is_fat_ptr(src_layout.ty) {
match (src, self.type_is_fat_ptr(dest.layout.ty)) {
// pointers to extern types
(Immediate::Scalar(_),_) |
// slices and trait objects to other slices/trait objects
(Immediate::ScalarPair(..), true) => {
// No change to immediate
self.write_immediate(*src, dest)?;
self.write_immediate(src, dest)?;
}
// slices and trait objects to thin pointers (dropping the metadata)
(Immediate::ScalarPair(data, _), false) => {
self.write_scalar(data, dest)?;
}
}
} else {
match src.layout.variants {
match src_layout.variants {
layout::Variants::Single { index } => {
if let Some(def) = src.layout.ty.ty_adt_def() {
if let Some(def) = src_layout.ty.ty_adt_def() {
// Cast from a univariant enum
assert!(src.layout.is_zst());
assert!(src_layout.is_zst());
let discr_val = def
.discriminant_for_variant(*self.tcx, index)
.val;
Expand All @@ -78,7 +84,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
layout::Variants::NicheFilling { .. } => {},
}

let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
let dest_val = self.cast_scalar(src.to_scalar()?, src_layout, dest.layout)?;
self.write_scalar(dest_val, dest)?;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ pub use self::machine::{Machine, AllocMap, MayLeak};

pub use self::operand::{ScalarMaybeUndef, Immediate, ImmTy, Operand, OpTy};

pub use self::visitor::ValueVisitor;
pub use self::visitor::{ValueVisitor, MutValueVisitor};

pub use self::validity::RefTracking;
5 changes: 3 additions & 2 deletions src/librustc_mir/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc::mir::interpret::{
};

use super::{
OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor
OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor
};

macro_rules! validation_failure {
Expand Down Expand Up @@ -281,8 +281,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
}
}

fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
{
let value = self.ecx.read_immediate(value)?;
// Go over all the primitive types
let ty = value.layout.ty;
match ty.sty {
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_mir/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc::mir::interpret::{
};

use super::{
Machine, EvalContext, MPlaceTy, OpTy, ImmTy,
Machine, EvalContext, MPlaceTy, OpTy,
};

// A thing that we can project into, and that has a layout.
Expand Down Expand Up @@ -201,9 +201,11 @@ macro_rules! make_value_visitor {
{ Ok(()) }

/// Called whenever we reach a value of primitive type. There can be no recursion
/// below such a value. This is the leave function.
/// below such a value. This is the leaf function.
/// We do *not* provide an `ImmTy` here because some implementations might want
/// to write to the place this primitive lives in.
#[inline(always)]
fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
{ Ok(()) }

// Default recursors. Not meant to be overloaded.
Expand Down Expand Up @@ -279,9 +281,7 @@ macro_rules! make_value_visitor {
_ => v.layout().ty.builtin_deref(true).is_some(),
};
if primitive {
let op = v.to_op(self.ecx())?;
let val = self.ecx().read_immediate(op)?;
return self.visit_primitive(val);
return self.visit_primitive(v);
}

// Proceed into the fields.
Expand Down