Skip to content

Commit ede8a6c

Browse files
authored
Rollup merge of rust-lang#61164 - RalfJung:scalar, r=oli-obk
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
2 parents a7e8a10 + fe19ed8 commit ede8a6c

File tree

20 files changed

+181
-195
lines changed

20 files changed

+181
-195
lines changed

src/librustc/mir/interpret/allocation.rs

+3-13
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use super::{
44
Pointer, EvalResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar,
5-
truncate,
65
};
76

87
use crate::ty::layout::{Size, Align};
@@ -407,18 +406,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
407406
ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
408407
};
409408

410-
let bytes = match val {
411-
Scalar::Ptr(val) => {
412-
assert_eq!(type_size, cx.data_layout().pointer_size);
413-
val.offset.bytes() as u128
414-
}
415-
416-
Scalar::Bits { bits, size } => {
417-
assert_eq!(size as u64, type_size.bytes());
418-
debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
419-
"Unexpected value of size {} when writing to memory", size);
420-
bits
421-
},
409+
let bytes = match val.to_bits_or_ptr(type_size, cx) {
410+
Err(val) => val.offset.bytes() as u128,
411+
Ok(data) => data,
422412
};
423413

424414
let endian = cx.data_layout().endian;

src/librustc/mir/interpret/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ impl<'tcx> AllocMap<'tcx> {
349349
/// illegal and will likely ICE.
350350
/// This function exists to allow const eval to detect the difference between evaluation-
351351
/// local dangling pointers and allocations in constants/statics.
352+
#[inline]
352353
pub fn get(&self, id: AllocId) -> Option<AllocKind<'tcx>> {
353354
self.id_to_kind.get(&id).cloned()
354355
}
@@ -397,6 +398,7 @@ impl<'tcx> AllocMap<'tcx> {
397398
// Methods to access integers in the target endianness
398399
////////////////////////////////////////////////////////////////////////////////
399400

401+
#[inline]
400402
pub fn write_target_uint(
401403
endianness: layout::Endian,
402404
mut target: &mut [u8],
@@ -409,6 +411,7 @@ pub fn write_target_uint(
409411
}
410412
}
411413

414+
#[inline]
412415
pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
413416
match endianness {
414417
layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
@@ -420,17 +423,30 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
420423
// Methods to facilitate working with signed integers stored in a u128
421424
////////////////////////////////////////////////////////////////////////////////
422425

426+
/// Truncate `value` to `size` bits and then sign-extend it to 128 bits
427+
/// (i.e., if it is negative, fill with 1's on the left).
428+
#[inline]
423429
pub fn sign_extend(value: u128, size: Size) -> u128 {
424430
let size = size.bits();
431+
if size == 0 {
432+
// Truncated until nothing is left.
433+
return 0;
434+
}
425435
// sign extend
426436
let shift = 128 - size;
427437
// shift the unsigned value to the left
428438
// and back to the right as signed (essentially fills with FF on the left)
429439
(((value << shift) as i128) >> shift) as u128
430440
}
431441

442+
/// Truncate `value` to `size` bits.
443+
#[inline]
432444
pub fn truncate(value: u128, size: Size) -> u128 {
433445
let size = size.bits();
446+
if size == 0 {
447+
// Truncated until nothing is left.
448+
return 0;
449+
}
434450
let shift = 128 - size;
435451
// truncate (shift left to drop out leftover values, shift right to fill with zeroes)
436452
(value << shift) >> shift

src/librustc/mir/interpret/pointer.rs

+24-21
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,48 @@ pub trait PointerArithmetic: layout::HasDataLayout {
2020
self.data_layout().pointer_size
2121
}
2222

23-
//// Trunace the given value to the pointer size; also return whether there was an overflow
23+
/// Helper function: truncate given value-"overflowed flag" pair to pointer size and
24+
/// update "overflowed flag" if there was an overflow.
25+
/// This should be called by all the other methods before returning!
2426
#[inline]
25-
fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
27+
fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
28+
let val = val as u128;
2629
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
27-
((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
28-
}
29-
30-
#[inline]
31-
fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
32-
let (res, over) = self.overflowing_offset(val, i);
33-
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
30+
((val % max_ptr_plus_1) as u64, over || val >= max_ptr_plus_1)
3431
}
3532

3633
#[inline]
3734
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
38-
let (res, over1) = val.overflowing_add(i);
39-
let (res, over2) = self.truncate_to_ptr(u128::from(res));
40-
(res, over1 || over2)
41-
}
42-
43-
#[inline]
44-
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
45-
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
46-
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
35+
let res = val.overflowing_add(i);
36+
self.truncate_to_ptr(res)
4737
}
4838

4939
// Overflow checking only works properly on the range from -u64 to +u64.
5040
#[inline]
5141
fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
5242
// FIXME: is it possible to over/underflow here?
5343
if i < 0 {
54-
// trickery to ensure that i64::min_value() works fine
55-
// this formula only works for true negative values, it panics for zero!
44+
// Trickery to ensure that i64::min_value() works fine: compute n = -i.
45+
// This formula only works for true negative values, it overflows for zero!
5646
let n = u64::max_value() - (i as u64) + 1;
57-
val.overflowing_sub(n)
47+
let res = val.overflowing_sub(n);
48+
self.truncate_to_ptr(res)
5849
} else {
5950
self.overflowing_offset(val, i as u64)
6051
}
6152
}
53+
54+
#[inline]
55+
fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
56+
let (res, over) = self.overflowing_offset(val, i);
57+
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
58+
}
59+
60+
#[inline]
61+
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
62+
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
63+
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
64+
}
6265
}
6366

6467
impl<T: layout::HasDataLayout> PointerArithmetic for T {}

0 commit comments

Comments
 (0)