diff options
| author | Ralf Jung <post@ralfj.de> | 2018-08-26 20:42:52 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-08-29 08:44:37 +0200 |
| commit | cdeef61425ec177d2eb0f84d02a9d25000c954dd (patch) | |
| tree | ee29ad9a7ce00e11c9996b35dc35163d5f4a7721 /src/librustc/mir | |
| parent | 29e6aabcebe3bdb507df22a6233024711412b343 (diff) | |
| download | rust-cdeef61425ec177d2eb0f84d02a9d25000c954dd.tar.gz rust-cdeef61425ec177d2eb0f84d02a9d25000c954dd.zip | |
move some Scalar helpers from miri here, and use them where appropriate
Diffstat (limited to 'src/librustc/mir')
| -rw-r--r-- | src/librustc/mir/interpret/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/mir/interpret/value.rs | 97 |
2 files changed, 102 insertions, 2 deletions
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 147f9ccad7c..da5216bd1be 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -85,9 +85,14 @@ pub struct GlobalId<'tcx> { pub trait PointerArithmetic: layout::HasDataLayout { // These are not supposed to be overridden. + #[inline(always)] + fn pointer_size(self) -> Size { + self.data_layout().pointer_size + } + //// Trunace the given value to the pointer size; also return whether there was an overflow fn truncate_to_ptr(self, val: u128) -> (u64, bool) { - let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits(); + let max_ptr_plus_1 = 1u128 << self.pointer_size().bits(); ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1) } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index d793bb1cc63..11a4f8b884e 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -14,7 +14,7 @@ use ty::layout::{HasDataLayout, Size}; use ty::subst::Substs; use hir::def_id::DefId; -use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend}; +use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which /// matches the LocalValue optimizations for easy conversions between Value and ConstValue. @@ -58,6 +58,7 @@ impl<'tcx> ConstValue<'tcx> { self.try_to_scalar()?.to_ptr().ok() } + #[inline] pub fn new_slice( val: Scalar, len: u64, @@ -69,12 +70,14 @@ impl<'tcx> ConstValue<'tcx> { }.into()) } + #[inline] pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self { ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into()) } } impl<'tcx> Scalar { + #[inline] pub fn ptr_null(cx: impl HasDataLayout) -> Self { Scalar::Bits { bits: 0, @@ -82,10 +85,12 @@ impl<'tcx> Scalar { } } + #[inline] pub fn zst() -> Self { Scalar::Bits { bits: 0, size: 0 } } + #[inline] pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> { let layout = cx.data_layout(); match self { @@ -100,6 +105,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> { let layout = cx.data_layout(); match self { @@ -114,6 +120,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self { let layout = cx.data_layout(); match self { @@ -128,6 +135,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool { match self { Scalar::Bits { bits, size } => { @@ -138,14 +146,53 @@ impl<'tcx> Scalar { } } + #[inline] + pub fn is_null(self) -> bool { + match self { + Scalar::Bits { bits, .. } => bits == 0, + Scalar::Ptr(_) => false + } + } + + #[inline] pub fn from_bool(b: bool) -> Self { Scalar::Bits { bits: b as u128, size: 1 } } + #[inline] pub fn from_char(c: char) -> Self { Scalar::Bits { bits: 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 } + } + + #[inline] + pub fn from_int(i: impl Into<i128>, size: Size) -> Self { + let i = i.into(); + // `into` performed sign extension, we have to truncate + 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 } + } + + #[inline] + pub fn from_f32(f: f32) -> Self { + Scalar::Bits { bits: 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 } + } + + #[inline] pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> { match self { Scalar::Bits { bits, size } => { @@ -157,6 +204,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { match self { Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage), @@ -165,6 +213,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn is_bits(self) -> bool { match self { Scalar::Bits { .. } => true, @@ -172,6 +221,7 @@ impl<'tcx> Scalar { } } + #[inline] pub fn is_ptr(self) -> bool { match self { Scalar::Ptr(_) => true, @@ -209,6 +259,13 @@ impl<'tcx> Scalar { Ok(b as u32) } + pub fn to_u64(self) -> EvalResult<'static, u64> { + let sz = Size::from_bits(64); + let b = self.to_bits(sz)?; + assert_eq!(b as u64 as u128, b); + Ok(b as u64) + } + pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> { let b = self.to_bits(cx.data_layout().pointer_size)?; assert_eq!(b as u64 as u128, b); @@ -231,12 +288,30 @@ impl<'tcx> Scalar { Ok(b as i32) } + pub fn to_i64(self) -> EvalResult<'static, i64> { + let sz = Size::from_bits(64); + let b = self.to_bits(sz)?; + let b = sign_extend(b, sz) as i128; + assert_eq!(b as i64 as i128, b); + Ok(b as i64) + } + pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> { let b = self.to_bits(cx.data_layout().pointer_size)?; let b = sign_extend(b, cx.data_layout().pointer_size) as i128; assert_eq!(b as i64 as i128, b); Ok(b as i64) } + + #[inline] + pub fn to_f32(self) -> EvalResult<'static, f32> { + Ok(f32::from_bits(self.to_u32()?)) + } + + #[inline] + pub fn to_f64(self) -> EvalResult<'static, f64> { + Ok(f64::from_bits(self.to_u64()?)) + } } impl From<Pointer> for Scalar { @@ -309,6 +384,16 @@ impl<'tcx> ScalarMaybeUndef { } #[inline(always)] + pub fn to_f32(self) -> EvalResult<'tcx, f32> { + self.not_undef()?.to_f32() + } + + #[inline(always)] + pub fn to_f64(self) -> EvalResult<'tcx, f64> { + self.not_undef()?.to_f64() + } + + #[inline(always)] pub fn to_u8(self) -> EvalResult<'tcx, u8> { self.not_undef()?.to_u8() } @@ -319,6 +404,11 @@ impl<'tcx> ScalarMaybeUndef { } #[inline(always)] + pub fn to_u64(self) -> EvalResult<'tcx, u64> { + self.not_undef()?.to_u64() + } + + #[inline(always)] pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> { self.not_undef()?.to_usize(cx) } @@ -334,6 +424,11 @@ impl<'tcx> ScalarMaybeUndef { } #[inline(always)] + pub fn to_i64(self) -> EvalResult<'tcx, i64> { + self.not_undef()?.to_i64() + } + + #[inline(always)] pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> { self.not_undef()?.to_isize(cx) } |
