From 85397286071c7971aded6b2c987aaa7f507d2312 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Aug 2017 14:41:59 +0200 Subject: [PATCH 01/10] memory: make sure we check non-NULL/undef even fore 0-sized accesses --- miri/intrinsic.rs | 4 +- src/librustc_mir/interpret/memory.rs | 83 ++++++++++++------------ src/librustc_mir/interpret/mod.rs | 4 +- src/librustc_mir/interpret/validation.rs | 2 +- tests/compile-fail/null_pointer_deref.rs | 2 +- tests/compile-fail/wild_pointer_deref.rs | 2 +- 6 files changed, 47 insertions(+), 50 deletions(-) diff --git a/miri/intrinsic.rs b/miri/intrinsic.rs index 3e04f8598716..8c722a46ae30 100644 --- a/miri/intrinsic.rs +++ b/miri/intrinsic.rs @@ -4,7 +4,7 @@ use rustc::ty::layout::Layout; use rustc::ty::{self, Ty}; use rustc_miri::interpret::{EvalResult, Lvalue, LvalueExtra, PrimVal, PrimValKind, Value, Pointer, - HasMemory, EvalContext, PtrAndAlign, ValTy}; + HasMemory, AccessKind, EvalContext, PtrAndAlign, ValTy}; use helpers::EvalContextExt as HelperEvalContextExt; @@ -624,7 +624,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> if count > 0 { // HashMap relies on write_bytes on a NULL ptr with count == 0 to work // TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic) - self.memory.check_align(ptr, ty_align)?; + self.memory.check_align(ptr, ty_align, Some(AccessKind::Write))?; self.memory.write_repeat(ptr, val_byte, size * count)?; } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9930555c199d..8c7a36f866da 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -3,7 +3,7 @@ use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; use std::{fmt, iter, ptr, mem, io}; use std::cell::Cell; -use rustc::ty; +use rustc::ty::Instance; use rustc::ty::layout::{self, TargetDataLayout, HasDataLayout}; use syntax::ast::Mutability; use rustc::middle::region::CodeExtent; @@ -250,10 +250,10 @@ pub struct Memory<'a, 'tcx, M: Machine<'tcx>> { /// Function "allocations". They exist solely so pointers have something to point to, and /// we can figure out what they point to. - functions: Vec>, + functions: Vec>, /// Inverse map of `functions` so we don't allocate a new pointer every time we need one - function_alloc_cache: HashMap, AllocId>, + function_alloc_cache: HashMap, AllocId>, /// Target machine data layout to emulate. pub layout: &'a TargetDataLayout, @@ -297,7 +297,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { }) } - pub fn create_fn_alloc(&mut self, instance: ty::Instance<'tcx>) -> MemoryPointer { + pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer { if let Some(&alloc_id) = self.function_alloc_cache.get(&instance) { return MemoryPointer::new(alloc_id, 0); } @@ -476,27 +476,38 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } /// Check that the pointer is aligned AND non-NULL. - pub fn check_align(&self, ptr: Pointer, align: u64) -> EvalResult<'tcx> { - let offset = match ptr.into_inner_primval() { + pub fn check_align(&self, ptr: Pointer, align: u64, access: Option) -> EvalResult<'tcx> { + // Check non-NULL/Undef, extract offset + let (offset, alloc_align) = match ptr.into_inner_primval() { PrimVal::Ptr(ptr) => { let alloc = self.get(ptr.alloc_id)?; - if alloc.align < align { - return err!(AlignmentCheckFailed { - has: alloc.align, - required: align, - }); - } - ptr.offset + (ptr.offset, alloc.align) } PrimVal::Bytes(bytes) => { let v = ((bytes as u128) % (1 << self.pointer_size())) as u64; if v == 0 { return err!(InvalidNullPointerUsage); } - v + (v, align) // the base address if the "integer allocation" is 0 and hence always aligned } PrimVal::Undef => return err!(ReadUndefBytes), }; + // See if alignment checking is disabled + let enforce_alignment = match access { + Some(AccessKind::Read) => self.reads_are_aligned.get(), + Some(AccessKind::Write) => self.writes_are_aligned.get(), + None => true, + }; + if !enforce_alignment { + return Ok(()); + } + // Check alignment + if alloc_align < align { + return err!(AlignmentCheckFailed { + has: alloc_align, + required: align, + }); + } if offset % align == 0 { Ok(()) } else { @@ -804,7 +815,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } } - pub fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation> { + fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation> { let alloc = self.get_mut_unchecked(id)?; if alloc.mutable == Mutability::Mutable { Ok(alloc) @@ -813,7 +824,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } } - pub fn get_fn(&self, ptr: MemoryPointer) -> EvalResult<'tcx, ty::Instance<'tcx>> { + pub fn get_fn(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Instance<'tcx>> { if ptr.offset != 0 { return err!(InvalidFunctionPointer); } @@ -933,9 +944,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { align: u64, ) -> EvalResult<'tcx, &[u8]> { // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL - if self.reads_are_aligned.get() { - self.check_align(ptr.into(), align)?; - } + self.check_align(ptr.into(), align, Some(AccessKind::Read))?; if size == 0 { return Ok(&[]); } @@ -955,9 +964,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { align: u64, ) -> EvalResult<'tcx, &mut [u8]> { // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL - if self.writes_are_aligned.get() { - self.check_align(ptr.into(), align)?; - } + self.check_align(ptr.into(), align, Some(AccessKind::Write))?; if size == 0 { return Ok(&mut []); } @@ -995,7 +1002,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { /// Reading and writing impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { /// mark an allocation pointed to by a static as static and initialized - pub fn mark_inner_allocation( + fn mark_inner_allocation_initialized( &mut self, alloc: AllocId, mutability: Mutability, @@ -1056,7 +1063,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { }; // recurse into inner allocations for &alloc in relocations.values() { - self.mark_inner_allocation(alloc, mutability)?; + self.mark_inner_allocation_initialized(alloc, mutability)?; } // put back the relocations self.alloc_map @@ -1074,14 +1081,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { align: u64, nonoverlapping: bool, ) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be aligned + self.check_align(src, align, Some(AccessKind::Read))?; + self.check_align(dest, align, Some(AccessKind::Write))?; if size == 0 { - // Empty accesses don't need to be valid pointers, but they should still be aligned - if self.reads_are_aligned.get() { - self.check_align(src, align)?; - } - if self.writes_are_aligned.get() { - self.check_align(dest, align)?; - } return Ok(()); } let src = src.to_ptr()?; @@ -1136,22 +1139,18 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + self.check_align(ptr, 1, Some(AccessKind::Read))?; if size == 0 { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.reads_are_aligned.get() { - self.check_align(ptr, 1)?; - } return Ok(&[]); } self.get_bytes(ptr.to_ptr()?, size, 1) } pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + self.check_align(ptr, 1, Some(AccessKind::Write))?; if src.is_empty() { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.writes_are_aligned.get() { - self.check_align(ptr, 1)?; - } return Ok(()); } let bytes = self.get_bytes_mut(ptr.to_ptr()?, src.len() as u64, 1)?; @@ -1160,11 +1159,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> { + // Empty accesses don't need to be valid pointers, but they should still be non-NULL + self.check_align(ptr, 1, Some(AccessKind::Write))?; if count == 0 { - // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.writes_are_aligned.get() { - self.check_align(ptr, 1)?; - } return Ok(()); } let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, 1)?; diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 3a5fdf273a48..634b8a0eeb8a 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -27,9 +27,9 @@ pub use self::eval_context::{EvalContext, Frame, ResourceLimits, StackPopCleanup pub use self::lvalue::{Lvalue, LvalueExtra, GlobalId}; -pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory}; +pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory, AccessKind}; -use self::memory::{PointerArithmetic, Lock, AccessKind}; +use self::memory::{PointerArithmetic, Lock}; use self::range_map::RangeMap; diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs index 20b601b538c4..6454e12e037f 100644 --- a/src/librustc_mir/interpret/validation.rs +++ b/src/librustc_mir/interpret/validation.rs @@ -275,7 +275,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { // Check alignment and non-NULLness let (_, align) = self.size_and_align_of_dst(pointee_ty, val)?; let ptr = val.into_ptr(&self.memory)?; - self.memory.check_align(ptr, align)?; + self.memory.check_align(ptr, align, None)?; // Recurse let pointee_lvalue = self.val_to_lvalue(val, pointee_ty)?; diff --git a/tests/compile-fail/null_pointer_deref.rs b/tests/compile-fail/null_pointer_deref.rs index 20b93aab1607..5a26856eba08 100644 --- a/tests/compile-fail/null_pointer_deref.rs +++ b/tests/compile-fail/null_pointer_deref.rs @@ -1,4 +1,4 @@ fn main() { - let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: a memory access tried to interpret some bytes as a pointer + let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: invalid use of NULL pointer panic!("this should never print: {}", x); } diff --git a/tests/compile-fail/wild_pointer_deref.rs b/tests/compile-fail/wild_pointer_deref.rs index 373e308e1c02..57da8dfc01b2 100644 --- a/tests/compile-fail/wild_pointer_deref.rs +++ b/tests/compile-fail/wild_pointer_deref.rs @@ -1,5 +1,5 @@ fn main() { - let p = 42 as *const i32; + let p = 44 as *const i32; let x = unsafe { *p }; //~ ERROR: a memory access tried to interpret some bytes as a pointer panic!("this should never print: {}", x); } From f036fe0d32a077a8d69f20c876389779e88e3ea5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Aug 2017 16:20:13 +0200 Subject: [PATCH 02/10] refactor memory read API: provide only size-based, no type-based methods --- src/librustc_mir/interpret/cast.rs | 1 + src/librustc_mir/interpret/eval_context.rs | 143 ++++++++++++++----- src/librustc_mir/interpret/memory.rs | 61 ++++---- src/librustc_mir/interpret/terminator/mod.rs | 109 +------------- src/librustc_mir/interpret/traits.rs | 8 +- src/librustc_mir/interpret/value.rs | 22 +-- tests/run-pass-fullmir/integer-ops.rs | 4 + 7 files changed, 164 insertions(+), 184 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index c6016509d238..2f45347d113c 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -10,6 +10,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { src_ty: Ty<'tcx>, dest_ty: Ty<'tcx>, ) -> EvalResult<'tcx, PrimVal> { + trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty); let src_kind = self.ty_to_primval_kind(src_ty)?; match val { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9fbc32c4f005..1841e1554056 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -998,16 +998,17 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { let ptr = self.force_allocation(lval)?.to_ptr()?; let discr_val = self.read_discriminant_value(ptr, ty)?; 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.to_u128_unchecked() }) { return err!(InvalidDiscriminant); } + self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } else { bug!("rustc only generates Rvalue::Discriminant for enums"); } - self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } } @@ -1295,6 +1296,96 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } } + pub fn read_discriminant_value( + &self, + adt_ptr: MemoryPointer, + adt_ty: Ty<'tcx>, + ) -> EvalResult<'tcx, u128> { + use rustc::ty::layout::Layout::*; + let adt_layout = self.type_layout(adt_ty)?; + //trace!("read_discriminant_value {:#?}", adt_layout); + + let discr_val = match *adt_layout { + General { discr, .. } => { + let discr_size = discr.size().bytes(); + self.memory.read_primval(adt_ptr, discr_size, false)?.to_bytes()? + } + + CEnum { + discr, + signed, + .. + } => { + let discr_size = discr.size().bytes(); + self.memory.read_primval(adt_ptr, discr_size, signed)?.to_bytes()? + } + + RawNullablePointer { nndiscr, value } => { + let discr_size = value.size(&self.tcx.data_layout).bytes(); + trace!("rawnullablepointer with size {}", discr_size); + self.read_nonnull_discriminant_value( + adt_ptr, + nndiscr as u128, + discr_size, + )? + } + + StructWrappedNullablePointer { + nndiscr, + ref discrfield_source, + .. + } => { + let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( + adt_ty, + nndiscr, + discrfield_source, + )?; + let nonnull = adt_ptr.offset(offset.bytes(), &*self)?; + trace!("struct wrapped nullable pointer type: {}", ty); + // only the pointer part of a fat pointer is used for this space optimization + let discr_size = self.type_size(ty)?.expect( + "bad StructWrappedNullablePointer discrfield", + ); + self.read_maybe_aligned(!packed, |ectx| { + ectx.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size) + })? + } + + // The discriminant_value intrinsic returns 0 for non-sum types. + Array { .. } | + FatPointer { .. } | + Scalar { .. } | + Univariant { .. } | + Vector { .. } | + UntaggedUnion { .. } => 0, + }; + + Ok(discr_val) + } + + fn read_nonnull_discriminant_value( + &self, + ptr: MemoryPointer, + nndiscr: u128, + discr_size: u64, + ) -> EvalResult<'tcx, u128> { + trace!( + "read_nonnull_discriminant_value: {:?}, {}, {}", + ptr, + nndiscr, + discr_size + ); + // We are only interested in 0 vs. non-0, the sign does not matter for this + let null = match self.memory.read_primval(ptr, discr_size, false)? { + PrimVal::Bytes(0) => true, + PrimVal::Bytes(_) | + PrimVal::Ptr(..) => false, + PrimVal::Undef => return err!(ReadUndefBytes), + }; + assert!(nndiscr == 0 || nndiscr == 1); + Ok(if !null { nndiscr } else { 1 - nndiscr }) + } + pub fn read_global_as_value(&self, gid: GlobalId) -> Value { Value::ByRef(*self.globals.get(&gid).expect("global not cached")) } @@ -1676,18 +1767,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ptr: MemoryPointer, pointee_ty: Ty<'tcx>, ) -> EvalResult<'tcx, Value> { - let p = self.memory.read_ptr(ptr)?; + let ptr_size = self.memory.pointer_size(); + let p : Pointer = self.memory.read_ptr_sized_unsigned(ptr)?.into(); if self.type_is_sized(pointee_ty) { Ok(p.to_value()) } else { trace!("reading fat pointer extra of type {}", pointee_ty); - let extra = ptr.offset(self.memory.pointer_size(), self)?; + let extra = ptr.offset(ptr_size, self)?; match self.tcx.struct_tail(pointee_ty).sty { ty::TyDynamic(..) => Ok(p.to_value_with_vtable( - self.memory.read_ptr(extra)?.to_ptr()?, + self.memory.read_ptr_sized_unsigned(extra)?.to_ptr()?, )), ty::TySlice(..) | ty::TyStr => Ok( - p.to_value_with_len(self.memory.read_usize(extra)?), + p.to_value_with_len(self.memory.read_ptr_sized_unsigned(extra)?.to_bytes()? as u64), ), _ => bug!("unsized primval ptr read from {:?}", pointee_ty), } @@ -1697,10 +1789,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { fn try_read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option> { use syntax::ast::FloatTy; + let ptr = ptr.to_ptr()?; let val = match ty.sty { - ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr.to_ptr()?)?), + ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr)?), ty::TyChar => { - let c = self.memory.read_uint(ptr.to_ptr()?, 4)? as u32; + let c = self.memory.read_primval(ptr, 4, false)?.to_bytes()? as u32; match ::std::char::from_u32(c) { Some(ch) => PrimVal::from_char(ch), None => return err!(InvalidChar(c as u128)), @@ -1717,15 +1810,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { I128 => 16, Is => self.memory.pointer_size(), }; - // if we transmute a ptr to an isize, reading it back into a primval shouldn't panic - // Due to read_ptr ignoring the sign, we need to jump around some hoops - match self.memory.read_int(ptr.to_ptr()?, size) { - Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. }) if size == self.memory.pointer_size() => - // Reading as an int failed because we are seeing ptr bytes *and* we are actually reading at ptr size. - // Let's try again, reading a ptr this time. - self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(), - other => PrimVal::from_i128(other?), - } + self.memory.read_primval(ptr, size, true)? } ty::TyUint(uint_ty) => { @@ -1738,36 +1823,24 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { U128 => 16, Us => self.memory.pointer_size(), }; - // if we transmute a ptr to an usize, reading it back into a primval shouldn't panic - // for consistency's sake, we use the same code as above - match self.memory.read_uint(ptr.to_ptr()?, size) { - Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. }) - if size == self.memory.pointer_size() => { - self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval() - } - other => PrimVal::from_u128(other?), - } + self.memory.read_primval(ptr, size, false)? } - ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr.to_ptr()?)?), - ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr.to_ptr()?)?), + ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?), + ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr)?), - ty::TyFnPtr(_) => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(), + ty::TyFnPtr(_) => self.memory.read_ptr_sized_unsigned(ptr)?, ty::TyRef(_, ref tam) | - ty::TyRawPtr(ref tam) => return self.read_ptr(ptr.to_ptr()?, tam.ty).map(Some), + ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, tam.ty).map(Some), ty::TyAdt(def, _) => { if def.is_box() { - return self.read_ptr(ptr.to_ptr()?, ty.boxed_ty()).map(Some); + return self.read_ptr(ptr, ty.boxed_ty()).map(Some); } use rustc::ty::layout::Layout::*; if let CEnum { discr, signed, .. } = *self.type_layout(ty)? { let size = discr.size().bytes(); - if signed { - PrimVal::from_i128(self.memory.read_int(ptr.to_ptr()?, size)?) - } else { - PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?) - } + self.memory.read_primval(ptr, size, signed)? } else { return Ok(None); } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 8c7a36f866da..d24f469de405 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1171,24 +1171,39 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { Ok(()) } - pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Pointer> { - let size = self.pointer_size(); + pub fn read_primval(&self, ptr: MemoryPointer, size: u64, signed: bool) -> EvalResult<'tcx, PrimVal> { self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer let endianess = self.endianess(); - let bytes = self.get_bytes_unchecked(ptr, size, size)?; + let bytes = self.get_bytes_unchecked(ptr, size, self.int_align(size)?)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { return Ok(PrimVal::Undef.into()); } - let offset = read_target_uint(endianess, bytes).unwrap(); - assert_eq!(offset as u64 as u128, offset); - let offset = offset as u64; - let alloc = self.get(ptr.alloc_id)?; - match alloc.relocations.get(&ptr.offset) { - Some(&alloc_id) => Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, offset)).into()), - None => Ok(PrimVal::Bytes(offset as u128).into()), + // Now we do the actual reading + let bytes = if signed { + read_target_int(endianess, bytes).unwrap() as u128 + } else { + read_target_uint(endianess, bytes).unwrap() + }; + // See if we got a pointer + if size != self.pointer_size() { + if self.relocations(ptr, size)?.count() != 0 { + return err!(ReadPointerAsBytes); + } + } else { + let alloc = self.get(ptr.alloc_id)?; + match alloc.relocations.get(&ptr.offset) { + Some(&alloc_id) => return Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, bytes as u64))), + None => {}, + } } + // We don't. Just return the bytes. + Ok(PrimVal::Bytes(bytes)) + } + + pub fn read_ptr_sized_unsigned(&self, ptr: MemoryPointer) -> EvalResult<'tcx, PrimVal> { + self.read_primval(ptr, self.pointer_size(), false) } pub fn write_ptr(&mut self, dest: MemoryPointer, ptr: MemoryPointer) -> EvalResult<'tcx> { @@ -1242,6 +1257,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> { + // We assume pointer-sized integers have the same alignment as pointers. + // We also assume singed and unsigned integers of the same size have the same alignment. match size { 1 => Ok(self.layout.i8_align.abi()), 2 => Ok(self.layout.i16_align.abi()), @@ -1252,13 +1269,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } } - pub fn read_int(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx, i128> { - let align = self.int_align(size)?; - self.get_bytes(ptr, size, align).map(|b| { - read_target_int(self.endianess(), b).unwrap() - }) - } - pub fn write_int(&mut self, ptr: MemoryPointer, n: i128, size: u64) -> EvalResult<'tcx> { let align = self.int_align(size)?; let endianess = self.endianess(); @@ -1267,13 +1277,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { Ok(()) } - pub fn read_uint(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx, u128> { - let align = self.int_align(size)?; - self.get_bytes(ptr, size, align).map(|b| { - read_target_uint(self.endianess(), b).unwrap() - }) - } - pub fn write_uint(&mut self, ptr: MemoryPointer, n: u128, size: u64) -> EvalResult<'tcx> { let align = self.int_align(size)?; let endianess = self.endianess(); @@ -1282,19 +1285,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { Ok(()) } - pub fn read_isize(&self, ptr: MemoryPointer) -> EvalResult<'tcx, i64> { - self.read_int(ptr, self.pointer_size()).map(|i| i as i64) - } - pub fn write_isize(&mut self, ptr: MemoryPointer, n: i64) -> EvalResult<'tcx> { let size = self.pointer_size(); self.write_int(ptr, n as i128, size) } - pub fn read_usize(&self, ptr: MemoryPointer) -> EvalResult<'tcx, u64> { - self.read_uint(ptr, self.pointer_size()).map(|i| i as u64) - } - pub fn write_usize(&mut self, ptr: MemoryPointer, n: u64) -> EvalResult<'tcx> { let size = self.pointer_size(); self.write_uint(ptr, n as u128, size) @@ -1494,6 +1489,7 @@ fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result source.read_uint128::(source.len()), } } + fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result { match endianess { layout::Endian::Little => source.read_int128::(source.len()), @@ -1501,6 +1497,7 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result> EvalContext<'a, 'tcx, M> { ty::InstanceDef::Virtual(_, idx) => { let ptr_size = self.memory.pointer_size(); let (ptr, vtable) = args[0].into_ptr_vtable_pair(&self.memory)?; - let fn_ptr = self.memory.read_ptr( - vtable.offset(ptr_size * (idx as u64 + 3), &self)?, - )?; - let instance = self.memory.get_fn(fn_ptr.to_ptr()?)?; + let fn_ptr = self.memory.read_ptr_sized_unsigned( + vtable.offset(ptr_size * (idx as u64 + 3), &self)? + )?.to_ptr()?; + let instance = self.memory.get_fn(fn_ptr)?; let mut args = args.to_vec(); let ty = self.get_field_ty(args[0].ty, 0)?.ty; // TODO: packed flag is ignored args[0].ty = ty; @@ -408,98 +407,4 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } } } - - pub fn read_discriminant_value( - &self, - adt_ptr: MemoryPointer, - adt_ty: Ty<'tcx>, - ) -> EvalResult<'tcx, u128> { - use rustc::ty::layout::Layout::*; - let adt_layout = self.type_layout(adt_ty)?; - //trace!("read_discriminant_value {:#?}", adt_layout); - - let discr_val = match *adt_layout { - General { discr, .. } | - CEnum { - discr, - signed: false, - .. - } => { - let discr_size = discr.size().bytes(); - self.memory.read_uint(adt_ptr, discr_size)? - } - - CEnum { - discr, - signed: true, - .. - } => { - let discr_size = discr.size().bytes(); - self.memory.read_int(adt_ptr, discr_size)? as u128 - } - - RawNullablePointer { nndiscr, value } => { - let discr_size = value.size(&self.tcx.data_layout).bytes(); - trace!("rawnullablepointer with size {}", discr_size); - self.read_nonnull_discriminant_value( - adt_ptr, - nndiscr as u128, - discr_size, - )? - } - - StructWrappedNullablePointer { - nndiscr, - ref discrfield_source, - .. - } => { - let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( - adt_ty, - nndiscr, - discrfield_source, - )?; - let nonnull = adt_ptr.offset(offset.bytes(), &*self)?; - trace!("struct wrapped nullable pointer type: {}", ty); - // only the pointer part of a fat pointer is used for this space optimization - let discr_size = self.type_size(ty)?.expect( - "bad StructWrappedNullablePointer discrfield", - ); - self.read_maybe_aligned(!packed, |ectx| { - ectx.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size) - })? - } - - // The discriminant_value intrinsic returns 0 for non-sum types. - Array { .. } | - FatPointer { .. } | - Scalar { .. } | - Univariant { .. } | - Vector { .. } | - UntaggedUnion { .. } => 0, - }; - - Ok(discr_val) - } - - fn read_nonnull_discriminant_value( - &self, - ptr: MemoryPointer, - nndiscr: u128, - discr_size: u64, - ) -> EvalResult<'tcx, u128> { - trace!( - "read_nonnull_discriminant_value: {:?}, {}, {}", - ptr, - nndiscr, - discr_size - ); - let not_null = match self.memory.read_uint(ptr, discr_size) { - Ok(0) => false, - Ok(_) | - Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. }) => true, - Err(e) => return Err(e), - }; - assert!(nndiscr == 0 || nndiscr == 1); - Ok(if not_null { nndiscr } else { 1 - nndiscr }) - } } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 07d7de854b99..284e9811c9fd 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -105,10 +105,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { vtable: MemoryPointer, ) -> EvalResult<'tcx, (u64, u64)> { let pointer_size = self.memory.pointer_size(); - let size = self.memory.read_usize(vtable.offset(pointer_size, self)?)?; - let align = self.memory.read_usize( - vtable.offset(pointer_size * 2, self)?, - )?; + let size = self.memory.read_ptr_sized_unsigned(vtable.offset(pointer_size, self)?)?.to_bytes()? as u64; + let align = self.memory.read_ptr_sized_unsigned( + vtable.offset(pointer_size * 2, self)? + )?.to_bytes()? as u64; Ok((size, align)) } diff --git a/src/librustc_mir/interpret/value.rs b/src/librustc_mir/interpret/value.rs index 8abb0b86bf8f..e052ec1e391c 100644 --- a/src/librustc_mir/interpret/value.rs +++ b/src/librustc_mir/interpret/value.rs @@ -176,13 +176,13 @@ impl<'a, 'tcx: 'a> Value { mem: &Memory<'a, 'tcx, M>, ) -> EvalResult<'tcx, Pointer> { use self::Value::*; - match *self { + Ok(match *self { ByRef(PtrAndAlign { ptr, aligned }) => { - mem.read_maybe_aligned(aligned, |mem| mem.read_ptr(ptr.to_ptr()?)) + mem.read_maybe_aligned(aligned, |mem| mem.read_ptr_sized_unsigned(ptr.to_ptr()?))? } ByVal(ptr) | - ByValPair(ptr, _) => Ok(ptr.into()), - } + ByValPair(ptr, _) => ptr, + }.into()) } pub(super) fn into_ptr_vtable_pair>( @@ -196,11 +196,11 @@ impl<'a, 'tcx: 'a> Value { aligned, }) => { mem.read_maybe_aligned(aligned, |mem| { - let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?; - let vtable = mem.read_ptr( + let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into(); + let vtable = mem.read_ptr_sized_unsigned( ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?, - )?; - Ok((ptr, vtable.to_ptr()?)) + )?.to_ptr()?; + Ok((ptr, vtable)) }) } @@ -222,10 +222,10 @@ impl<'a, 'tcx: 'a> Value { aligned, }) => { mem.read_maybe_aligned(aligned, |mem| { - let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?; - let len = mem.read_usize( + let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into(); + let len = mem.read_ptr_sized_unsigned( ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?, - )?; + )?.to_bytes()? as u64; Ok((ptr, len)) }) } diff --git a/tests/run-pass-fullmir/integer-ops.rs b/tests/run-pass-fullmir/integer-ops.rs index e761cdd6237c..0964b1b32b5c 100644 --- a/tests/run-pass-fullmir/integer-ops.rs +++ b/tests/run-pass-fullmir/integer-ops.rs @@ -14,6 +14,10 @@ use std::i32; pub fn main() { + // This tests that do (not) do sign extension properly when loading integers + assert_eq!(u32::max_value() as i64, 4294967295); + assert_eq!(i32::min_value() as i64, -2147483648); + assert_eq!(i8::min_value(), -128); assert_eq!(i8::max_value(), 127); From b1ca65447a0134f9431417e1bd5a4325b9a22dd2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Aug 2017 18:25:05 +0200 Subject: [PATCH 03/10] refactor memory write API to match read API --- miri/fn_call.rs | 6 +- src/librustc_mir/interpret/eval_context.rs | 27 ++++++-- src/librustc_mir/interpret/memory.rs | 79 +++++++++++----------- src/librustc_mir/interpret/step.rs | 13 ++-- src/librustc_mir/interpret/traits.rs | 8 +-- 5 files changed, 76 insertions(+), 57 deletions(-) diff --git a/miri/fn_call.rs b/miri/fn_call.rs index cb7ee73e9961..7dc8f54849f0 100644 --- a/miri/fn_call.rs +++ b/miri/fn_call.rs @@ -421,11 +421,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) { return err!(OutOfTls); } - // TODO: Does this need checking for alignment? - self.memory.write_uint( + self.memory.write_primval( key_ptr.to_ptr()?, - key, + PrimVal::Bytes(key), key_size.bytes(), + false, )?; // Return success (0) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 1841e1554056..19dc2bdf847d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -579,12 +579,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { discr_val: u128, variant_idx: usize, discr_size: u64, + discr_signed: bool, ) -> EvalResult<'tcx> { // FIXME(solson) let dest_ptr = self.force_allocation(dest)?.to_ptr()?; let discr_dest = dest_ptr.offset(discr_offset, &self)?; - self.memory.write_uint(discr_dest, discr_val, discr_size)?; + self.memory.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr_size, discr_signed)?; let dest = Lvalue::Ptr { ptr: PtrAndAlign { @@ -724,6 +725,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { discr_val, variant, discr_size, + false, )?; } else { bug!("tried to assign {:?} to Layout::General", kind); @@ -783,7 +785,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ); self.memory.write_maybe_aligned_mut( !nonnull.packed, - |mem| mem.write_int(dest, 0, dest_size), + // The sign does not matter for 0 + |mem| mem.write_primval(dest, PrimVal::Bytes(0), dest_size, false), )?; } } else { @@ -1607,7 +1610,20 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } Value::ByVal(primval) => { let size = self.type_size(dest_ty)?.expect("dest type must be sized"); - self.memory.write_primval(dest, primval, size) + // TODO: This fn gets called with sizes like 6, which cannot be a primitive type + // and hence is not supported by write_primval. + // (E.g. in the arrays.rs testcase.) That seems to only happen for Undef though, + // so we special-case that here. + match primval { + PrimVal::Undef => { + self.memory.mark_definedness(dest, size, false)?; + } + _ => { + // TODO: Do we need signedness? + self.memory.write_primval(dest.to_ptr()?, primval, size, false)?; + } + } + Ok(()) } Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty), } @@ -1645,11 +1661,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ); let field_0_ptr = ptr.offset(field_0.bytes(), &self)?.into(); let field_1_ptr = ptr.offset(field_1.bytes(), &self)?.into(); + // TODO: What about signedess? self.write_maybe_aligned_mut(!packed, |ectx| { - ectx.memory.write_primval(field_0_ptr, a, field_0_size) + ectx.memory.write_primval(field_0_ptr, a, field_0_size, false) })?; self.write_maybe_aligned_mut(!packed, |ectx| { - ectx.memory.write_primval(field_1_ptr, b, field_1_size) + ectx.memory.write_primval(field_1_ptr, b, field_1_size, false) })?; Ok(()) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d24f469de405..d8a4ae66cf67 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1206,20 +1206,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { self.read_primval(ptr, self.pointer_size(), false) } - pub fn write_ptr(&mut self, dest: MemoryPointer, ptr: MemoryPointer) -> EvalResult<'tcx> { - self.write_usize(dest, ptr.offset as u64)?; - self.get_mut(dest.alloc_id)?.relocations.insert( - dest.offset, - ptr.alloc_id, - ); - Ok(()) - } + pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> { + trace!("Writing {:?}, size {}", val, size); + let align = self.int_align(size)?; + let endianess = self.endianess(); - pub fn write_primval(&mut self, dest: Pointer, val: PrimVal, size: u64) -> EvalResult<'tcx> { - match val { - PrimVal::Ptr(ptr) => { + let bytes = match val { + PrimVal::Ptr(val) => { assert_eq!(size, self.pointer_size()); - self.write_ptr(dest.to_ptr()?, ptr) + val.offset as u128 } PrimVal::Bytes(bytes) => { @@ -1233,11 +1228,41 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { 16 => !0, n => bug!("unexpected PrimVal::Bytes size: {}", n), }; - self.write_uint(dest.to_ptr()?, bytes & mask, size) + bytes & mask } - PrimVal::Undef => self.mark_definedness(dest, size, false), + PrimVal::Undef => { + self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?; + return Ok(()); + } + }; + + { + let dst = self.get_bytes_mut(ptr, size, align)?; + if signed { + write_target_int(endianess, dst, bytes as i128).unwrap(); + } else { + write_target_uint(endianess, dst, bytes).unwrap(); + } } + + // See if we have to also write a relocation + match val { + PrimVal::Ptr(val) => { + self.get_mut(ptr.alloc_id)?.relocations.insert( + ptr.offset, + val.alloc_id, + ); + } + _ => {} + } + + Ok(()) + } + + pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, val: PrimVal) -> EvalResult<'tcx> { + let ptr_size = self.pointer_size(); + self.write_primval(ptr, val, ptr_size, false) } pub fn read_bool(&self, ptr: MemoryPointer) -> EvalResult<'tcx, bool> { @@ -1269,32 +1294,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } } - pub fn write_int(&mut self, ptr: MemoryPointer, n: i128, size: u64) -> EvalResult<'tcx> { - let align = self.int_align(size)?; - let endianess = self.endianess(); - let b = self.get_bytes_mut(ptr, size, align)?; - write_target_int(endianess, b, n).unwrap(); - Ok(()) - } - - pub fn write_uint(&mut self, ptr: MemoryPointer, n: u128, size: u64) -> EvalResult<'tcx> { - let align = self.int_align(size)?; - let endianess = self.endianess(); - let b = self.get_bytes_mut(ptr, size, align)?; - write_target_uint(endianess, b, n).unwrap(); - Ok(()) - } - - pub fn write_isize(&mut self, ptr: MemoryPointer, n: i64) -> EvalResult<'tcx> { - let size = self.pointer_size(); - self.write_int(ptr, n as i128, size) - } - - pub fn write_usize(&mut self, ptr: MemoryPointer, n: u64) -> EvalResult<'tcx> { - let size = self.pointer_size(); - self.write_uint(ptr, n as u128, size) - } - pub fn write_f32(&mut self, ptr: MemoryPointer, f: f32) -> EvalResult<'tcx> { let endianess = self.endianess(); let align = self.layout.f32_align.abi(); diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index c43ad18e0d87..9a6f72c7bfde 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -12,7 +12,7 @@ use rustc::ty::layout::Layout; use rustc::ty::subst::Substs; use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue, - HasMemory, MemoryKind, Machine}; + HasMemory, MemoryKind, Machine, PrimVal}; use syntax::codemap::Span; use syntax::ast::Mutability; @@ -106,10 +106,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { Layout::General { discr, .. } => { let discr_size = discr.size().bytes(); let dest_ptr = self.force_allocation(dest)?.to_ptr()?; - self.memory.write_uint( + self.memory.write_primval( dest_ptr, - variant_index as u128, + PrimVal::Bytes(variant_index as u128), discr_size, + false )? } @@ -124,6 +125,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ref discrfield_source, .. } => { + // TODO: There's some duplication between here and eval_rvalue_into_lvalue if variant_index as u64 != nndiscr { let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( dest_ty, @@ -140,7 +142,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { "bad StructWrappedNullablePointer discrfield", ); self.write_maybe_aligned_mut(!packed, |ectx| { - ectx.memory.write_uint(nonnull, 0, discr_size) + // We're writing 0, signedness does not matter + ectx.memory.write_primval(nonnull, PrimVal::Bytes(0), discr_size, false) })?; } } @@ -229,7 +232,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ptr_size, MemoryKind::UninitializedStatic, )?; - self.memory.write_usize(ptr, 0)?; + self.memory.write_ptr_sized_unsigned(ptr, PrimVal::Bytes(0))?; self.memory.mark_static_initalized(ptr.alloc_id, mutability)?; self.globals.insert( cid, diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 284e9811c9fd..3f7e10a9eaff 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -63,19 +63,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { let drop = eval_context::resolve_drop_in_place(self.tcx, ty); let drop = self.memory.create_fn_alloc(drop); - self.memory.write_ptr(vtable, drop)?; + self.memory.write_ptr_sized_unsigned(vtable, PrimVal::Ptr(drop))?; let size_ptr = vtable.offset(ptr_size, &self)?; - self.memory.write_usize(size_ptr, size)?; + self.memory.write_ptr_sized_unsigned(size_ptr, PrimVal::Bytes(size as u128))?; let align_ptr = vtable.offset(ptr_size * 2, &self)?; - self.memory.write_usize(align_ptr, align)?; + self.memory.write_ptr_sized_unsigned(align_ptr, PrimVal::Bytes(align as u128))?; for (i, method) in ::rustc::traits::get_vtable_methods(self.tcx, trait_ref).enumerate() { if let Some((def_id, substs)) = method { let instance = eval_context::resolve(self.tcx, def_id, substs); let fn_ptr = self.memory.create_fn_alloc(instance); let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?; - self.memory.write_ptr(method_ptr, fn_ptr)?; + self.memory.write_ptr_sized_unsigned(method_ptr, PrimVal::Ptr(fn_ptr))?; } } From ac80212f7e973ccd57ed41137e2ec38db6fbde1f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Aug 2017 19:21:10 +0200 Subject: [PATCH 04/10] move tests with MIR-opt to their own function we we can run them separately --- tests/compiletest.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 5ceb60de638a..35c5e82803f9 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -174,17 +174,24 @@ fn get_host() -> String { String::from(host) } -#[test] -fn run_pass_miri() { +fn run_pass_miri(opt: bool) { let sysroot = get_sysroot(); let host = get_host(); - for &opt in [false, true].iter() { - for_all_targets(&sysroot, |target| { - miri_pass("tests/run-pass", &target, &host, false, opt); - }); - miri_pass("tests/run-pass-fullmir", &host, &host, true, opt); - } + for_all_targets(&sysroot, |target| { + miri_pass("tests/run-pass", &target, &host, false, opt); + }); + miri_pass("tests/run-pass-fullmir", &host, &host, true, opt); +} + +#[test] +fn run_pass_miri_noopt() { + run_pass_miri(false); +} + +#[test] +fn run_pass_miri_opt() { + run_pass_miri(true); } #[test] From 8ce6b06d52e6b0792d9f6c3bc192cbcfb21842f1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Aug 2017 19:21:26 +0200 Subject: [PATCH 05/10] Remove specialize float/bool read/write methods from memory Notice that the write methods were previously unused, so if this makes us handle some things incorrectly, they probably were already broken --- src/librustc_mir/interpret/eval_context.rs | 16 +++- src/librustc_mir/interpret/memory.rs | 88 ---------------------- 2 files changed, 12 insertions(+), 92 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 19dc2bdf847d..2d86c14a86ae 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1610,7 +1610,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } Value::ByVal(primval) => { let size = self.type_size(dest_ty)?.expect("dest type must be sized"); - // TODO: This fn gets called with sizes like 6, which cannot be a primitive type + // TODO: This fn gets called with sizes like 0 and 6, which cannot be a primitive type // and hence is not supported by write_primval. // (E.g. in the arrays.rs testcase.) That seems to only happen for Undef though, // so we special-case that here. @@ -1808,7 +1808,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { let ptr = ptr.to_ptr()?; let val = match ty.sty { - ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr)?), + ty::TyBool => { + let val = self.memory.read_primval(ptr, 1, false)?; + let val = match val { + PrimVal::Bytes(0) => false, + PrimVal::Bytes(1) => true, + _ => return err!(InvalidBool), + }; + PrimVal::from_bool(val) + } ty::TyChar => { let c = self.memory.read_primval(ptr, 4, false)?.to_bytes()? as u32; match ::std::char::from_u32(c) { @@ -1843,8 +1851,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { self.memory.read_primval(ptr, size, false)? } - ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?), - ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr)?), + ty::TyFloat(FloatTy::F32) => PrimVal::Bytes(self.memory.read_primval(ptr, 4, false)?.to_bytes()?), + ty::TyFloat(FloatTy::F64) => PrimVal::Bytes(self.memory.read_primval(ptr, 8, false)?.to_bytes()?), ty::TyFnPtr(_) => self.memory.read_ptr_sized_unsigned(ptr)?, ty::TyRef(_, ref tam) | diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d8a4ae66cf67..8e2b5e9c4309 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1207,7 +1207,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> { - trace!("Writing {:?}, size {}", val, size); let align = self.int_align(size)?; let endianess = self.endianess(); @@ -1265,22 +1264,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { self.write_primval(ptr, val, ptr_size, false) } - pub fn read_bool(&self, ptr: MemoryPointer) -> EvalResult<'tcx, bool> { - let bytes = self.get_bytes(ptr, 1, self.layout.i1_align.abi())?; - match bytes[0] { - 0 => Ok(false), - 1 => Ok(true), - _ => err!(InvalidBool), - } - } - - pub fn write_bool(&mut self, ptr: MemoryPointer, b: bool) -> EvalResult<'tcx> { - let align = self.layout.i1_align.abi(); - self.get_bytes_mut(ptr, 1, align).map( - |bytes| bytes[0] = b as u8, - ) - } - fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> { // We assume pointer-sized integers have the same alignment as pointers. // We also assume singed and unsigned integers of the same size have the same alignment. @@ -1293,38 +1276,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { _ => bug!("bad integer size: {}", size), } } - - pub fn write_f32(&mut self, ptr: MemoryPointer, f: f32) -> EvalResult<'tcx> { - let endianess = self.endianess(); - let align = self.layout.f32_align.abi(); - let b = self.get_bytes_mut(ptr, 4, align)?; - write_target_f32(endianess, b, f).unwrap(); - Ok(()) - } - - pub fn write_f64(&mut self, ptr: MemoryPointer, f: f64) -> EvalResult<'tcx> { - let endianess = self.endianess(); - let align = self.layout.f64_align.abi(); - let b = self.get_bytes_mut(ptr, 8, align)?; - write_target_f64(endianess, b, f).unwrap(); - Ok(()) - } - - pub fn read_f32(&self, ptr: MemoryPointer) -> EvalResult<'tcx, f32> { - self.get_bytes(ptr, 4, self.layout.f32_align.abi()).map( - |b| { - read_target_f32(self.endianess(), b).unwrap() - }, - ) - } - - pub fn read_f64(&self, ptr: MemoryPointer) -> EvalResult<'tcx, f64> { - self.get_bytes(ptr, 8, self.layout.f64_align.abi()).map( - |b| { - read_target_f64(self.endianess(), b).unwrap() - }, - ) - } } /// Relocations @@ -1496,45 +1447,6 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result Result<(), io::Error> { - match endianess { - layout::Endian::Little => target.write_f32::(data), - layout::Endian::Big => target.write_f32::(data), - } -} -fn write_target_f64( - endianess: layout::Endian, - mut target: &mut [u8], - data: f64, -) -> Result<(), io::Error> { - match endianess { - layout::Endian::Little => target.write_f64::(data), - layout::Endian::Big => target.write_f64::(data), - } -} - -fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result { - match endianess { - layout::Endian::Little => source.read_f32::(), - layout::Endian::Big => source.read_f32::(), - } -} -fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result { - match endianess { - layout::Endian::Little => source.read_f64::(), - layout::Endian::Big => source.read_f64::(), - } -} - //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking //////////////////////////////////////////////////////////////////////////////// From e53e9b9e63be157efeac9212dc05b3e9c8d0fd19 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 15:27:50 +0200 Subject: [PATCH 06/10] Deduplicate writing null case of struct wrapped nullable pointers --- src/librustc_mir/interpret/eval_context.rs | 51 ++++++++++++++-------- src/librustc_mir/interpret/step.rs | 21 ++------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 79f170ace6c8..39ead337906f 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -767,25 +767,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { let operand_ty = self.operand_ty(operand); assert_eq!(self.type_size(operand_ty)?, Some(0)); } - let (offset, TyAndPacked { ty, packed: _ }) = - self.nonnull_offset_and_ty( - dest_ty, - nndiscr, - discrfield_source, - )?; - // TODO: The packed flag is ignored - - // FIXME(solson) - let dest = self.force_allocation(dest)?.to_ptr()?; - - let dest = dest.offset(offset.bytes(), &self)?; - let dest_size = self.type_size(ty)?.expect( - "bad StructWrappedNullablePointer discrfield", - ); - self.memory.write_maybe_aligned_mut( - !nonnull.packed, - // The sign does not matter for 0 - |mem| mem.write_primval(dest, PrimVal::Bytes(0), dest_size, false), + self.write_struct_wrapped_null_pointer( + dest_ty, + nndiscr, + discrfield_source, + dest, )?; } } else { @@ -1021,6 +1007,33 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { Ok(()) } + pub(crate) fn write_struct_wrapped_null_pointer( + &mut self, + dest_ty: ty::Ty<'tcx>, + nndiscr: u64, + discrfield_source: &layout::FieldPath, + dest: Lvalue, + ) -> EvalResult<'tcx> { + let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( + dest_ty, + nndiscr, + discrfield_source, + )?; + let nonnull = self.force_allocation(dest)?.to_ptr()?.offset( + offset.bytes(), + &self, + )?; + trace!("struct wrapped nullable pointer type: {}", ty); + // only the pointer part of a fat pointer is used for this space optimization + let discr_size = self.type_size(ty)?.expect( + "bad StructWrappedNullablePointer discrfield", + ); + self.memory.write_maybe_aligned_mut(!packed, |mem| { + // We're writing 0, signedness does not matter + mem.write_primval(nonnull, PrimVal::Bytes(0), discr_size, false) + }) + } + pub(super) fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool { match ty.sty { ty::TyRawPtr(ref tam) | diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 9a6f72c7bfde..ea90e39489d5 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -11,8 +11,8 @@ use rustc::ty; use rustc::ty::layout::Layout; use rustc::ty::subst::Substs; -use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue, - HasMemory, MemoryKind, Machine, PrimVal}; +use super::{EvalResult, EvalContext, StackPopCleanup, PtrAndAlign, GlobalId, Lvalue, + MemoryKind, Machine, PrimVal}; use syntax::codemap::Span; use syntax::ast::Mutability; @@ -125,26 +125,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { ref discrfield_source, .. } => { - // TODO: There's some duplication between here and eval_rvalue_into_lvalue if variant_index as u64 != nndiscr { - let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( + self.write_struct_wrapped_null_pointer( dest_ty, nndiscr, discrfield_source, + dest, )?; - let nonnull = self.force_allocation(dest)?.to_ptr()?.offset( - offset.bytes(), - &self, - )?; - trace!("struct wrapped nullable pointer type: {}", ty); - // only the pointer part of a fat pointer is used for this space optimization - let discr_size = self.type_size(ty)?.expect( - "bad StructWrappedNullablePointer discrfield", - ); - self.write_maybe_aligned_mut(!packed, |ectx| { - // We're writing 0, signedness does not matter - ectx.memory.write_primval(nonnull, PrimVal::Bytes(0), discr_size, false) - })?; } } From 129b914bdc9bac5c10181d1e87f722be15cb627c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 15:58:58 +0200 Subject: [PATCH 07/10] `int_align` has no dynamic error case --- src/librustc_mir/interpret/memory.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 8e2b5e9c4309..adca51acba62 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1174,7 +1174,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { pub fn read_primval(&self, ptr: MemoryPointer, size: u64, signed: bool) -> EvalResult<'tcx, PrimVal> { self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer let endianess = self.endianess(); - let bytes = self.get_bytes_unchecked(ptr, size, self.int_align(size)?)?; + let bytes = self.get_bytes_unchecked(ptr, size, self.int_align(size))?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -1207,7 +1207,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> { - let align = self.int_align(size)?; let endianess = self.endianess(); let bytes = match val { @@ -1237,6 +1236,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { }; { + let align = self.int_align(size); let dst = self.get_bytes_mut(ptr, size, align)?; if signed { write_target_int(endianess, dst, bytes as i128).unwrap(); @@ -1264,15 +1264,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { self.write_primval(ptr, val, ptr_size, false) } - fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> { + fn int_align(&self, size: u64) -> u64 { // We assume pointer-sized integers have the same alignment as pointers. - // We also assume singed and unsigned integers of the same size have the same alignment. + // We also assume signed and unsigned integers of the same size have the same alignment. match size { - 1 => Ok(self.layout.i8_align.abi()), - 2 => Ok(self.layout.i16_align.abi()), - 4 => Ok(self.layout.i32_align.abi()), - 8 => Ok(self.layout.i64_align.abi()), - 16 => Ok(self.layout.i128_align.abi()), + 1 => self.layout.i8_align.abi(), + 2 => self.layout.i16_align.abi(), + 4 => self.layout.i32_align.abi(), + 8 => self.layout.i64_align.abi(), + 16 => self.layout.i128_align.abi(), _ => bug!("bad integer size: {}", size), } } From 2f0dcfba1d7fd007af1d9d9cfb92bf67ec151f7e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 16:06:49 +0200 Subject: [PATCH 08/10] Simplify `write_value_to_ptr` --- src/librustc_mir/interpret/eval_context.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 39ead337906f..044f37947d30 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1622,20 +1622,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } Value::ByVal(primval) => { let size = self.type_size(dest_ty)?.expect("dest type must be sized"); - // TODO: This fn gets called with sizes like 0 and 6, which cannot be a primitive type - // and hence is not supported by write_primval. - // (E.g. in the arrays.rs testcase.) That seems to only happen for Undef though, - // so we special-case that here. - match primval { - PrimVal::Undef => { - self.memory.mark_definedness(dest, size, false)?; - } - _ => { - // TODO: Do we need signedness? - self.memory.write_primval(dest.to_ptr()?, primval, size, false)?; - } + if size == 0 { + assert!(primval.is_undef()); + Ok(()) + } else { + // TODO: Do we need signedness? + self.memory.write_primval(dest.to_ptr()?, primval, size, false) } - Ok(()) } Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty), } From f817f1c66072e5830a1a0162a63baa05450df9a3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 17:32:21 +0200 Subject: [PATCH 09/10] Get rid of env var race condition once and for all --- Cargo.lock | 40 ++++++++++++++++++++-------------------- miri/bin/miri.rs | 28 +++++++++++++++++++++------- rustc_tests/src/main.rs | 26 +++++++++++++++++++------- tests/compiletest.rs | 7 +++---- 4 files changed, 63 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e41c3010879..00ae333b4671 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,24 +21,24 @@ dependencies = [ [[package]] name = "backtrace" version = "0.3.2" -source = "git+https://github.com/alexcrichton/backtrace-rs#3d96a9242ed2096984d15d177f4762b699bee6d4" +source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4" dependencies = [ "backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" version = "0.1.12" -source = "git+https://github.com/alexcrichton/backtrace-rs#3d96a9242ed2096984d15d177f4762b699bee6d4" +source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -99,7 +99,7 @@ dependencies = [ [[package]] name = "dtoa" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -113,12 +113,12 @@ dependencies = [ [[package]] name = "gcc" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itoa" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -137,7 +137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.28" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -175,7 +175,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -207,7 +207,7 @@ name = "rand" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-demangle" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -267,8 +267,8 @@ name = "serde_json" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -353,13 +353,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" "checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" -"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" +"checksum itoa 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f74cf6ca1bdbc28496a2b9798ab7fccc2ca5a42cace95bb2b219577216a5fb90" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb7b49972ee23d8aa1026c365a5b440ba08e35075f18c459980c7395c221ec48" +"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6" "checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527" @@ -370,7 +370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" "checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" diff --git a/miri/bin/miri.rs b/miri/bin/miri.rs index 29c47e355703..337a723a40d6 100644 --- a/miri/bin/miri.rs +++ b/miri/bin/miri.rs @@ -19,7 +19,11 @@ use rustc::ty::TyCtxt; use syntax::ast::{self, MetaItemKind, NestedMetaItemKind}; use std::path::PathBuf; -struct MiriCompilerCalls(RustcDefaultCalls); +struct MiriCompilerCalls { + default: RustcDefaultCalls, + /// whether we are building for the host + host_target: bool, +} impl<'a> CompilerCalls<'a> for MiriCompilerCalls { fn early_callback( @@ -30,7 +34,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType, ) -> Compilation { - self.0.early_callback( + self.default.early_callback( matches, sopts, cfg, @@ -47,7 +51,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry, ) -> Option<(Input, Option)> { - self.0.no_input( + self.default.no_input( matches, sopts, cfg, @@ -64,17 +68,17 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { odir: &Option, ofile: &Option, ) -> Compilation { - self.0.late_callback(matches, sess, input, odir, ofile) + self.default.late_callback(matches, sess, input, odir, ofile) } fn build_controller( &mut self, sess: &Session, matches: &getopts::Matches, ) -> CompileController<'a> { - let mut control = self.0.build_controller(sess, matches); + let mut control = self.default.build_controller(sess, matches); control.after_hir_lowering.callback = Box::new(after_hir_lowering); control.after_analysis.callback = Box::new(after_analysis); - if std::env::var("MIRI_HOST_TARGET") != Ok("yes".to_owned()) { + if !self.host_target { // only fully compile targets on the host control.after_analysis.stop = Compilation::Stop; } @@ -254,6 +258,16 @@ fn main() { // for auxilary builds in unit tests args.push("-Zalways-encode-mir".to_owned()); + let mut host_target = false; + args.retain(|arg| if arg == "--miri_host_target" { + host_target = true; + false // remove the flag, rustc doesn't know it + } else { + true + }); - rustc_driver::run_compiler(&args, &mut MiriCompilerCalls(RustcDefaultCalls), None, None); + rustc_driver::run_compiler(&args, &mut MiriCompilerCalls { + default: RustcDefaultCalls, + host_target, + }, None, None); } diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs index 4cff381b3321..a44880f11251 100644 --- a/rustc_tests/src/main.rs +++ b/rustc_tests/src/main.rs @@ -20,7 +20,11 @@ use rustc::hir::{self, itemlikevisit}; use rustc::ty::TyCtxt; use syntax::ast; -struct MiriCompilerCalls(RustcDefaultCalls); +struct MiriCompilerCalls { + default: RustcDefaultCalls, + /// whether we are building for the host + host_target: bool, +} impl<'a> CompilerCalls<'a> for MiriCompilerCalls { fn early_callback( @@ -31,7 +35,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { descriptions: &rustc_errors::registry::Registry, output: ErrorOutputType ) -> Compilation { - self.0.early_callback(matches, sopts, cfg, descriptions, output) + self.default.early_callback(matches, sopts, cfg, descriptions, output) } fn no_input( &mut self, @@ -42,7 +46,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { ofile: &Option, descriptions: &rustc_errors::registry::Registry ) -> Option<(Input, Option)> { - self.0.no_input(matches, sopts, cfg, odir, ofile, descriptions) + self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions) } fn late_callback( &mut self, @@ -52,13 +56,13 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { odir: &Option, ofile: &Option ) -> Compilation { - self.0.late_callback(matches, sess, input, odir, ofile) + self.default.late_callback(matches, sess, input, odir, ofile) } fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> { - let mut control = self.0.build_controller(sess, matches); + let mut control = self.default.build_controller(sess, matches); control.after_hir_lowering.callback = Box::new(after_hir_lowering); control.after_analysis.callback = Box::new(after_analysis); - if std::env::var("MIRI_HOST_TARGET") != Ok("yes".to_owned()) { + if !self.host_target { // only fully compile targets on the host control.after_analysis.stop = Compilation::Stop; } @@ -139,7 +143,15 @@ fn main() { } let stderr = std::io::stderr(); write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap(); - let mut args: Vec = std::env::args().collect(); + let mut host_target = false; + let mut args: Vec = std::env::args().filter(|arg| { + if arg == "--miri_host_target" { + host_target = true; + false // remove the flag, rustc doesn't know it + } else { + true + } + }).collect(); // file to process args.push(path.display().to_string()); diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 7a220ec76276..e7c82367b29d 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -126,15 +126,14 @@ fn miri_pass(path: &str, target: &str, host: &str, fullmir: bool, opt: bool) { // For now, only validate without optimizations. Inlining breaks validation. flags.push("-Zmir-emit-validate=1".to_owned()); } + if target == host { + flags.push("--miri_host_target".to_owned()); + } config.target_rustcflags = Some(flags.join(" ")); // don't actually execute the final binary, it might be for other targets and we only care // about running miri, not the binary. config.runtool = Some("echo \"\" || ".to_owned()); - if target == host { - std::env::set_var("MIRI_HOST_TARGET", "yes"); - } compiletest::run_tests(&config); - std::env::set_var("MIRI_HOST_TARGET", ""); } fn is_target_dir>(path: P) -> bool { From 55eaf5eb5e5854f7f7b47e9a990ef17fbc505f14 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 28 Aug 2017 18:06:06 +0200 Subject: [PATCH 10/10] Also update the rustc test suite runner --- rustc_tests/Cargo.lock | 159 +++++++++++++++++----------------------- rustc_tests/src/main.rs | 5 +- 2 files changed, 71 insertions(+), 93 deletions(-) diff --git a/rustc_tests/Cargo.lock b/rustc_tests/Cargo.lock index 2b6e311bf1b2..f2ad1c2c3b0d 100644 --- a/rustc_tests/Cargo.lock +++ b/rustc_tests/Cargo.lock @@ -13,25 +13,47 @@ dependencies = [ "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.2" +source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4" +dependencies = [ + "backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.12" +source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4" +dependencies = [ + "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "byteorder" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cargo_metadata" -version = "0.2.3" +name = "cfg-if" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "dtoa" -version = "0.4.1" +name = "dbghelp-sys" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "env_logger" @@ -43,10 +65,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "0.3.1" +name = "gcc" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "0.2.8" @@ -83,23 +114,12 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_miri 0.1.0", ] -[[package]] -name = "num-traits" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex" version = "0.2.2" @@ -117,10 +137,16 @@ name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_miri" version = "0.1.0" dependencies = [ + "backtrace 0.3.2 (git+https://github.com/alexcrichton/backtrace-rs)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -128,59 +154,6 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "serde" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.4" @@ -190,11 +163,6 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unreachable" version = "1.0.0" @@ -213,30 +181,37 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum backtrace 0.3.2 (git+https://github.com/alexcrichton/backtrace-rs)" = "" +"checksum backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)" = "" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" -"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" -"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb7b49972ee23d8aa1026c365a5b440ba08e35075f18c459980c7395c221ec48" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" -"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs index a44880f11251..ea699833f6f6 100644 --- a/rustc_tests/src/main.rs +++ b/rustc_tests/src/main.rs @@ -180,7 +180,10 @@ fn main() { let buf = BufWriter::default(); let output = buf.clone(); let result = std::panic::catch_unwind(|| { - rustc_driver::run_compiler(&args, &mut MiriCompilerCalls(RustcDefaultCalls), None, Some(Box::new(buf))); + rustc_driver::run_compiler(&args, &mut MiriCompilerCalls { + default: RustcDefaultCalls, + host_target, + }, None, Some(Box::new(buf))); }); match result {