Skip to content

Commit

Permalink
Auto merge of #50690 - oli-obk:mir_stuff, r=eddyb
Browse files Browse the repository at this point in the history
Ensure that statics are always ByRef

Statics aren't values to be used, they are names for memory locations.

r? @eddyb

cc @Zoxc

fixes #50706
  • Loading branch information
bors committed May 19, 2018
2 parents 1b240da + 7c25aa7 commit 5c3960c
Show file tree
Hide file tree
Showing 22 changed files with 389 additions and 370 deletions.
3 changes: 2 additions & 1 deletion src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,9 @@ for ::mir::interpret::ConstValue<'gcx> {
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher);
}
ByRef(alloc) => {
ByRef(alloc, offset) => {
alloc.hash_stable(hcx, hasher);
offset.hash_stable(hcx, hasher);
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{fmt, env};

use mir;
use ty::{FnSig, Ty, layout};
use ty::layout::{Size, Align};

use super::{
MemoryPointer, Lock, AccessKind
Expand Down Expand Up @@ -47,7 +48,7 @@ pub enum EvalErrorKind<'tcx, O> {
PointerOutOfBounds {
ptr: MemoryPointer,
access: bool,
allocation_size: u64,
allocation_size: Size,
},
InvalidNullPointerUsage,
ReadPointerAsBytes,
Expand All @@ -71,8 +72,8 @@ pub enum EvalErrorKind<'tcx, O> {
TlsOutOfBounds,
AbiViolation(String),
AlignmentCheckFailed {
required: u64,
has: u64,
required: Align,
has: Align,
},
MemoryLockViolation {
ptr: MemoryPointer,
Expand Down Expand Up @@ -108,7 +109,7 @@ pub enum EvalErrorKind<'tcx, O> {
DeallocatedWrongMemoryKind(String, String),
ReallocateNonBasePtr,
DeallocateNonBasePtr,
IncorrectAllocationInformation(u64, usize, u64, u64),
IncorrectAllocationInformation(Size, Size, Align, Align),
Layout(layout::LayoutError<'tcx>),
HeapAllocZeroBytes,
HeapAllocNonPowerOfTwoAlignment(u64),
Expand Down Expand Up @@ -269,7 +270,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
PointerOutOfBounds { ptr, access, allocation_size } => {
write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
if access { "memory access" } else { "pointer computed" },
ptr.offset, ptr.alloc_id, allocation_size)
ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes())
},
MemoryLockViolation { ptr, len, frame, access, ref lock } => {
write!(f, "{:?} access by frame {} at {:?}, size {}, is in conflict with lock {:?}",
Expand Down Expand Up @@ -305,7 +306,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
AlignmentCheckFailed { required, has } =>
write!(f, "tried to access memory with alignment {}, but alignment {} is required",
has, required),
has.abi(), required.abi()),
TypeNotPrimitive(ty) =>
write!(f, "expected primitive type, got {}", ty),
Layout(ref err) =>
Expand All @@ -315,7 +316,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
MachineError(ref inner) =>
write!(f, "{}", inner),
IncorrectAllocationInformation(size, size2, align, align2) =>
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
_ => write!(f, "{}", self.description()),
}
}
Expand Down
71 changes: 36 additions & 35 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::fmt;
use mir;
use hir::def_id::DefId;
use ty::{self, TyCtxt};
use ty::layout::{self, Align, HasDataLayout};
use ty::layout::{self, Align, HasDataLayout, Size};
use middle::region;
use std::iter;
use std::io;
Expand Down Expand Up @@ -109,42 +109,42 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
pub struct MemoryPointer {
pub alloc_id: AllocId,
pub offset: u64,
pub offset: Size,
}

impl<'tcx> MemoryPointer {
pub fn new(alloc_id: AllocId, offset: u64) -> Self {
pub fn new(alloc_id: AllocId, offset: Size) -> Self {
MemoryPointer { alloc_id, offset }
}

pub(crate) fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
MemoryPointer::new(
self.alloc_id,
cx.data_layout().wrapping_signed_offset(self.offset, i),
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
)
}

pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset, i);
(MemoryPointer::new(self.alloc_id, res), over)
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
(MemoryPointer::new(self.alloc_id, Size::from_bytes(res)), over)
}

pub(crate) fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
Ok(MemoryPointer::new(
self.alloc_id,
cx.data_layout().signed_offset(self.offset, i)?,
Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
))
}

pub fn overflowing_offset<C: HasDataLayout>(self, i: u64, cx: C) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_offset(self.offset, i);
(MemoryPointer::new(self.alloc_id, res), over)
pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
(MemoryPointer::new(self.alloc_id, Size::from_bytes(res)), over)
}

pub fn offset<C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
Ok(MemoryPointer::new(
self.alloc_id,
cx.data_layout().offset(self.offset, i)?,
Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
))
}
}
Expand Down Expand Up @@ -244,7 +244,7 @@ pub struct Allocation {
pub bytes: Vec<u8>,
/// Maps from byte addresses to allocations.
/// Only the first byte of a pointer is inserted into the map.
pub relocations: BTreeMap<u64, AllocId>,
pub relocations: BTreeMap<Size, AllocId>,
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
pub undef_mask: UndefMask,
/// The alignment of the allocation to detect unaligned reads.
Expand All @@ -257,8 +257,8 @@ pub struct Allocation {

impl Allocation {
pub fn from_bytes(slice: &[u8], align: Align) -> Self {
let mut undef_mask = UndefMask::new(0);
undef_mask.grow(slice.len() as u64, true);
let mut undef_mask = UndefMask::new(Size::from_bytes(0));
undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
Self {
bytes: slice.to_owned(),
relocations: BTreeMap::new(),
Expand All @@ -272,10 +272,10 @@ impl Allocation {
Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
}

pub fn undef(size: u64, align: Align) -> Self {
assert_eq!(size as usize as u64, size);
pub fn undef(size: Size, align: Align) -> Self {
assert_eq!(size.bytes() as usize as u64, size.bytes());
Allocation {
bytes: vec![0; size as usize],
bytes: vec![0; size.bytes() as usize],
relocations: BTreeMap::new(),
undef_mask: UndefMask::new(size),
align,
Expand Down Expand Up @@ -331,54 +331,54 @@ const BLOCK_SIZE: u64 = 64;
#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
pub struct UndefMask {
blocks: Vec<Block>,
len: u64,
len: Size,
}

impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});

impl UndefMask {
pub fn new(size: u64) -> Self {
pub fn new(size: Size) -> Self {
let mut m = UndefMask {
blocks: vec![],
len: 0,
len: Size::from_bytes(0),
};
m.grow(size, false);
m
}

/// Check whether the range `start..end` (end-exclusive) is entirely defined.
pub fn is_range_defined(&self, start: u64, end: u64) -> bool {
pub fn is_range_defined(&self, start: Size, end: Size) -> bool {
if end > self.len {
return false;
}
for i in start..end {
if !self.get(i) {
for i in start.bytes()..end.bytes() {
if !self.get(Size::from_bytes(i)) {
return false;
}
}
true
}

pub fn set_range(&mut self, start: u64, end: u64, new_state: bool) {
pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
let len = self.len;
if end > len {
self.grow(end - len, new_state);
}
self.set_range_inbounds(start, end, new_state);
}

pub fn set_range_inbounds(&mut self, start: u64, end: u64, new_state: bool) {
for i in start..end {
self.set(i, new_state);
pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
for i in start.bytes()..end.bytes() {
self.set(Size::from_bytes(i), new_state);
}
}

pub fn get(&self, i: u64) -> bool {
pub fn get(&self, i: Size) -> bool {
let (block, bit) = bit_index(i);
(self.blocks[block] & 1 << bit) != 0
}

pub fn set(&mut self, i: u64, new_state: bool) {
pub fn set(&mut self, i: Size, new_state: bool) {
let (block, bit) = bit_index(i);
if new_state {
self.blocks[block] |= 1 << bit;
Expand All @@ -387,10 +387,10 @@ impl UndefMask {
}
}

pub fn grow(&mut self, amount: u64, new_state: bool) {
let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len;
if amount > unused_trailing_bits {
let additional_blocks = amount / BLOCK_SIZE + 1;
pub fn grow(&mut self, amount: Size, new_state: bool) {
let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len.bytes();
if amount.bytes() > unused_trailing_bits {
let additional_blocks = amount.bytes() / BLOCK_SIZE + 1;
assert_eq!(additional_blocks as usize as u64, additional_blocks);
self.blocks.extend(
iter::repeat(0).take(additional_blocks as usize),
Expand All @@ -402,7 +402,8 @@ impl UndefMask {
}
}

fn bit_index(bits: u64) -> (usize, usize) {
fn bit_index(bits: Size) -> (usize, usize) {
let bits = bits.bytes();
let a = bits / BLOCK_SIZE;
let b = bits % BLOCK_SIZE;
assert_eq!(a as usize as u64, a);
Expand Down
26 changes: 13 additions & 13 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(unknown_lints)]

use ty::layout::{Align, HasDataLayout};
use ty::layout::{Align, HasDataLayout, Size};
use ty;

use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
Expand All @@ -9,12 +9,12 @@ use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
/// matches Value's optimizations for easy conversions between these two types
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
/// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
ByVal(PrimVal),
// Used only for types with layout::abi::ScalarPair
/// Used only for types with layout::abi::ScalarPair
ByValPair(PrimVal, PrimVal),
// Used only for the remaining cases
ByRef(&'tcx Allocation),
/// Used only for the remaining cases. An allocation + offset into the allocation
ByRef(&'tcx Allocation, Size),
}

impl<'tcx> ConstValue<'tcx> {
Expand Down Expand Up @@ -129,13 +129,13 @@ impl<'tcx> Pointer {
}
}

pub fn offset<C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout();
match self.primval {
PrimVal::Bytes(b) => {
assert_eq!(b as u64 as u128, b);
Ok(Pointer::from(
PrimVal::Bytes(layout.offset(b as u64, i)? as u128),
PrimVal::Bytes(layout.offset(b as u64, i.bytes())? as u128),
))
}
PrimVal::Ptr(ptr) => ptr.offset(i, layout).map(Pointer::from),
Expand Down Expand Up @@ -336,25 +336,25 @@ impl PrimValKind {
}
}

pub fn from_uint_size(size: u64) -> Self {
match size {
pub fn from_uint_size(size: Size) -> Self {
match size.bytes() {
1 => PrimValKind::U8,
2 => PrimValKind::U16,
4 => PrimValKind::U32,
8 => PrimValKind::U64,
16 => PrimValKind::U128,
_ => bug!("can't make uint with size {}", size),
_ => bug!("can't make uint with size {}", size.bytes()),
}
}

pub fn from_int_size(size: u64) -> Self {
match size {
pub fn from_int_size(size: Size) -> Self {
match size.bytes() {
1 => PrimValKind::I8,
2 => PrimValKind::I16,
4 => PrimValKind::I32,
8 => PrimValKind::I64,
16 => PrimValKind::I128,
_ => bug!("can't make int with size {}", size),
_ => bug!("can't make int with size {}", size.bytes()),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1913,7 +1913,7 @@ pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Resul
.get_alloc(ptr.alloc_id);
if let Some(alloc) = alloc {
assert_eq!(len as usize as u128, len);
let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
let s = ::std::str::from_utf8(slice)
.expect("non utf8 str from miri");
write!(f, "{:?}", s)
Expand Down
11 changes: 1 addition & 10 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ty::subst::{Substs, Subst, Kind, UnpackedKind};
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS};
use util::captures::Captures;
use mir::interpret::{Allocation, PrimVal, MemoryPointer, Value, ConstValue};
use mir::interpret::{PrimVal, MemoryPointer, Value, ConstValue};

use std::iter;
use std::cmp::Ordering;
Expand Down Expand Up @@ -1767,15 +1767,6 @@ impl<'tcx> Const<'tcx> {
Self::from_const_val(tcx, ConstVal::Value(val), ty)
}

#[inline]
pub fn from_alloc(
tcx: TyCtxt<'_, '_, 'tcx>,
alloc: &'tcx Allocation,
ty: Ty<'tcx>,
) -> &'tcx Self {
Self::from_const_value(tcx, ConstValue::ByRef(alloc), ty)
}

#[inline]
pub fn from_byval_value(
tcx: TyCtxt<'_, '_, 'tcx>,
Expand Down
Loading

0 comments on commit 5c3960c

Please sign in to comment.