Skip to content

Commit e3fad34

Browse files
committed
Give an AllocId to ConstValue::Slice.
1 parent aa51a9b commit e3fad34

File tree

68 files changed

+591
-131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+591
-131
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@ pub(crate) fn codegen_const_value<'tcx>(
210210
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
211211
layout,
212212
),
213-
ConstValue::Slice { data, meta } => {
214-
let alloc_id = fx.tcx.reserve_and_set_memory_alloc(data);
213+
ConstValue::Slice { alloc_id, meta, phantom: _ } => {
215214
let ptr = pointer_for_allocation(fx, alloc_id).get_addr(fx);
216215
let len = fx.bcx.ins().iconst(fx.pointer_type, meta as i64);
217216
CValue::by_val_pair(ptr, len, layout)

compiler/rustc_codegen_ssa/src/mir/operand.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
154154
OperandValue::Immediate(llval)
155155
}
156156
ConstValue::ZeroSized => return OperandRef::zero_sized(layout),
157-
ConstValue::Slice { data, meta } => {
157+
ConstValue::Slice { alloc_id, meta, phantom: _ } => {
158158
let BackendRepr::ScalarPair(a_scalar, _) = layout.backend_repr else {
159159
bug!("from_const: invalid ScalarPair layout: {:#?}", layout);
160160
};
161-
let a = Scalar::from_pointer(
162-
Pointer::new(bx.tcx().reserve_and_set_memory_alloc(data).into(), Size::ZERO),
163-
&bx.tcx(),
164-
);
161+
let a = Scalar::from_pointer(Pointer::new(alloc_id.into(), Size::ZERO), &bx.tcx());
165162
let a_llval = bx.scalar_to_backend(
166163
a,
167164
a_scalar,

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,9 @@ pub(super) fn op_to_const<'tcx>(
236236
let (prov, offset) =
237237
ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
238238
let alloc_id = prov.alloc_id();
239-
let data = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
240239
assert!(offset == abi::Size::ZERO, "{}", msg);
241240
let meta = b.to_target_usize(ecx).expect(msg);
242-
ConstValue::Slice { data, meta }
241+
ConstValue::Slice { alloc_id, meta, phantom: std::marker::PhantomData }
243242
}
244243
Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
245244
},

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
//! and miri.
44
55
use std::assert_matches::assert_matches;
6+
use std::marker::PhantomData;
67

78
use rustc_abi::{FieldIdx, Size};
89
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
10+
use rustc_middle::mir::interpret::CTFE_ALLOC_SALT;
911
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1012
use rustc_middle::ty::layout::TyAndLayout;
1113
use rustc_middle::ty::{Ty, TyCtxt};
@@ -16,17 +18,18 @@ use tracing::trace;
1618
use super::memory::MemoryKind;
1719
use super::util::ensure_monomorphic_enough;
1820
use super::{
19-
Allocation, CheckInAllocMsg, ConstAllocation, ImmTy, InterpCx, InterpResult, Machine, OpTy,
20-
PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format,
21-
interp_ok, throw_inval, throw_ub_custom, throw_ub_format,
21+
AllocId, CheckInAllocMsg, ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Pointer,
22+
PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok, throw_inval,
23+
throw_ub_custom, throw_ub_format,
2224
};
2325
use crate::fluent_generated as fluent;
2426

2527
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
26-
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
28+
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (AllocId, u64) {
2729
let path = crate::util::type_name(tcx, ty);
28-
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes(), ());
29-
tcx.mk_const_alloc(alloc)
30+
let bytes = path.into_bytes();
31+
let len = bytes.len().try_into().unwrap();
32+
(tcx.allocate_bytes_dedup(bytes, CTFE_ALLOC_SALT), len)
3033
}
3134
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
3235
/// Generates a value of `TypeId` for `ty` in-place.
@@ -75,8 +78,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
7578
sym::type_name => {
7679
let tp_ty = instance.args.type_at(0);
7780
ensure_monomorphic_enough(tcx, tp_ty)?;
78-
let alloc = alloc_type_name(tcx, tp_ty);
79-
let val = ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() };
81+
let (alloc_id, meta) = alloc_type_name(tcx, tp_ty);
82+
let val = ConstValue::Slice { alloc_id, meta, phantom: PhantomData };
8083
let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?;
8184
self.copy_op(&val, dest)?;
8285
}

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -860,9 +860,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
860860
}
861861
mir::ConstValue::Scalar(x) => adjust_scalar(x)?.into(),
862862
mir::ConstValue::ZeroSized => Immediate::Uninit,
863-
mir::ConstValue::Slice { data, meta } => {
863+
mir::ConstValue::Slice { alloc_id, meta, phantom: _ } => {
864864
// This is const data, no mutation allowed.
865-
let alloc_id = self.tcx.reserve_and_set_memory_alloc(data);
866865
let ptr = Pointer::new(CtfeProvenance::from(alloc_id).as_immutable(), Size::ZERO);
867866
Immediate::new_slice(self.global_root_pointer(ptr)?.into(), meta, self)
868867
}

compiler/rustc_middle/src/mir/consts.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
99
use rustc_type_ir::TypeVisitableExt;
1010

1111
use super::interpret::ReportedErrorInfo;
12-
use crate::mir::interpret::{
13-
AllocId, AllocRange, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar, alloc_range,
14-
};
12+
use crate::mir::interpret::{AllocId, AllocRange, ErrorHandled, GlobalAlloc, Scalar, alloc_range};
1513
use crate::mir::{Promoted, pretty_print_const_value};
1614
use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
1715
use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt};
@@ -32,8 +30,8 @@ pub struct ConstAlloc<'tcx> {
3230

3331
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
3432
/// array length computations, enum discriminants and the pattern matching logic.
35-
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
36-
#[derive(HashStable, Lift)]
33+
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Lift, Hash)]
34+
#[derive(HashStable)]
3735
pub enum ConstValue<'tcx> {
3836
/// Used for types with `layout::abi::Scalar` ABI.
3937
///
@@ -52,10 +50,11 @@ pub enum ConstValue<'tcx> {
5250
Slice {
5351
/// The allocation storing the slice contents.
5452
/// This always points to the beginning of the allocation.
55-
data: ConstAllocation<'tcx>,
53+
alloc_id: AllocId,
5654
/// The metadata field of the reference.
5755
/// This is a "target usize", so we use `u64` as in the interpreter.
5856
meta: u64,
57+
phantom: std::marker::PhantomData<&'tcx ()>,
5958
},
6059

6160
/// A value not representable by the other variants; needs to be stored in-memory.
@@ -77,7 +76,7 @@ pub enum ConstValue<'tcx> {
7776
#[cfg(target_pointer_width = "64")]
7877
rustc_data_structures::static_assert_size!(ConstValue<'_>, 24);
7978

80-
impl<'tcx> ConstValue<'tcx> {
79+
impl ConstValue<'_> {
8180
#[inline]
8281
pub fn try_to_scalar(&self) -> Option<Scalar> {
8382
match *self {
@@ -98,11 +97,11 @@ impl<'tcx> ConstValue<'tcx> {
9897
self.try_to_scalar_int()?.try_into().ok()
9998
}
10099

101-
pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
100+
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Option<u64> {
102101
Some(self.try_to_scalar_int()?.to_target_usize(tcx))
103102
}
104103

105-
pub fn try_to_bits_for_ty(
104+
pub fn try_to_bits_for_ty<'tcx>(
106105
&self,
107106
tcx: TyCtxt<'tcx>,
108107
typing_env: ty::TypingEnv<'tcx>,
@@ -132,12 +131,15 @@ impl<'tcx> ConstValue<'tcx> {
132131
}
133132

134133
/// Must only be called on constants of type `&str` or `&[u8]`!
135-
pub fn try_get_slice_bytes_for_diagnostics(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx [u8]> {
136-
let (data, start, end) = match self {
134+
pub fn try_get_slice_bytes_for_diagnostics<'tcx>(
135+
&self,
136+
tcx: TyCtxt<'tcx>,
137+
) -> Option<&'tcx [u8]> {
138+
let (alloc_id, start, len) = match self {
137139
ConstValue::Scalar(_) | ConstValue::ZeroSized => {
138140
bug!("`try_get_slice_bytes` on non-slice constant")
139141
}
140-
&ConstValue::Slice { data, meta } => (data, 0, meta),
142+
&ConstValue::Slice { alloc_id, meta, phantom: _ } => (alloc_id, 0, meta),
141143
&ConstValue::Indirect { alloc_id, offset } => {
142144
// The reference itself is stored behind an indirection.
143145
// Load the reference, and then load the actual slice contents.
@@ -170,26 +172,29 @@ impl<'tcx> ConstValue<'tcx> {
170172
// Non-empty slice, must have memory. We know this is a relative pointer.
171173
let (inner_prov, offset) =
172174
ptr.into_pointer_or_addr().ok()?.prov_and_relative_offset();
173-
let data = tcx.global_alloc(inner_prov.alloc_id()).unwrap_memory();
174-
(data, offset.bytes(), offset.bytes() + len)
175+
(inner_prov.alloc_id(), offset.bytes(), len)
175176
}
176177
};
177178

179+
let data = tcx.global_alloc(alloc_id).unwrap_memory();
180+
178181
// This is for diagnostics only, so we are okay to use `inspect_with_uninit_and_ptr_outside_interpreter`.
179182
let start = start.try_into().unwrap();
180-
let end = end.try_into().unwrap();
183+
let end = start + usize::try_from(len).unwrap();
181184
Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end))
182185
}
183186

184187
/// Check if a constant may contain provenance information. This is used by MIR opts.
185188
/// Can return `true` even if there is no provenance.
186-
pub fn may_have_provenance(&self, tcx: TyCtxt<'tcx>, size: Size) -> bool {
189+
pub fn may_have_provenance(&self, tcx: TyCtxt<'_>, size: Size) -> bool {
187190
match *self {
188191
ConstValue::ZeroSized | ConstValue::Scalar(Scalar::Int(_)) => return false,
189192
ConstValue::Scalar(Scalar::Ptr(..)) => return true,
190193
// It's hard to find out the part of the allocation we point to;
191194
// just conservatively check everything.
192-
ConstValue::Slice { data, meta: _ } => !data.inner().provenance().ptrs().is_empty(),
195+
ConstValue::Slice { alloc_id, meta: _, phantom: _ } => {
196+
!tcx.global_alloc(alloc_id).unwrap_memory().inner().provenance().ptrs().is_empty()
197+
}
193198
ConstValue::Indirect { alloc_id, offset } => !tcx
194199
.global_alloc(alloc_id)
195200
.unwrap_memory()
@@ -200,7 +205,7 @@ impl<'tcx> ConstValue<'tcx> {
200205
}
201206

202207
/// Check if a constant only contains uninitialized bytes.
203-
pub fn all_bytes_uninit(&self, tcx: TyCtxt<'tcx>) -> bool {
208+
pub fn all_bytes_uninit(&self, tcx: TyCtxt<'_>) -> bool {
204209
let ConstValue::Indirect { alloc_id, .. } = self else {
205210
return false;
206211
};
@@ -487,9 +492,8 @@ impl<'tcx> Const<'tcx> {
487492
/// taking into account even pointer identity tests.
488493
pub fn is_deterministic(&self) -> bool {
489494
// Some constants may generate fresh allocations for pointers they contain,
490-
// so using the same constant twice can yield two different results:
491-
// - valtrees purposefully generate new allocations
492-
// - ConstValue::Slice also generate new allocations
495+
// so using the same constant twice can yield two different results.
496+
// Notably, valtrees purposefully generate new allocations.
493497
match self {
494498
Const::Ty(_, c) => match c.kind() {
495499
ty::ConstKind::Param(..) => true,
@@ -507,11 +511,11 @@ impl<'tcx> Const<'tcx> {
507511
| ty::ConstKind::Placeholder(..) => bug!(),
508512
},
509513
Const::Unevaluated(..) => false,
510-
// If the same slice appears twice in the MIR, we cannot guarantee that we will
511-
// give the same `AllocId` to the data.
512-
Const::Val(ConstValue::Slice { .. }, _) => false,
513514
Const::Val(
514-
ConstValue::ZeroSized | ConstValue::Scalar(_) | ConstValue::Indirect { .. },
515+
ConstValue::Slice { .. }
516+
| ConstValue::ZeroSized
517+
| ConstValue::Scalar(_)
518+
| ConstValue::Indirect { .. },
515519
_,
516520
) => true,
517521
}

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,11 +1567,7 @@ pub fn write_allocations<'tcx>(
15671567
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()),
15681568
ConstValue::Scalar(interpret::Scalar::Int { .. }) => None,
15691569
ConstValue::ZeroSized => None,
1570-
ConstValue::Slice { .. } => {
1571-
// `u8`/`str` slices, shouldn't contain pointers that we want to print.
1572-
None
1573-
}
1574-
ConstValue::Indirect { alloc_id, .. } => {
1570+
ConstValue::Slice { alloc_id, .. } | ConstValue::Indirect { alloc_id, .. } => {
15751571
// FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR.
15761572
// Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor.
15771573
Some(alloc_id)

compiler/rustc_middle/src/ty/context.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
pub mod tls;
66

77
use std::assert_matches::debug_assert_matches;
8-
use std::borrow::Borrow;
8+
use std::borrow::{Borrow, Cow};
99
use std::cmp::Ordering;
1010
use std::env::VarError;
1111
use std::ffi::OsStr;
@@ -1617,7 +1617,11 @@ impl<'tcx> TyCtxt<'tcx> {
16171617

16181618
/// Allocates a read-only byte or string literal for `mir::interpret` with alignment 1.
16191619
/// Returns the same `AllocId` if called again with the same bytes.
1620-
pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId {
1620+
pub fn allocate_bytes_dedup<'a>(
1621+
self,
1622+
bytes: impl Into<Cow<'a, [u8]>>,
1623+
salt: usize,
1624+
) -> interpret::AllocId {
16211625
// Create an allocation that just contains these bytes.
16221626
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ());
16231627
let alloc = self.mk_const_alloc(alloc);

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! to help with the tedium.
55
66
use std::fmt::{self, Debug};
7+
use std::marker::PhantomData;
78

89
use rustc_abi::TyAndLayout;
910
use rustc_hir::def::Namespace;
@@ -311,6 +312,13 @@ TrivialTypeTraversalAndLiftImpls! {
311312
///////////////////////////////////////////////////////////////////////////
312313
// Lift implementations
313314

315+
impl<'tcx> Lift<TyCtxt<'tcx>> for PhantomData<&()> {
316+
type Lifted = PhantomData<&'tcx ()>;
317+
fn lift_to_interner(self, _: TyCtxt<'tcx>) -> Option<Self::Lifted> {
318+
Some(PhantomData)
319+
}
320+
}
321+
314322
impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
315323
type Lifted = Option<T::Lifted>;
316324
fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! See docs in build/expr/mod.rs
22
3+
use std::marker::PhantomData;
4+
35
use rustc_abi::Size;
46
use rustc_ast as ast;
57
use rustc_hir::LangItem;
6-
use rustc_middle::mir::interpret::{Allocation, CTFE_ALLOC_SALT, LitToConstInput, Scalar};
8+
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar};
79
use rustc_middle::mir::*;
810
use rustc_middle::thir::*;
911
use rustc_middle::ty::{
@@ -120,28 +122,41 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
120122

121123
let value = match (lit, lit_ty.kind()) {
122124
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
123-
let s = s.as_str();
124-
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ());
125-
let allocation = tcx.mk_const_alloc(allocation);
126-
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
125+
let s = s.as_str().as_bytes();
126+
let len = s.len();
127+
let allocation = tcx.allocate_bytes_dedup(s, CTFE_ALLOC_SALT);
128+
ConstValue::Slice {
129+
alloc_id: allocation,
130+
meta: len.try_into().unwrap(),
131+
phantom: PhantomData,
132+
}
127133
}
128-
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
134+
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
129135
if matches!(inner_ty.kind(), ty::Slice(_)) =>
130136
{
131-
let allocation = Allocation::from_bytes_byte_aligned_immutable(data.as_byte_str(), ());
132-
let allocation = tcx.mk_const_alloc(allocation);
133-
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
137+
let data = byte_sym.as_byte_str();
138+
let len = data.len();
139+
let allocation = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
140+
ConstValue::Slice {
141+
alloc_id: allocation,
142+
meta: len.try_into().unwrap(),
143+
phantom: PhantomData,
144+
}
134145
}
135146
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
136147
let id = tcx.allocate_bytes_dedup(byte_sym.as_byte_str(), CTFE_ALLOC_SALT);
137148
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
138149
}
139150
(ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
140151
{
141-
let allocation =
142-
Allocation::from_bytes_byte_aligned_immutable(byte_sym.as_byte_str(), ());
143-
let allocation = tcx.mk_const_alloc(allocation);
144-
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
152+
let data = byte_sym.as_byte_str();
153+
let len = data.len();
154+
let allocation = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
155+
ConstValue::Slice {
156+
alloc_id: allocation,
157+
meta: len.try_into().unwrap(),
158+
phantom: PhantomData,
159+
}
145160
}
146161
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
147162
ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1)))

0 commit comments

Comments
 (0)