Skip to content

Make miri value visitor useful for mutation #55916

New issue

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

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

Already on GitHub? # to your account

Merged
merged 3 commits into from
Nov 19, 2018
Merged
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
@@ -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;
@@ -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)?;
}
}
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/mod.rs
Original file line number Diff line number Diff line change
@@ -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
@@ -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 {
@@ -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 {
12 changes: 6 additions & 6 deletions src/librustc_mir/interpret/visitor.rs
Original file line number Diff line number Diff line change
@@ -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.
@@ -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.
@@ -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.