Skip to content

Commit

Permalink
Auto merge of #61164 - RalfJung:scalar, r=<try>
Browse files Browse the repository at this point in the history
rename Scalar::Bits to Scalar::Raw and bits field to data

Also use this opportunity to seal some abstraction leaks (other modules constructing `Scalar::Bits` directly instead of using a constructor).

r? @oli-obk
  • Loading branch information
bors committed May 26, 2019
2 parents 566f3d7 + aad13a1 commit 2189421
Show file tree
Hide file tree
Showing 19 changed files with 156 additions and 192 deletions.
16 changes: 3 additions & 13 deletions src/librustc/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use super::{
Pointer, EvalResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar,
truncate,
};

use crate::ty::layout::{Size, Align};
Expand Down Expand Up @@ -382,18 +381,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
};

let bytes = match val {
Scalar::Ptr(val) => {
assert_eq!(type_size, cx.data_layout().pointer_size);
val.offset.bytes() as u128
}

Scalar::Bits { bits, size } => {
assert_eq!(size as u64, type_size.bytes());
debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
"Unexpected value of size {} when writing to memory", size);
bits
},
let bytes = match val.to_bits_or_ptr(type_size, cx) {
Err(val) => val.offset.bytes() as u128,
Ok(data) => data,
};

let endian = cx.data_layout().endian;
Expand Down
45 changes: 24 additions & 21 deletions src/librustc/mir/interpret/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,48 @@ pub trait PointerArithmetic: layout::HasDataLayout {
self.data_layout().pointer_size
}

//// Trunace the given value to the pointer size; also return whether there was an overflow
/// Helper function: truncate given value-"overflowed flag" pair to pointer size and
/// update "overflowed flag" if there was an overflow.
/// This should be called by all the other methods before returning!
#[inline]
fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
let val = val as u128;
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
}

#[inline]
fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_offset(val, i);
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
((val % max_ptr_plus_1) as u64, over || val >= max_ptr_plus_1)
}

#[inline]
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
let (res, over1) = val.overflowing_add(i);
let (res, over2) = self.truncate_to_ptr(u128::from(res));
(res, over1 || over2)
}

#[inline]
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
let res = val.overflowing_add(i);
self.truncate_to_ptr(res)
}

// Overflow checking only works properly on the range from -u64 to +u64.
#[inline]
fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
// FIXME: is it possible to over/underflow here?
if i < 0 {
// trickery to ensure that i64::min_value() works fine
// this formula only works for true negative values, it panics for zero!
// Trickery to ensure that i64::min_value() works fine: compute n = -i.
// This formula only works for true negative values, it overflows for zero!
let n = u64::max_value() - (i as u64) + 1;
val.overflowing_sub(n)
let res = val.overflowing_sub(n);
self.truncate_to_ptr(res)
} else {
self.overflowing_offset(val, i as u64)
}
}

#[inline]
fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_offset(val, i);
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
}

#[inline]
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
}
}

impl<T: layout::HasDataLayout> PointerArithmetic for T {}
Expand Down
Loading

0 comments on commit 2189421

Please sign in to comment.