From 3084c066e408f7a2921b02a16f115bb4833c71de Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 13 Apr 2018 16:05:54 +0200 Subject: [PATCH] Fix the miri tool --- src/Cargo.lock | 15 +--- src/ci/docker/x86_64-gnu-tools/checktools.sh | 2 +- src/librustc_mir/hair/pattern/mod.rs | 35 +------- src/librustc_mir/interpret/const_eval.rs | 8 +- src/librustc_mir/interpret/eval_context.rs | 87 ++++++++++++++------ src/librustc_mir/interpret/memory.rs | 9 +- src/librustc_mir/interpret/mod.rs | 2 +- src/librustc_mir/interpret/terminator/mod.rs | 4 +- src/tools/miri | 2 +- 9 files changed, 80 insertions(+), 84 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index d60a8689f3da1..5fd8334e8ed9a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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" diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index da89aa9423b2d..3fed0175371a7 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -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" diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 9f17af8b16f1d..c2da8c11d87e9 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -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::>(), - ); - }) - } - 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), diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 954a3dbe5b9ab..6d131501865bd 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -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>( diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index a5ddd50ae10c5..b98ab218de5cb 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -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::>()); - 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) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index dcf97f61545db..5e156e9271f57 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -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 { diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 147db3bdc0e7a..2a690af036871 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -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; diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index 851fac532e366..3360e5b72a7c7 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -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; } diff --git a/src/tools/miri b/src/tools/miri index d4712ca37500f..f48fed70d4447 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit d4712ca37500f26bbcbf97edcb27820717f769f7 +Subproject commit f48fed70d4447445b586a35c4ae88683542ffc72