Skip to content

Commit 3084c06

Browse files
committed
Fix the miri tool
1 parent f5cf1a8 commit 3084c06

File tree

9 files changed

+80
-84
lines changed

9 files changed

+80
-84
lines changed

src/Cargo.lock

+3-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ci/docker/x86_64-gnu-tools/checktools.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ verify_status rust-by-example src/doc/rust-by-example
6767
verify_status rls src/tool/rls
6868
verify_status rustfmt src/tool/rustfmt
6969
verify_status clippy-driver src/tool/clippy
70-
#verify_status miri src/tool/miri
70+
verify_status miri src/tool/miri
7171

7272
if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
7373
. "$(dirname $0)/repo.sh"

src/librustc_mir/hair/pattern/mod.rs

+3-32
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod check_match;
1616
pub use self::check_match::check_crate;
1717
pub(crate) use self::check_match::check_match;
1818

19-
use interpret::{const_val_field, const_discr, self};
19+
use interpret::{const_val_field, const_variant_index, self};
2020

2121
use rustc::middle::const_val::ConstVal;
2222
use rustc::mir::{Field, BorrowKind, Mutability};
@@ -835,38 +835,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
835835
ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
836836
match cv.val {
837837
ConstVal::Value(val) => {
838-
let discr_val = const_discr(
838+
let variant_index = const_variant_index(
839839
self.tcx, self.param_env, instance, val, cv.ty
840-
).expect("const_discr failed");
841-
let layout = self
842-
.tcx
843-
.layout_of(self.param_env.and(cv.ty))
844-
.expect("layout of enum not available");
845-
let variant_index = match layout.variants {
846-
ty::layout::Variants::Single { index } => index,
847-
ty::layout::Variants::Tagged { ref discr, .. } => {
848-
// raw discriminants for enums are isize or bigger during
849-
// their computation, but later shrunk to the smallest possible
850-
// representation
851-
let size = discr.value.size(self.tcx).bits();
852-
let amt = 128 - size;
853-
adt_def
854-
.discriminants(self.tcx)
855-
.position(|var| ((var.val << amt) >> amt) == discr_val)
856-
.unwrap_or_else(|| {
857-
bug!("discriminant {} not found in {:#?}",
858-
discr_val,
859-
adt_def
860-
.discriminants(self.tcx)
861-
.collect::<Vec<_>>(),
862-
);
863-
})
864-
}
865-
ty::layout::Variants::NicheFilling { .. } => {
866-
assert_eq!(discr_val as usize as u128, discr_val);
867-
discr_val as usize
868-
},
869-
};
840+
).expect("const_variant_index failed");
870841
let subpatterns = adt_subpatterns(
871842
adt_def.variants[variant_index].fields.len(),
872843
Some(variant_index),

src/librustc_mir/interpret/const_eval.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -400,14 +400,14 @@ pub fn const_val_field<'a, 'tcx>(
400400
}
401401
}
402402

403-
pub fn const_discr<'a, 'tcx>(
403+
pub fn const_variant_index<'a, 'tcx>(
404404
tcx: TyCtxt<'a, 'tcx, 'tcx>,
405405
param_env: ty::ParamEnv<'tcx>,
406406
instance: ty::Instance<'tcx>,
407407
value: Value,
408408
ty: Ty<'tcx>,
409-
) -> EvalResult<'tcx, u128> {
410-
trace!("const_discr: {:?}, {:?}, {:?}", instance, value, ty);
409+
) -> EvalResult<'tcx, usize> {
410+
trace!("const_variant_index: {:?}, {:?}, {:?}", instance, value, ty);
411411
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
412412
let (ptr, align) = match value {
413413
Value::ByValPair(..) | Value::ByVal(_) => {
@@ -421,7 +421,7 @@ pub fn const_discr<'a, 'tcx>(
421421
Value::ByRef(ptr, align) => (ptr, align),
422422
};
423423
let place = Place::from_primval_ptr(ptr, align);
424-
ecx.read_discriminant_value(place, ty)
424+
ecx.read_discriminant_as_variant_index(place, ty)
425425
}
426426

427427
pub fn const_eval_provider<'a, 'tcx>(

src/librustc_mir/interpret/eval_context.rs

+60-27
Original file line numberDiff line numberDiff line change
@@ -743,28 +743,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
743743

744744
Discriminant(ref place) => {
745745
let ty = self.place_ty(place);
746-
let layout = self.layout_of(ty)?;
747746
let place = self.eval_place(place)?;
748747
let discr_val = self.read_discriminant_value(place, ty)?;
749-
match layout.variants {
750-
layout::Variants::Single { index } => {
751-
assert_eq!(discr_val, index as u128);
752-
}
753-
layout::Variants::Tagged { .. } |
754-
layout::Variants::NicheFilling { .. } => {
755-
if let ty::TyAdt(adt_def, _) = ty.sty {
756-
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>());
757-
if adt_def.discriminants(*self.tcx).all(|v| {
758-
discr_val != v.val
759-
})
760-
{
761-
return err!(InvalidDiscriminant);
762-
}
763-
} else {
764-
bug!("rustc only generates Rvalue::Discriminant for enums");
765-
}
766-
}
767-
}
768748
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
769749
}
770750
}
@@ -837,13 +817,39 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
837817
}
838818
}
839819

820+
/// reads a tag and produces the corresponding variant index
821+
pub fn read_discriminant_as_variant_index(
822+
&mut self,
823+
place: Place,
824+
ty: Ty<'tcx>,
825+
) -> EvalResult<'tcx, usize> {
826+
let layout = self.layout_of(ty)?;
827+
match layout.variants {
828+
ty::layout::Variants::Single { index } => Ok(index),
829+
ty::layout::Variants::Tagged { .. } => {
830+
let discr_val = self.read_discriminant_value(place, ty)?;
831+
ty
832+
.ty_adt_def()
833+
.expect("tagged layout for non adt")
834+
.discriminants(self.tcx.tcx)
835+
.position(|var| var.val == discr_val)
836+
.ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into())
837+
}
838+
ty::layout::Variants::NicheFilling { .. } => {
839+
let discr_val = self.read_discriminant_value(place, ty)?;
840+
assert_eq!(discr_val as usize as u128, discr_val);
841+
Ok(discr_val as usize)
842+
},
843+
}
844+
}
845+
840846
pub fn read_discriminant_value(
841847
&mut self,
842848
place: Place,
843849
ty: Ty<'tcx>,
844850
) -> EvalResult<'tcx, u128> {
845851
let layout = self.layout_of(ty)?;
846-
//trace!("read_discriminant_value {:#?}", layout);
852+
trace!("read_discriminant_value {:#?}", layout);
847853

848854
match layout.variants {
849855
layout::Variants::Single { index } => {
@@ -854,13 +860,34 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
854860
}
855861

856862
let (discr_place, discr) = self.place_field(place, mir::Field::new(0), layout)?;
863+
trace!("discr place: {:?}, {:?}", discr_place, discr);
857864
let raw_discr = self.value_to_primval(ValTy {
858865
value: self.read_place(discr_place)?,
859866
ty: discr.ty
860867
})?;
861868
let discr_val = match layout.variants {
862869
layout::Variants::Single { .. } => bug!(),
863-
layout::Variants::Tagged { .. } => raw_discr.to_bytes()?,
870+
// FIXME: should we catch invalid discriminants here?
871+
layout::Variants::Tagged { .. } => {
872+
if discr.ty.is_signed() {
873+
let i = raw_discr.to_bytes()? as i128;
874+
// going from layout tag type to typeck discriminant type
875+
// requires first sign extending with the layout discriminant
876+
let amt = 128 - discr.size.bits();
877+
let sexted = (i << amt) >> amt;
878+
// and then zeroing with the typeck discriminant type
879+
let discr_ty = ty
880+
.ty_adt_def().expect("tagged layout corresponds to adt")
881+
.repr
882+
.discr_type();
883+
let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty);
884+
let amt = 128 - discr_ty.size().bits();
885+
let truncatee = sexted as u128;
886+
(truncatee << amt) >> amt
887+
} else {
888+
raw_discr.to_bytes()?
889+
}
890+
},
864891
layout::Variants::NicheFilling {
865892
dataful_variant,
866893
ref niche_variants,
@@ -910,11 +937,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
910937
layout::Abi::Uninhabited);
911938
}
912939
}
913-
layout::Variants::Tagged { .. } => {
940+
layout::Variants::Tagged { ref discr, .. } => {
914941
let discr_val = dest_ty.ty_adt_def().unwrap()
915942
.discriminant_for_variant(*self.tcx, variant_index)
916943
.val;
917944

945+
// raw discriminants for enums are isize or bigger during
946+
// their computation, but the in-memory tag is the smallest possible
947+
// representation
948+
let size = discr.value.size(self.tcx.tcx).bits();
949+
let amt = 128 - size;
950+
let discr_val = (discr_val << amt) >> amt;
951+
918952
let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
919953
self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?;
920954
}
@@ -1145,19 +1179,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
11451179
_ if primval.is_undef() => false,
11461180
_ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
11471181
};
1148-
self.memory.write_primval(dest.to_ptr()?, dest_align, primval, layout.size.bytes(), signed)
1182+
self.memory.write_primval(dest, dest_align, primval, layout.size.bytes(), signed)
11491183
}
11501184
Value::ByValPair(a_val, b_val) => {
1151-
let ptr = dest.to_ptr()?;
11521185
trace!("write_value_to_ptr valpair: {:#?}", layout);
11531186
let (a, b) = match layout.abi {
11541187
layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
11551188
_ => bug!("write_value_to_ptr: invalid ByValPair layout: {:#?}", layout)
11561189
};
11571190
let (a_size, b_size) = (a.size(&self), b.size(&self));
1158-
let a_ptr = ptr;
1191+
let a_ptr = dest;
11591192
let b_offset = a_size.abi_align(b.align(&self));
1160-
let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into();
1193+
let b_ptr = dest.offset(b_offset.bytes(), &self)?.into();
11611194
// TODO: What about signedess?
11621195
self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?;
11631196
self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false)

src/librustc_mir/interpret/memory.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
691691
self.read_primval(ptr, ptr_align, self.pointer_size())
692692
}
693693

694-
pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
694+
pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
695695
let endianness = self.endianness();
696696

697697
let bytes = match val {
@@ -703,11 +703,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
703703
PrimVal::Bytes(bytes) => bytes,
704704

705705
PrimVal::Undef => {
706-
self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?;
706+
self.check_align(ptr.into(), ptr_align)?;
707+
self.mark_definedness(ptr, size, false)?;
707708
return Ok(());
708709
}
709710
};
710711

712+
let ptr = ptr.to_ptr()?;
713+
711714
{
712715
let align = self.int_align(size);
713716
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> {
734737

735738
pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal) -> EvalResult<'tcx> {
736739
let ptr_size = self.pointer_size();
737-
self.write_primval(ptr, ptr_align, val, ptr_size, false)
740+
self.write_primval(ptr.into(), ptr_align, val, ptr_size, false)
738741
}
739742

740743
fn int_align(&self, size: u64) -> Align {

src/librustc_mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub use self::const_eval::{
2525
CompileTimeEvaluator,
2626
const_eval_provider,
2727
const_val_field,
28-
const_discr,
28+
const_variant_index,
2929
};
3030

3131
pub use self::machine::Machine;

src/librustc_mir/interpret/terminator/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
3737
ref targets,
3838
..
3939
} => {
40-
// FIXME(CTFE): forbid branching
4140
let discr_val = self.eval_operand(discr)?;
4241
let discr_prim = self.value_to_primval(discr_val)?;
4342

4443
// Branch to the `otherwise` case by default, if no match is found.
4544
let mut target_block = targets[targets.len() - 1];
4645

4746
for (index, &const_int) in values.iter().enumerate() {
48-
let prim = PrimVal::Bytes(const_int);
49-
if discr_prim.to_bytes()? == prim.to_bytes()? {
47+
if discr_prim.to_bytes()? == const_int {
5048
target_block = targets[index];
5149
break;
5250
}

src/tools/miri

Submodule miri updated from d4712ca to f48fed7

0 commit comments

Comments
 (0)