Skip to content

Commit cdeef61

Browse files
committed
move some Scalar helpers from miri here, and use them where appropriate
1 parent 29e6aab commit cdeef61

File tree

13 files changed

+207
-178
lines changed

13 files changed

+207
-178
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,14 @@ pub struct GlobalId<'tcx> {
8585
pub trait PointerArithmetic: layout::HasDataLayout {
8686
// These are not supposed to be overridden.
8787

88+
#[inline(always)]
89+
fn pointer_size(self) -> Size {
90+
self.data_layout().pointer_size
91+
}
92+
8893
//// Trunace the given value to the pointer size; also return whether there was an overflow
8994
fn truncate_to_ptr(self, val: u128) -> (u64, bool) {
90-
let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits();
95+
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
9196
((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
9297
}
9398

src/librustc/mir/interpret/value.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ty::layout::{HasDataLayout, Size};
1414
use ty::subst::Substs;
1515
use hir::def_id::DefId;
1616

17-
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend};
17+
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
1818

1919
/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
2020
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
@@ -58,6 +58,7 @@ impl<'tcx> ConstValue<'tcx> {
5858
self.try_to_scalar()?.to_ptr().ok()
5959
}
6060

61+
#[inline]
6162
pub fn new_slice(
6263
val: Scalar,
6364
len: u64,
@@ -69,23 +70,27 @@ impl<'tcx> ConstValue<'tcx> {
6970
}.into())
7071
}
7172

73+
#[inline]
7274
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
7375
ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into())
7476
}
7577
}
7678

7779
impl<'tcx> Scalar {
80+
#[inline]
7881
pub fn ptr_null(cx: impl HasDataLayout) -> Self {
7982
Scalar::Bits {
8083
bits: 0,
8184
size: cx.data_layout().pointer_size.bytes() as u8,
8285
}
8386
}
8487

88+
#[inline]
8589
pub fn zst() -> Self {
8690
Scalar::Bits { bits: 0, size: 0 }
8791
}
8892

93+
#[inline]
8994
pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
9095
let layout = cx.data_layout();
9196
match self {
@@ -100,6 +105,7 @@ impl<'tcx> Scalar {
100105
}
101106
}
102107

108+
#[inline]
103109
pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
104110
let layout = cx.data_layout();
105111
match self {
@@ -114,6 +120,7 @@ impl<'tcx> Scalar {
114120
}
115121
}
116122

123+
#[inline]
117124
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
118125
let layout = cx.data_layout();
119126
match self {
@@ -128,6 +135,7 @@ impl<'tcx> Scalar {
128135
}
129136
}
130137

138+
#[inline]
131139
pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
132140
match self {
133141
Scalar::Bits { bits, size } => {
@@ -138,14 +146,53 @@ impl<'tcx> Scalar {
138146
}
139147
}
140148

149+
#[inline]
150+
pub fn is_null(self) -> bool {
151+
match self {
152+
Scalar::Bits { bits, .. } => bits == 0,
153+
Scalar::Ptr(_) => false
154+
}
155+
}
156+
157+
#[inline]
141158
pub fn from_bool(b: bool) -> Self {
142159
Scalar::Bits { bits: b as u128, size: 1 }
143160
}
144161

162+
#[inline]
145163
pub fn from_char(c: char) -> Self {
146164
Scalar::Bits { bits: c as u128, size: 4 }
147165
}
148166

167+
#[inline]
168+
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
169+
let i = i.into();
170+
debug_assert_eq!(truncate(i, size), i,
171+
"Unsigned value {} does not fit in {} bits", i, size.bits());
172+
Scalar::Bits { bits: i, size: size.bytes() as u8 }
173+
}
174+
175+
#[inline]
176+
pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
177+
let i = i.into();
178+
// `into` performed sign extension, we have to truncate
179+
let truncated = truncate(i as u128, size);
180+
debug_assert_eq!(sign_extend(truncated, size) as i128, i,
181+
"Signed value {} does not fit in {} bits", i, size.bits());
182+
Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
183+
}
184+
185+
#[inline]
186+
pub fn from_f32(f: f32) -> Self {
187+
Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
188+
}
189+
190+
#[inline]
191+
pub fn from_f64(f: f64) -> Self {
192+
Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
193+
}
194+
195+
#[inline]
149196
pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
150197
match self {
151198
Scalar::Bits { bits, size } => {
@@ -157,6 +204,7 @@ impl<'tcx> Scalar {
157204
}
158205
}
159206

207+
#[inline]
160208
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
161209
match self {
162210
Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
@@ -165,13 +213,15 @@ impl<'tcx> Scalar {
165213
}
166214
}
167215

216+
#[inline]
168217
pub fn is_bits(self) -> bool {
169218
match self {
170219
Scalar::Bits { .. } => true,
171220
_ => false,
172221
}
173222
}
174223

224+
#[inline]
175225
pub fn is_ptr(self) -> bool {
176226
match self {
177227
Scalar::Ptr(_) => true,
@@ -209,6 +259,13 @@ impl<'tcx> Scalar {
209259
Ok(b as u32)
210260
}
211261

262+
pub fn to_u64(self) -> EvalResult<'static, u64> {
263+
let sz = Size::from_bits(64);
264+
let b = self.to_bits(sz)?;
265+
assert_eq!(b as u64 as u128, b);
266+
Ok(b as u64)
267+
}
268+
212269
pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
213270
let b = self.to_bits(cx.data_layout().pointer_size)?;
214271
assert_eq!(b as u64 as u128, b);
@@ -231,12 +288,30 @@ impl<'tcx> Scalar {
231288
Ok(b as i32)
232289
}
233290

291+
pub fn to_i64(self) -> EvalResult<'static, i64> {
292+
let sz = Size::from_bits(64);
293+
let b = self.to_bits(sz)?;
294+
let b = sign_extend(b, sz) as i128;
295+
assert_eq!(b as i64 as i128, b);
296+
Ok(b as i64)
297+
}
298+
234299
pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
235300
let b = self.to_bits(cx.data_layout().pointer_size)?;
236301
let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
237302
assert_eq!(b as i64 as i128, b);
238303
Ok(b as i64)
239304
}
305+
306+
#[inline]
307+
pub fn to_f32(self) -> EvalResult<'static, f32> {
308+
Ok(f32::from_bits(self.to_u32()?))
309+
}
310+
311+
#[inline]
312+
pub fn to_f64(self) -> EvalResult<'static, f64> {
313+
Ok(f64::from_bits(self.to_u64()?))
314+
}
240315
}
241316

242317
impl From<Pointer> for Scalar {
@@ -308,6 +383,16 @@ impl<'tcx> ScalarMaybeUndef {
308383
self.not_undef()?.to_char()
309384
}
310385

386+
#[inline(always)]
387+
pub fn to_f32(self) -> EvalResult<'tcx, f32> {
388+
self.not_undef()?.to_f32()
389+
}
390+
391+
#[inline(always)]
392+
pub fn to_f64(self) -> EvalResult<'tcx, f64> {
393+
self.not_undef()?.to_f64()
394+
}
395+
311396
#[inline(always)]
312397
pub fn to_u8(self) -> EvalResult<'tcx, u8> {
313398
self.not_undef()?.to_u8()
@@ -318,6 +403,11 @@ impl<'tcx> ScalarMaybeUndef {
318403
self.not_undef()?.to_u32()
319404
}
320405

406+
#[inline(always)]
407+
pub fn to_u64(self) -> EvalResult<'tcx, u64> {
408+
self.not_undef()?.to_u64()
409+
}
410+
321411
#[inline(always)]
322412
pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
323413
self.not_undef()?.to_usize(cx)
@@ -333,6 +423,11 @@ impl<'tcx> ScalarMaybeUndef {
333423
self.not_undef()?.to_i32()
334424
}
335425

426+
#[inline(always)]
427+
pub fn to_i64(self) -> EvalResult<'tcx, i64> {
428+
self.not_undef()?.to_i64()
429+
}
430+
336431
#[inline(always)]
337432
pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
338433
self.not_undef()?.to_isize(cx)

0 commit comments

Comments
 (0)