Auto merge of #49933 - oli-obk:miri_rustup, r=eddyb
Fix the miri tool r? @eddyb cc @bjorn3 fixes #49777
This commit is contained in:
commit
f5203d1073
15
src/Cargo.lock
generated
15
src/Cargo.lock
generated
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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),
|
||||
|
@ -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>(
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user