Skip to content

Commit bff32fc

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 f014b94 + 3177a6f commit bff32fc

File tree

14 files changed

+69
-79
lines changed

14 files changed

+69
-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

+13-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,8 @@ pub enum Scalar<Tag=(), Id=AllocId> {
9087
Ptr(Pointer<Tag, Id>),
9188
}
9289

90+
static_assert!(SCALAR_SIZE: ::std::mem::size_of::<Scalar>() == 24);
91+
9392
impl<Tag> fmt::Display for Scalar<Tag> {
9493
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9594
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
@@ -1740,7 +1740,7 @@ macro_rules! nop_list_lift {
17401740
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
17411741
type Lifted = &'tcx List<$lifted>;
17421742
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
1743-
if self.is_empty() {
1743+
if self.is_empty() {
17441744
return Some(List::empty());
17451745
}
17461746
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
@@ -118,14 +118,11 @@ pub fn op_to_const<'tcx>(
118118
op: OpTy<'tcx>,
119119
may_normalize: bool,
120120
) -> EvalResult<'tcx, ty::Const<'tcx>> {
121-
// We do not normalize just any data. Only scalar layout and fat pointers.
121+
// We do not normalize just any data. Only scalar layout and slices.
122122
let normalize = may_normalize
123123
&& match op.layout.abi {
124124
layout::Abi::Scalar(..) => true,
125-
layout::Abi::ScalarPair(..) => {
126-
// Must be a fat pointer
127-
op.layout.ty.builtin_deref(true).is_some()
128-
},
125+
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
129126
_ => false,
130127
};
131128
let normalized_op = if normalize {
@@ -154,7 +151,7 @@ pub fn op_to_const<'tcx>(
154151
Ok(Immediate::Scalar(x)) =>
155152
ConstValue::Scalar(x.not_undef()?),
156153
Ok(Immediate::ScalarPair(a, b)) =>
157-
ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?),
154+
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
158155
};
159156
Ok(ty::Const { val, ty: op.layout.ty })
160157
}

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::ByteStr(ref data) => {
4141
let id = tcx.allocate_bytes(data);

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
}
@@ -777,9 +780,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
777780
max_fixed_len,
778781
n.unwrap_usize(cx.tcx),
779782
),
780-
(ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
783+
(ConstValue::Slice(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
781784
max_fixed_len,
782-
n.to_usize(&cx.tcx).unwrap(),
785+
n,
783786
),
784787
_ => {},
785788
}
@@ -1414,27 +1417,25 @@ fn slice_pat_covered_by_const<'tcx>(
14141417
alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
14151418
},
14161419
// a slice fat pointer to a zero length slice
1417-
(ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => {
1420+
(ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => {
14181421
if *t != tcx.types.u8 {
14191422
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
14201423
// any sort of exhaustiveness/unreachable check yet
14211424
// This solely means that we don't lint about unreachable patterns, even if some
14221425
// are definitely unreachable.
14231426
return Ok(false);
14241427
}
1425-
assert_eq!(n.to_usize(&tcx).unwrap(), 0);
14261428
&[]
14271429
},
14281430
//
1429-
(ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
1431+
(ConstValue::Slice(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
14301432
if *t != tcx.types.u8 {
14311433
// FIXME(oli-obk): can't mix const patterns with slice patterns and get
14321434
// any sort of exhaustiveness/unreachable check yet
14331435
// This solely means that we don't lint about unreachable patterns, even if some
14341436
// are definitely unreachable.
14351437
return Ok(false);
14361438
}
1437-
let n = n.to_usize(&tcx).unwrap();
14381439
tcx.alloc_map
14391440
.lock()
14401441
.unwrap_memory(ptr.alloc_id)
@@ -1766,12 +1767,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
17661767
},
17671768
ty::TyKind::Slice(t) => {
17681769
match value.val {
1769-
ConstValue::ScalarPair(ptr, n) => (
1770+
ConstValue::Slice(ptr, n) => (
17701771
ptr.to_ptr().ok().map(|ptr| (
17711772
ptr,
17721773
cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
17731774
)),
1774-
n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
1775+
n,
17751776
t,
17761777
),
17771778
_ => span_bug!(

src/librustc_mir/hair/pattern/mod.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -1215,25 +1215,21 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
12151215
if let ty::Str = ty.value.sty {
12161216
match (a.val, b.val) {
12171217
(
1218-
ConstValue::ScalarPair(
1218+
ConstValue::Slice(
12191219
Scalar::Ptr(ptr_a),
12201220
len_a,
12211221
),
1222-
ConstValue::ScalarPair(
1222+
ConstValue::Slice(
12231223
Scalar::Ptr(ptr_b),
12241224
len_b,
12251225
),
12261226
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
1227-
if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
1228-
if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
1229-
if len_a == len_b {
1230-
let map = tcx.alloc_map.lock();
1231-
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1232-
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1233-
if alloc_a.bytes.len() as u128 == len_a {
1234-
return from_bool(alloc_a == alloc_b);
1235-
}
1236-
}
1227+
if len_a == len_b {
1228+
let map = tcx.alloc_map.lock();
1229+
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1230+
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1231+
if alloc_a.bytes.len() as u64 == len_a {
1232+
return from_bool(alloc_a == alloc_b);
12371233
}
12381234
}
12391235
}

src/librustc_mir/interpret/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
561561
MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
562562
).with_default_tag())
563563
},
564-
ConstValue::ScalarPair(a, b) =>
564+
ConstValue::Slice(a, b) =>
565565
Ok(Operand::Immediate(Immediate::ScalarPair(
566566
a.into(),
567-
b.into(),
567+
Scalar::from_uint(b, self.tcx.data_layout.pointer_size).into(),
568568
)).with_default_tag()),
569569
ConstValue::Scalar(x) =>
570570
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
@@ -1261,12 +1261,7 @@ fn collect_const<'a, 'tcx>(
12611261
debug!("visiting const {:?}", constant);
12621262

12631263
match constant.val {
1264-
ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
1265-
collect_miri(tcx, a.alloc_id, output);
1266-
collect_miri(tcx, b.alloc_id, output);
1267-
}
1268-
ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
1269-
ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
1264+
ConstValue::Slice(Scalar::Ptr(ptr), _) |
12701265
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
12711266
collect_miri(tcx, ptr.alloc_id, output),
12721267
ConstValue::ByRef(_id, alloc, _offset) => {

0 commit comments

Comments
 (0)