Skip to content

Commit 1dcbcb9

Browse files
authored
Rollup merge of rust-lang#57442 - oli-obk:lazy_const, r=RalfJung
Simplify `ConstValue::ScalarPair` While looking at rust-lang#57432 I realized that some of our types for representing constants are very big. This reduces `LazyConst` to 3/4th of its original size and simplifies some code around slices at the same time. r? @RalfJung
2 parents 5e446d5 + d7f57d4 commit 1dcbcb9

File tree

14 files changed

+70
-79
lines changed

14 files changed

+70
-79
lines changed

src/librustc/ich/impls_ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ impl_stable_hash_for!(struct ty::FieldDef {
302302
impl_stable_hash_for!(
303303
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
304304
Scalar(val),
305-
ScalarPair(a, b),
305+
Slice(a, b),
306306
ByRef(id, alloc, offset),
307307
}
308308
);

src/librustc/mir/interpret/pointer.rs

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub struct Pointer<Tag=(),Id=AllocId> {
7676
pub tag: Tag,
7777
}
7878

79+
static_assert!(POINTER_SIZE: ::std::mem::size_of::<Pointer>() == 16);
80+
7981
/// Produces a `Pointer` which points to the beginning of the Allocation
8082
impl From<AllocId> for Pointer {
8183
#[inline(always)]

src/librustc/mir/interpret/value.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,28 @@ pub enum ConstValue<'tcx> {
2222
/// Not using the enum `Value` to encode that this must not be `Undef`
2323
Scalar(Scalar),
2424

25-
/// Used only for *fat pointers* with layout::abi::ScalarPair
25+
/// Used only for slices and strings (`&[T]`, `&str`, `*const [T]`, `*mut str`, `Box<str>`, ...)
2626
///
27-
/// Needed for pattern matching code related to slices and strings.
28-
ScalarPair(Scalar, Scalar),
27+
/// Empty slices don't necessarily have an address backed by an `AllocId`, thus we also need to
28+
/// enable integer pointers. The `Scalar` type covers exactly those two cases. While we could
29+
/// create dummy-`AllocId`s, the additional code effort for the conversions doesn't seem worth
30+
/// it.
31+
Slice(Scalar, u64),
2932

3033
/// An allocation + offset into the allocation.
3134
/// Invariant: The AllocId matches the allocation.
3235
ByRef(AllocId, &'tcx Allocation, Size),
3336
}
3437

38+
#[cfg(target_arch = "x86_64")]
39+
static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 40);
40+
3541
impl<'tcx> ConstValue<'tcx> {
3642
#[inline]
3743
pub fn try_to_scalar(&self) -> Option<Scalar> {
3844
match *self {
3945
ConstValue::ByRef(..) |
40-
ConstValue::ScalarPair(..) => None,
46+
ConstValue::Slice(..) => None,
4147
ConstValue::Scalar(val) => Some(val),
4248
}
4349
}
@@ -56,17 +62,8 @@ impl<'tcx> ConstValue<'tcx> {
5662
pub fn new_slice(
5763
val: Scalar,
5864
len: u64,
59-
cx: &impl HasDataLayout
6065
) -> Self {
61-
ConstValue::ScalarPair(val, Scalar::Bits {
62-
bits: len as u128,
63-
size: cx.data_layout().pointer_size.bytes() as u8,
64-
})
65-
}
66-
67-
#[inline]
68-
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
69-
ConstValue::ScalarPair(val, Scalar::Ptr(vtable))
66+
ConstValue::Slice(val, len)
7067
}
7168
}
7269

@@ -90,6 +87,9 @@ pub enum Scalar<Tag=(), Id=AllocId> {
9087
Ptr(Pointer<Tag, Id>),
9188
}
9289

90+
#[cfg(target_arch = "x86_64")]
91+
static_assert!(SCALAR_SIZE: ::std::mem::size_of::<Scalar>() == 24);
92+
9393
impl<Tag> fmt::Display for Scalar<Tag> {
9494
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9595
match self {

src/librustc/mir/mod.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -2702,23 +2702,21 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
27022702
return write!(f, "{}", item_path_str(did));
27032703
}
27042704
// print string literals
2705-
if let ConstValue::ScalarPair(ptr, len) = value {
2705+
if let ConstValue::Slice(ptr, len) = value {
27062706
if let Scalar::Ptr(ptr) = ptr {
2707-
if let Scalar::Bits { bits: len, .. } = len {
2708-
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
2709-
return ty::tls::with(|tcx| {
2710-
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
2711-
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
2712-
assert_eq!(len as usize as u128, len);
2713-
let slice =
2714-
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
2715-
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
2716-
write!(f, "{:?}", s)
2717-
} else {
2718-
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
2719-
}
2720-
});
2721-
}
2707+
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
2708+
return ty::tls::with(|tcx| {
2709+
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
2710+
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
2711+
assert_eq!(len as usize as u64, len);
2712+
let slice =
2713+
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
2714+
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
2715+
write!(f, "{:?}", s)
2716+
} else {
2717+
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
2718+
}
2719+
});
27222720
}
27232721
}
27242722
}

src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ macro_rules! nop_list_lift {
17671767
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
17681768
type Lifted = &'tcx List<$lifted>;
17691769
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
1770-
if self.is_empty() {
1770+
if self.is_empty() {
17711771
return Some(List::empty());
17721772
}
17731773
if tcx.interners.arena.in_arena(*self as *const _) {

src/librustc/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
498498
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
499499
match *self {
500500
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
501-
ConstValue::ScalarPair(x, y) => Some(ConstValue::ScalarPair(x, y)),
501+
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
502502
ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef(
503503
x, alloc.lift_to_tcx(tcx)?, z,
504504
)),

src/librustc/ty/sty.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2063,6 +2063,9 @@ pub enum LazyConst<'tcx> {
20632063
Evaluated(Const<'tcx>),
20642064
}
20652065

2066+
#[cfg(target_arch = "x86_64")]
2067+
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
2068+
20662069
impl<'tcx> LazyConst<'tcx> {
20672070
pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
20682071
match self {
@@ -2089,6 +2092,9 @@ pub struct Const<'tcx> {
20892092
pub val: ConstValue<'tcx>,
20902093
}
20912094

2095+
#[cfg(target_arch = "x86_64")]
2096+
static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 48);
2097+
20922098
impl<'tcx> Const<'tcx> {
20932099
#[inline]
20942100
pub fn from_scalar(

src/librustc_codegen_ssa/mir/operand.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,17 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
8888
);
8989
OperandValue::Immediate(llval)
9090
},
91-
ConstValue::ScalarPair(a, b) => {
92-
let (a_scalar, b_scalar) = match layout.abi {
93-
layout::Abi::ScalarPair(ref a, ref b) => (a, b),
91+
ConstValue::Slice(a, b) => {
92+
let a_scalar = match layout.abi {
93+
layout::Abi::ScalarPair(ref a, _) => a,
9494
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
9595
};
9696
let a_llval = bx.cx().scalar_to_backend(
9797
a,
9898
a_scalar,
9999
bx.cx().scalar_pair_element_backend_type(layout, 0, true),
100100
);
101-
let b_llval = bx.cx().scalar_to_backend(
102-
b,
103-
b_scalar,
104-
bx.cx().scalar_pair_element_backend_type(layout, 1, true),
105-
);
101+
let b_llval = bx.cx().const_usize(b);
106102
OperandValue::Pair(a_llval, b_llval)
107103
},
108104
ConstValue::ByRef(_, alloc, offset) => {

src/librustc_mir/const_eval.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,11 @@ pub fn op_to_const<'tcx>(
6767
op: OpTy<'tcx>,
6868
may_normalize: bool,
6969
) -> EvalResult<'tcx, ty::Const<'tcx>> {
70-
// We do not normalize just any data. Only scalar layout and fat pointers.
70+
// We do not normalize just any data. Only scalar layout and slices.
7171
let normalize = may_normalize
7272
&& match op.layout.abi {
7373
layout::Abi::Scalar(..) => true,
74-
layout::Abi::ScalarPair(..) => {
75-
// Must be a fat pointer
76-
op.layout.ty.builtin_deref(true).is_some()
77-
},
74+
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
7875
_ => false,
7976
};
8077
let normalized_op = if normalize {
@@ -103,7 +100,7 @@ pub fn op_to_const<'tcx>(
103100
Ok(Immediate::Scalar(x)) =>
104101
ConstValue::Scalar(x.not_undef()?),
105102
Ok(Immediate::ScalarPair(a, b)) =>
106-
ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?),
103+
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
107104
};
108105
Ok(ty::Const { val, ty: op.layout.ty })
109106
}

src/librustc_mir/hair/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
3535
LitKind::Str(ref s, _) => {
3636
let s = s.as_str();
3737
let id = tcx.allocate_bytes(s.as_bytes());
38-
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
38+
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64)
3939
},
4040
LitKind::Err(ref s) => {
4141
let s = s.as_str();

src/librustc_mir/hair/pattern/_match.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,16 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
221221
// unsize array to slice if pattern is array but match value or other patterns are slice
222222
(ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
223223
assert_eq!(t, u);
224-
ConstValue::ScalarPair(
224+
ConstValue::Slice(
225225
Scalar::Ptr(p),
226-
n.map_evaluated(|val| val.val.try_to_scalar()).unwrap(),
226+
n.map_evaluated(|val| val.val.try_to_scalar())
227+
.unwrap()
228+
.to_usize(&self.tcx)
229+
.unwrap(),
227230
)
228231
},
229232
// fat pointers stay the same
230-
(ConstValue::ScalarPair(..), _, _) => val,
233+
(ConstValue::Slice(..), _, _) => val,
231234
// FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
232235
_ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
233236
}
@@ -788,9 +791,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
788791
max_fixed_len,
789792
n.unwrap_usize(cx.tcx),
790793
),
791-
(ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
794+
(ConstValue::Slice(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
792795
max_fixed_len,
793-
n.to_usize(&cx.tcx).unwrap(),
796+
n,
794797
),
795798
_ => {},
796799
}
@@ -1432,27 +1435,25 @@ fn slice_pat_covered_by_const<'tcx>(
14321435
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
14331436
},
14341437
// a slice fat pointer to a zero length slice
1435-
(ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => {
1438+
(ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => {
14361439
if *t != tcx.types.u8 {
14371440
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
14381441
// any sort of exhaustiveness/unreachable check yet
14391442
// This solely means that we don't lint about unreachable patterns, even if some
14401443
// are definitely unreachable.
14411444
return Ok(false);
14421445
}
1443-
assert_eq!(n.to_usize(&tcx).unwrap(), 0);
14441446
&[]
14451447
},
14461448
//
1447-
(ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
1449+
(ConstValue::Slice(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
14481450
if *t != tcx.types.u8 {
14491451
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
14501452
// any sort of exhaustiveness/unreachable check yet
14511453
// This solely means that we don't lint about unreachable patterns, even if some
14521454
// are definitely unreachable.
14531455
return Ok(false);
14541456
}
1455-
let n = n.to_usize(&tcx).unwrap();
14561457
tcx.alloc_map
14571458
.lock()
14581459
.unwrap_memory(ptr.alloc_id)
@@ -1784,12 +1785,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
17841785
},
17851786
ty::TyKind::Slice(t) => {
17861787
match value.val {
1787-
ConstValue::ScalarPair(ptr, n) => (
1788+
ConstValue::Slice(ptr, n) => (
17881789
ptr.to_ptr().ok().map(|ptr| (
17891790
ptr,
17901791
cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
17911792
)),
1792-
n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
1793+
n,
17931794
t,
17941795
),
17951796
_ => span_bug!(

src/librustc_mir/hair/pattern/mod.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -1218,25 +1218,21 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
12181218
if let ty::Str = ty.value.sty {
12191219
match (a.val, b.val) {
12201220
(
1221-
ConstValue::ScalarPair(
1221+
ConstValue::Slice(
12221222
Scalar::Ptr(ptr_a),
12231223
len_a,
12241224
),
1225-
ConstValue::ScalarPair(
1225+
ConstValue::Slice(
12261226
Scalar::Ptr(ptr_b),
12271227
len_b,
12281228
),
12291229
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
1230-
if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
1231-
if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
1232-
if len_a == len_b {
1233-
let map = tcx.alloc_map.lock();
1234-
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1235-
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1236-
if alloc_a.bytes.len() as u128 == len_a {
1237-
return from_bool(alloc_a == alloc_b);
1238-
}
1239-
}
1230+
if len_a == len_b {
1231+
let map = tcx.alloc_map.lock();
1232+
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1233+
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1234+
if alloc_a.bytes.len() as u64 == len_a {
1235+
return from_bool(alloc_a == alloc_b);
12401236
}
12411237
}
12421238
}

src/librustc_mir/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -555,10 +555,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
555555
MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
556556
).with_default_tag())
557557
},
558-
ConstValue::ScalarPair(a, b) =>
558+
ConstValue::Slice(a, b) =>
559559
Ok(Operand::Immediate(Immediate::ScalarPair(
560560
a.into(),
561-
b.into(),
561+
Scalar::from_uint(b, self.tcx.data_layout.pointer_size).into(),
562562
)).with_default_tag()),
563563
ConstValue::Scalar(x) =>
564564
Ok(Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag()),

src/librustc_mir/monomorphize/collector.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1254,12 +1254,7 @@ fn collect_const<'a, 'tcx>(
12541254
debug!("visiting const {:?}", constant);
12551255

12561256
match constant.val {
1257-
ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
1258-
collect_miri(tcx, a.alloc_id, output);
1259-
collect_miri(tcx, b.alloc_id, output);
1260-
}
1261-
ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
1262-
ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
1257+
ConstValue::Slice(Scalar::Ptr(ptr), _) |
12631258
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
12641259
collect_miri(tcx, ptr.alloc_id, output),
12651260
ConstValue::ByRef(_id, alloc, _offset) => {

0 commit comments

Comments
 (0)