Skip to content
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

rename Scalar::Bits to Scalar::Raw and bits field to data #61164

Merged
merged 5 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
6 changes: 3 additions & 3 deletions src/librustc/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,11 +388,11 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
val.offset.bytes() as u128
}

Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, type_size.bytes());
debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
debug_assert_eq!(truncate(data, Size::from_bytes(size.into())), data,
"Unexpected value of size {} when writing to memory", size);
bits
data
},
};

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
88 changes: 44 additions & 44 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ impl<'tcx> ConstValue<'tcx> {
RustcEncodable, RustcDecodable, Hash, HashStable)]
pub enum Scalar<Tag=(), Id=AllocId> {
/// The raw bytes of a simple value.
Bits {
/// The first `size` bytes are the value.
Raw {
/// The first `size` bytes of `data` are the value.
/// Do not try to read less or more bytes than that. The remaining bytes must be 0.
data: u128,
size: u8,
bits: u128,
},

/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
Expand All @@ -108,16 +108,16 @@ impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Scalar<Tag, Id> {
match self {
Scalar::Ptr(ptr) =>
write!(f, "{:?}", ptr),
&Scalar::Bits { bits, size } => {
&Scalar::Raw { data, size } => {
if size == 0 {
assert_eq!(bits, 0, "ZST value must be 0");
assert_eq!(data, 0, "ZST value must be 0");
write!(f, "<ZST>")
} else {
assert_eq!(truncate(bits, Size::from_bytes(size as u64)), bits,
"Scalar value {:#x} exceeds size of {} bytes", bits, size);
assert_eq!(truncate(data, Size::from_bytes(size as u64)), data,
"Scalar value {:#x} exceeds size of {} bytes", data, size);
// Format as hex number wide enough to fit any value of the given `size`.
// So bits=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
write!(f, "0x{:>0width$x}", bits, width=(size*2) as usize)
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
write!(f, "0x{:>0width$x}", data, width=(size*2) as usize)
}
}
}
Expand All @@ -128,7 +128,7 @@ impl<Tag> fmt::Display for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(_) => write!(f, "a pointer"),
Scalar::Bits { bits, .. } => write!(f, "{}", bits),
Scalar::Raw { data, .. } => write!(f, "{}", data),
}
}
}
Expand All @@ -138,7 +138,7 @@ impl<'tcx> Scalar<()> {
pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
}

Expand All @@ -155,31 +155,31 @@ impl<'tcx, Tag> Scalar<Tag> {
pub fn erase_tag(self) -> Scalar {
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
}

#[inline]
pub fn ptr_null(cx: &impl HasDataLayout) -> Self {
Scalar::Bits {
bits: 0,
Scalar::Raw {
data: 0,
size: cx.data_layout().pointer_size.bytes() as u8,
}
}

#[inline]
pub fn zst() -> Self {
Scalar::Bits { bits: 0, size: 0 }
Scalar::Raw { data: 0, size: 0 }
}

#[inline]
pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
Ok(Scalar::Bits {
bits: dl.offset(bits as u64, i.bytes())? as u128,
Ok(Scalar::Raw {
data: dl.offset(data as u64, i.bytes())? as u128,
size,
})
}
Expand All @@ -191,10 +191,10 @@ impl<'tcx, Tag> Scalar<Tag> {
pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
Scalar::Bits {
bits: dl.overflowing_offset(bits as u64, i.bytes()).0 as u128,
Scalar::Raw {
data: dl.overflowing_offset(data as u64, i.bytes()).0 as u128,
size,
}
}
Expand All @@ -206,10 +206,10 @@ impl<'tcx, Tag> Scalar<Tag> {
pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size().bytes());
Ok(Scalar::Bits {
bits: dl.signed_offset(bits as u64, i)? as u128,
Ok(Scalar::Raw {
data: dl.signed_offset(data as u64, i)? as u128,
size,
})
}
Expand All @@ -221,10 +221,10 @@ impl<'tcx, Tag> Scalar<Tag> {
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
Scalar::Bits {
bits: dl.overflowing_signed_offset(bits as u64, i128::from(i)).0 as u128,
Scalar::Raw {
data: dl.overflowing_signed_offset(data as u64, i128::from(i)).0 as u128,
size,
}
}
Expand All @@ -237,9 +237,9 @@ impl<'tcx, Tag> Scalar<Tag> {
#[inline]
pub fn get_ptr_offset(self, cx: &impl HasDataLayout) -> Size {
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, cx.pointer_size().bytes());
Size::from_bytes(bits as u64)
Size::from_bytes(data as u64)
}
Scalar::Ptr(ptr) => ptr.offset,
}
Expand All @@ -248,30 +248,30 @@ impl<'tcx, Tag> Scalar<Tag> {
#[inline]
pub fn is_null_ptr(self, cx: &impl HasDataLayout) -> bool {
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
bits == 0
data == 0
},
Scalar::Ptr(_) => false,
}
}

#[inline]
pub fn from_bool(b: bool) -> Self {
Scalar::Bits { bits: b as u128, size: 1 }
Scalar::Raw { data: b as u128, size: 1 }
}

#[inline]
pub fn from_char(c: char) -> Self {
Scalar::Bits { bits: c as u128, size: 4 }
Scalar::Raw { data: c as u128, size: 4 }
}

#[inline]
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
let i = i.into();
debug_assert_eq!(truncate(i, size), i,
"Unsigned value {} does not fit in {} bits", i, size.bits());
Scalar::Bits { bits: i, size: size.bytes() as u8 }
Scalar::Raw { data: i, size: size.bytes() as u8 }
}

#[inline]
Expand All @@ -281,26 +281,26 @@ impl<'tcx, Tag> Scalar<Tag> {
let truncated = truncate(i as u128, size);
debug_assert_eq!(sign_extend(truncated, size) as i128, i,
"Signed value {} does not fit in {} bits", i, size.bits());
Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
Scalar::Raw { data: truncated, size: size.bytes() as u8 }
}

#[inline]
pub fn from_f32(f: f32) -> Self {
Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
Scalar::Raw { data: f.to_bits() as u128, size: 4 }
}

#[inline]
pub fn from_f64(f: f64) -> Self {
Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
Scalar::Raw { data: f.to_bits() as u128, size: 8 }
}

#[inline]
pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
match self {
Scalar::Bits { bits, size } => {
Scalar::Raw { data, size } => {
assert_eq!(target_size.bytes(), size as u64);
assert_ne!(size, 0, "to_bits cannot be used with zsts");
Ok(bits)
Ok(data)
}
Scalar::Ptr(_) => err!(ReadPointerAsBytes),
}
Expand All @@ -309,16 +309,16 @@ impl<'tcx, Tag> Scalar<Tag> {
#[inline]
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
match self {
Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
Scalar::Bits { .. } => err!(ReadBytesAsPointer),
Scalar::Raw { data: 0, .. } => err!(InvalidNullPointerUsage),
Scalar::Raw { .. } => err!(ReadBytesAsPointer),
Scalar::Ptr(p) => Ok(p),
}
}

#[inline]
pub fn is_bits(self) -> bool {
match self {
Scalar::Bits { .. } => true,
Scalar::Raw { .. } => true,
_ => false,
}
}
Expand All @@ -333,8 +333,8 @@ impl<'tcx, Tag> Scalar<Tag> {

pub fn to_bool(self) -> EvalResult<'tcx, bool> {
match self {
Scalar::Bits { bits: 0, size: 1 } => Ok(false),
Scalar::Bits { bits: 1, size: 1 } => Ok(true),
Scalar::Raw { data: 0, size: 1 } => Ok(false),
Scalar::Raw { data: 1, size: 1 } => Ok(true),
_ => err!(InvalidBool),
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1669,10 +1669,7 @@ impl<'tcx> TerminatorKind<'tcx> {
.map(|&u| {
tcx.mk_const(ty::Const {
val: ConstValue::Scalar(
Scalar::Bits {
bits: u,
size: size.bytes() as u8,
}.into(),
Scalar::from_uint(u, size).into(),
),
ty: switch_ty,
}).to_string().into()
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ impl<'tcx> CommonConsts<'tcx> {

CommonConsts {
err: mk_const(ty::Const {
val: ConstValue::Scalar(Scalar::Bits { bits: 0, size: 0 }),
val: ConstValue::Scalar(Scalar::zst()),
ty: types.err,
}),
}
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,34 +845,34 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
p!(write("{}", name));
return Ok(self);
}
if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = ct.val {
if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
match ct.ty.sty {
ty::Bool => {
p!(write("{}", if bits == 0 { "false" } else { "true" }));
p!(write("{}", if data == 0 { "false" } else { "true" }));
return Ok(self);
},
ty::Float(ast::FloatTy::F32) => {
p!(write("{}f32", Single::from_bits(bits)));
p!(write("{}f32", Single::from_bits(data)));
return Ok(self);
},
ty::Float(ast::FloatTy::F64) => {
p!(write("{}f64", Double::from_bits(bits)));
p!(write("{}f64", Double::from_bits(data)));
return Ok(self);
},
ty::Uint(ui) => {
p!(write("{}{}", bits, ui));
p!(write("{}{}", data, ui));
return Ok(self);
},
ty::Int(i) =>{
let ty = self.tcx().lift_to_global(&ct.ty).unwrap();
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
p!(write("{}{}", sign_extend(bits, size) as i128, i));
p!(write("{}{}", sign_extend(data, size) as i128, i));
return Ok(self);
},
ty::Char => {
p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap()));
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
return Ok(self);
}
_ => {},
Expand Down
Loading