Fix the miri tool

This commit is contained in:
Oliver Schneider 2018-04-13 16:05:54 +02:00 committed by Oliver Schneider
parent f5cf1a8419
commit 3084c066e4
No known key found for this signature in database
GPG Key ID: A69F8D225B3AD7D9
9 changed files with 80 additions and 84 deletions

15
src/Cargo.lock generated
View File

@ -222,16 +222,6 @@ dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargo_metadata"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cargo_metadata"
version = "0.5.4"
@ -1188,9 +1178,11 @@ name = "miri"
version = "0.1.0"
dependencies = [
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2923,7 +2915,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
"checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3"
"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"

View File

@ -67,7 +67,7 @@ verify_status rust-by-example src/doc/rust-by-example
verify_status rls src/tool/rls
verify_status rustfmt src/tool/rustfmt
verify_status clippy-driver src/tool/clippy
#verify_status miri src/tool/miri
verify_status miri src/tool/miri
if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
. "$(dirname $0)/repo.sh"

View File

@ -16,7 +16,7 @@ mod check_match;
pub use self::check_match::check_crate;
pub(crate) use self::check_match::check_match;
use interpret::{const_val_field, const_discr, self};
use interpret::{const_val_field, const_variant_index, self};
use rustc::middle::const_val::ConstVal;
use rustc::mir::{Field, BorrowKind, Mutability};
@ -835,38 +835,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
match cv.val {
ConstVal::Value(val) => {
let discr_val = const_discr(
let variant_index = const_variant_index(
self.tcx, self.param_env, instance, val, cv.ty
).expect("const_discr failed");
let layout = self
.tcx
.layout_of(self.param_env.and(cv.ty))
.expect("layout of enum not available");
let variant_index = match layout.variants {
ty::layout::Variants::Single { index } => index,
ty::layout::Variants::Tagged { ref discr, .. } => {
// raw discriminants for enums are isize or bigger during
// their computation, but later shrunk to the smallest possible
// representation
let size = discr.value.size(self.tcx).bits();
let amt = 128 - size;
adt_def
.discriminants(self.tcx)
.position(|var| ((var.val << amt) >> amt) == discr_val)
.unwrap_or_else(|| {
bug!("discriminant {} not found in {:#?}",
discr_val,
adt_def
.discriminants(self.tcx)
.collect::<Vec<_>>(),
);
})
}
ty::layout::Variants::NicheFilling { .. } => {
assert_eq!(discr_val as usize as u128, discr_val);
discr_val as usize
},
};
).expect("const_variant_index failed");
let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(),
Some(variant_index),

View File

@ -400,14 +400,14 @@ pub fn const_val_field<'a, 'tcx>(
}
}
pub fn const_discr<'a, 'tcx>(
pub fn const_variant_index<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
value: Value,
ty: Ty<'tcx>,
) -> EvalResult<'tcx, u128> {
trace!("const_discr: {:?}, {:?}, {:?}", instance, value, ty);
) -> EvalResult<'tcx, usize> {
trace!("const_variant_index: {:?}, {:?}, {:?}", instance, value, ty);
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let (ptr, align) = match value {
Value::ByValPair(..) | Value::ByVal(_) => {
@ -421,7 +421,7 @@ pub fn const_discr<'a, 'tcx>(
Value::ByRef(ptr, align) => (ptr, align),
};
let place = Place::from_primval_ptr(ptr, align);
ecx.read_discriminant_value(place, ty)
ecx.read_discriminant_as_variant_index(place, ty)
}
pub fn const_eval_provider<'a, 'tcx>(

View File

@ -743,28 +743,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
Discriminant(ref place) => {
let ty = self.place_ty(place);
let layout = self.layout_of(ty)?;
let place = self.eval_place(place)?;
let discr_val = self.read_discriminant_value(place, ty)?;
match layout.variants {
layout::Variants::Single { index } => {
assert_eq!(discr_val, index as u128);
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {
if let ty::TyAdt(adt_def, _) = ty.sty {
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>());
if adt_def.discriminants(*self.tcx).all(|v| {
discr_val != v.val
})
{
return err!(InvalidDiscriminant);
}
} else {
bug!("rustc only generates Rvalue::Discriminant for enums");
}
}
}
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
}
}
@ -837,13 +817,39 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
}
}
/// reads a tag and produces the corresponding variant index
pub fn read_discriminant_as_variant_index(
&mut self,
place: Place,
ty: Ty<'tcx>,
) -> EvalResult<'tcx, usize> {
let layout = self.layout_of(ty)?;
match layout.variants {
ty::layout::Variants::Single { index } => Ok(index),
ty::layout::Variants::Tagged { .. } => {
let discr_val = self.read_discriminant_value(place, ty)?;
ty
.ty_adt_def()
.expect("tagged layout for non adt")
.discriminants(self.tcx.tcx)
.position(|var| var.val == discr_val)
.ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into())
}
ty::layout::Variants::NicheFilling { .. } => {
let discr_val = self.read_discriminant_value(place, ty)?;
assert_eq!(discr_val as usize as u128, discr_val);
Ok(discr_val as usize)
},
}
}
pub fn read_discriminant_value(
&mut self,
place: Place,
ty: Ty<'tcx>,
) -> EvalResult<'tcx, u128> {
let layout = self.layout_of(ty)?;
//trace!("read_discriminant_value {:#?}", layout);
trace!("read_discriminant_value {:#?}", layout);
match layout.variants {
layout::Variants::Single { index } => {
@ -854,13 +860,34 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
}
let (discr_place, discr) = self.place_field(place, mir::Field::new(0), layout)?;
trace!("discr place: {:?}, {:?}", discr_place, discr);
let raw_discr = self.value_to_primval(ValTy {
value: self.read_place(discr_place)?,
ty: discr.ty
})?;
let discr_val = match layout.variants {
layout::Variants::Single { .. } => bug!(),
layout::Variants::Tagged { .. } => raw_discr.to_bytes()?,
// FIXME: should we catch invalid discriminants here?
layout::Variants::Tagged { .. } => {
if discr.ty.is_signed() {
let i = raw_discr.to_bytes()? as i128;
// going from layout tag type to typeck discriminant type
// requires first sign extending with the layout discriminant
let amt = 128 - discr.size.bits();
let sexted = (i << amt) >> amt;
// and then zeroing with the typeck discriminant type
let discr_ty = ty
.ty_adt_def().expect("tagged layout corresponds to adt")
.repr
.discr_type();
let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty);
let amt = 128 - discr_ty.size().bits();
let truncatee = sexted as u128;
(truncatee << amt) >> amt
} else {
raw_discr.to_bytes()?
}
},
layout::Variants::NicheFilling {
dataful_variant,
ref niche_variants,
@ -910,11 +937,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
layout::Abi::Uninhabited);
}
}
layout::Variants::Tagged { .. } => {
layout::Variants::Tagged { ref discr, .. } => {
let discr_val = dest_ty.ty_adt_def().unwrap()
.discriminant_for_variant(*self.tcx, variant_index)
.val;
// raw discriminants for enums are isize or bigger during
// their computation, but the in-memory tag is the smallest possible
// representation
let size = discr.value.size(self.tcx.tcx).bits();
let amt = 128 - size;
let discr_val = (discr_val << amt) >> amt;
let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?;
}
@ -1145,19 +1179,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
_ if primval.is_undef() => false,
_ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
};
self.memory.write_primval(dest.to_ptr()?, dest_align, primval, layout.size.bytes(), signed)
self.memory.write_primval(dest, dest_align, primval, layout.size.bytes(), signed)
}
Value::ByValPair(a_val, b_val) => {
let ptr = dest.to_ptr()?;
trace!("write_value_to_ptr valpair: {:#?}", layout);
let (a, b) = match layout.abi {
layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
_ => bug!("write_value_to_ptr: invalid ByValPair layout: {:#?}", layout)
};
let (a_size, b_size) = (a.size(&self), b.size(&self));
let a_ptr = ptr;
let a_ptr = dest;
let b_offset = a_size.abi_align(b.align(&self));
let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into();
let b_ptr = dest.offset(b_offset.bytes(), &self)?.into();
// TODO: What about signedess?
self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?;
self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false)

View File

@ -691,7 +691,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
self.read_primval(ptr, ptr_align, self.pointer_size())
}
pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
let endianness = self.endianness();
let bytes = match val {
@ -703,11 +703,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
PrimVal::Bytes(bytes) => bytes,
PrimVal::Undef => {
self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?;
self.check_align(ptr.into(), ptr_align)?;
self.mark_definedness(ptr, size, false)?;
return Ok(());
}
};
let ptr = ptr.to_ptr()?;
{
let align = self.int_align(size);
let dst = self.get_bytes_mut(ptr, size, ptr_align.min(align))?;
@ -734,7 +737,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal) -> EvalResult<'tcx> {
let ptr_size = self.pointer_size();
self.write_primval(ptr, ptr_align, val, ptr_size, false)
self.write_primval(ptr.into(), ptr_align, val, ptr_size, false)
}
fn int_align(&self, size: u64) -> Align {

View File

@ -25,7 +25,7 @@ pub use self::const_eval::{
CompileTimeEvaluator,
const_eval_provider,
const_val_field,
const_discr,
const_variant_index,
};
pub use self::machine::Machine;

View File

@ -37,7 +37,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
ref targets,
..
} => {
// FIXME(CTFE): forbid branching
let discr_val = self.eval_operand(discr)?;
let discr_prim = self.value_to_primval(discr_val)?;
@ -45,8 +44,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
let mut target_block = targets[targets.len() - 1];
for (index, &const_int) in values.iter().enumerate() {
let prim = PrimVal::Bytes(const_int);
if discr_prim.to_bytes()? == prim.to_bytes()? {
if discr_prim.to_bytes()? == const_int {
target_block = targets[index];
break;
}

@ -1 +1 @@
Subproject commit d4712ca37500f26bbcbf97edcb27820717f769f7
Subproject commit f48fed70d4447445b586a35c4ae88683542ffc72