Skip to content

Commit 362123d

Browse files
committed
Split the "raw integer bytes" part out of Scalar
1 parent 5629309 commit 362123d

File tree

17 files changed

+325
-184
lines changed

17 files changed

+325
-184
lines changed

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1212
use rustc_codegen_ssa::traits::*;
1313
use rustc_middle::bug;
1414
use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
15-
use rustc_middle::ty::layout::TyAndLayout;
15+
use rustc_middle::ty::{layout::TyAndLayout, ScalarInt};
1616
use rustc_span::symbol::Symbol;
1717
use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};
1818

@@ -230,12 +230,12 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
230230
fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value {
231231
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
232232
match cv {
233-
Scalar::Raw { size: 0, .. } => {
233+
Scalar::Raw(ScalarInt::ZST) => {
234234
assert_eq!(0, layout.value.size(self).bytes());
235235
self.const_undef(self.type_ix(0))
236236
}
237-
Scalar::Raw { data, size } => {
238-
assert_eq!(size as u64, layout.value.size(self).bytes());
237+
Scalar::Raw(int) => {
238+
let data = int.assert_bits(layout.value.size(self));
239239
let llval = self.const_uint_big(self.type_ix(bitsize), data);
240240
if layout.value == Pointer {
241241
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }

compiler/rustc_middle/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
2525
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
2626
#![feature(array_windows)]
27+
#![feature(assoc_char_funcs)]
2728
#![feature(backtrace)]
2829
#![feature(bool_to_option)]
2930
#![feature(box_patterns)]

compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ macro_rules! throw_inval {
7171

7272
#[macro_export]
7373
macro_rules! throw_ub {
74-
($($tt:tt)*) => { Err::<!, _>(err_ub!($($tt)*))? };
74+
($($tt:tt)*) => { Err::<!, _>($crate::err_ub!($($tt)*))? };
7575
}
7676

7777
#[macro_export]

compiler/rustc_middle/src/mir/interpret/value.rs

Lines changed: 21 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use rustc_apfloat::{
88
use rustc_macros::HashStable;
99
use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
1010

11-
use crate::ty::{ParamEnv, Ty, TyCtxt};
11+
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
1212

13-
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
13+
use super::{sign_extend, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
1414

1515
/// Represents the result of const evaluation via the `eval_to_allocation` query.
1616
#[derive(Clone, HashStable, TyEncodable, TyDecodable)]
@@ -103,12 +103,7 @@ impl<'tcx> ConstValue<'tcx> {
103103
#[derive(HashStable)]
104104
pub enum Scalar<Tag = ()> {
105105
/// The raw bytes of a simple value.
106-
Raw {
107-
/// The first `size` bytes of `data` are the value.
108-
/// Do not try to read less or more bytes than that. The remaining bytes must be 0.
109-
data: u128,
110-
size: u8,
111-
},
106+
Raw(ScalarInt),
112107

113108
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
114109
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
@@ -125,16 +120,7 @@ impl<Tag: fmt::Debug> fmt::Debug for Scalar<Tag> {
125120
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126121
match self {
127122
Scalar::Ptr(ptr) => write!(f, "{:?}", ptr),
128-
&Scalar::Raw { data, size } => {
129-
Scalar::check_data(data, size);
130-
if size == 0 {
131-
write!(f, "<ZST>")
132-
} else {
133-
// Format as hex number wide enough to fit any value of the given `size`.
134-
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
135-
write!(f, "0x{:>0width$x}", data, width = (size * 2) as usize)
136-
}
137-
}
123+
Scalar::Raw(int) => write!(f, "{:?}", int),
138124
}
139125
}
140126
}
@@ -163,29 +149,14 @@ impl<Tag> From<Double> for Scalar<Tag> {
163149
}
164150

165151
impl Scalar<()> {
166-
/// Make sure the `data` fits in `size`.
167-
/// This is guaranteed by all constructors here, but since the enum variants are public,
168-
/// it could still be violated (even though no code outside this file should
169-
/// construct `Scalar`s).
170-
#[inline(always)]
171-
fn check_data(data: u128, size: u8) {
172-
debug_assert_eq!(
173-
truncate(data, Size::from_bytes(u64::from(size))),
174-
data,
175-
"Scalar value {:#x} exceeds size of {} bytes",
176-
data,
177-
size
178-
);
179-
}
180-
181152
/// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise.
182153
///
183154
/// Used by `MemPlace::replace_tag`.
184155
#[inline]
185156
pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
186157
match self {
187158
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
188-
Scalar::Raw { data, size } => Scalar::Raw { data, size },
159+
Scalar::Raw(int) => Scalar::Raw(int),
189160
}
190161
}
191162
}
@@ -198,18 +169,18 @@ impl<'tcx, Tag> Scalar<Tag> {
198169
pub fn erase_tag(self) -> Scalar {
199170
match self {
200171
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
201-
Scalar::Raw { data, size } => Scalar::Raw { data, size },
172+
Scalar::Raw(int) => Scalar::Raw(int),
202173
}
203174
}
204175

205176
#[inline]
206177
pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
207-
Scalar::Raw { data: 0, size: cx.data_layout().pointer_size.bytes() as u8 }
178+
Scalar::Raw(ScalarInt::null(cx.data_layout().pointer_size))
208179
}
209180

210181
#[inline]
211182
pub fn zst() -> Self {
212-
Scalar::Raw { data: 0, size: 0 }
183+
Scalar::Raw(ScalarInt::zst())
213184
}
214185

215186
#[inline(always)]
@@ -220,10 +191,7 @@ impl<'tcx, Tag> Scalar<Tag> {
220191
f_ptr: impl FnOnce(Pointer<Tag>) -> InterpResult<'tcx, Pointer<Tag>>,
221192
) -> InterpResult<'tcx, Self> {
222193
match self {
223-
Scalar::Raw { data, size } => {
224-
assert_eq!(u64::from(size), dl.pointer_size.bytes());
225-
Ok(Scalar::Raw { data: u128::from(f_int(u64::try_from(data).unwrap())?), size })
226-
}
194+
Scalar::Raw(int) => Ok(Scalar::Raw(int.ptr_sized_op(dl, f_int)?)),
227195
Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)),
228196
}
229197
}
@@ -264,24 +232,17 @@ impl<'tcx, Tag> Scalar<Tag> {
264232

265233
#[inline]
266234
pub fn from_bool(b: bool) -> Self {
267-
// Guaranteed to be truncated and does not need sign extension.
268-
Scalar::Raw { data: b as u128, size: 1 }
235+
Scalar::Raw(b.into())
269236
}
270237

271238
#[inline]
272239
pub fn from_char(c: char) -> Self {
273-
// Guaranteed to be truncated and does not need sign extension.
274-
Scalar::Raw { data: c as u128, size: 4 }
240+
Scalar::Raw(c.into())
275241
}
276242

277243
#[inline]
278244
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
279-
let i = i.into();
280-
if truncate(i, size) == i {
281-
Some(Scalar::Raw { data: i, size: size.bytes() as u8 })
282-
} else {
283-
None
284-
}
245+
ScalarInt::try_from_uint(i, size).map(Scalar::Raw)
285246
}
286247

287248
#[inline]
@@ -293,26 +254,22 @@ impl<'tcx, Tag> Scalar<Tag> {
293254

294255
#[inline]
295256
pub fn from_u8(i: u8) -> Self {
296-
// Guaranteed to be truncated and does not need sign extension.
297-
Scalar::Raw { data: i.into(), size: 1 }
257+
Scalar::Raw(i.into())
298258
}
299259

300260
#[inline]
301261
pub fn from_u16(i: u16) -> Self {
302-
// Guaranteed to be truncated and does not need sign extension.
303-
Scalar::Raw { data: i.into(), size: 2 }
262+
Scalar::Raw(i.into())
304263
}
305264

306265
#[inline]
307266
pub fn from_u32(i: u32) -> Self {
308-
// Guaranteed to be truncated and does not need sign extension.
309-
Scalar::Raw { data: i.into(), size: 4 }
267+
Scalar::Raw(i.into())
310268
}
311269

312270
#[inline]
313271
pub fn from_u64(i: u64) -> Self {
314-
// Guaranteed to be truncated and does not need sign extension.
315-
Scalar::Raw { data: i.into(), size: 8 }
272+
Scalar::Raw(i.into())
316273
}
317274

318275
#[inline]
@@ -322,14 +279,7 @@ impl<'tcx, Tag> Scalar<Tag> {
322279

323280
#[inline]
324281
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
325-
let i = i.into();
326-
// `into` performed sign extension, we have to truncate
327-
let truncated = truncate(i as u128, size);
328-
if sign_extend(truncated, size) as i128 == i {
329-
Some(Scalar::Raw { data: truncated, size: size.bytes() as u8 })
330-
} else {
331-
None
332-
}
282+
ScalarInt::try_from_int(i, size).map(Scalar::Raw)
333283
}
334284

335285
#[inline]
@@ -366,14 +316,12 @@ impl<'tcx, Tag> Scalar<Tag> {
366316

367317
#[inline]
368318
pub fn from_f32(f: Single) -> Self {
369-
// We trust apfloat to give us properly truncated data.
370-
Scalar::Raw { data: f.to_bits(), size: 4 }
319+
Scalar::Raw(f.into())
371320
}
372321

373322
#[inline]
374323
pub fn from_f64(f: Double) -> Self {
375-
// We trust apfloat to give us properly truncated data.
376-
Scalar::Raw { data: f.to_bits(), size: 8 }
324+
Scalar::Raw(f.into())
377325
}
378326

379327
/// This is very rarely the method you want! You should dispatch on the type
@@ -388,11 +336,7 @@ impl<'tcx, Tag> Scalar<Tag> {
388336
) -> Result<u128, Pointer<Tag>> {
389337
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
390338
match self {
391-
Scalar::Raw { data, size } => {
392-
assert_eq!(target_size.bytes(), u64::from(size));
393-
Scalar::check_data(data, size);
394-
Ok(data)
395-
}
339+
Scalar::Raw(int) => Ok(int.assert_bits(target_size)),
396340
Scalar::Ptr(ptr) => {
397341
assert_eq!(target_size, cx.data_layout().pointer_size);
398342
Err(ptr)
@@ -406,16 +350,7 @@ impl<'tcx, Tag> Scalar<Tag> {
406350
fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
407351
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
408352
match self {
409-
Scalar::Raw { data, size } => {
410-
if target_size.bytes() != u64::from(size) {
411-
throw_ub!(ScalarSizeMismatch {
412-
target_size: target_size.bytes(),
413-
data_size: u64::from(size),
414-
});
415-
}
416-
Scalar::check_data(data, size);
417-
Ok(data)
418-
}
353+
Scalar::Raw(int) => int.to_bits(target_size),
419354
Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes),
420355
}
421356
}

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ use rustc_index::vec::{Idx, IndexVec};
2828
use rustc_serialize::{Decodable, Encodable};
2929
use rustc_span::symbol::Symbol;
3030
use rustc_span::{Span, DUMMY_SP};
31-
use rustc_target::abi;
3231
use rustc_target::asm::InlineAsmRegOrRegClass;
3332
use std::borrow::Cow;
3433
use std::fmt::{self, Debug, Display, Formatter, Write};
@@ -1952,10 +1951,10 @@ impl<'tcx> Operand<'tcx> {
19521951
.layout_of(param_env_and_ty)
19531952
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
19541953
.size;
1955-
let scalar_size = abi::Size::from_bytes(match val {
1956-
Scalar::Raw { size, .. } => size,
1954+
let scalar_size = match val {
1955+
Scalar::Raw(int) => int.size(),
19571956
_ => panic!("Invalid scalar type {:?}", val),
1958-
});
1957+
};
19591958
scalar_size == type_size
19601959
});
19611960
Operand::Constant(box Constant {

0 commit comments

Comments
 (0)