Skip to content

Ensure that statics are always ByRef #50690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would wrapping_signed_offset not work on a Size?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because SIze doesn't have a sign. I mean we could create an Offset type (which would then also be the Output of impl Sub for Size)...

)
}

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