Skip to content

Commit dd45abe

Browse files
committed
also make ConstValue::Slice use an AllocId
1 parent 0367060 commit dd45abe

File tree

26 files changed

+135
-158
lines changed

26 files changed

+135
-158
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
7676
pub(crate) fn eval_mir_constant<'tcx>(
7777
fx: &FunctionCx<'_, '_, 'tcx>,
7878
constant: &Constant<'tcx>,
79-
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
79+
) -> Option<(ConstValue, Ty<'tcx>)> {
8080
let constant_kind = fx.monomorphize(constant.literal);
8181
let uv = match constant_kind {
8282
ConstantKind::Ty(const_) => match const_.kind() {
@@ -127,7 +127,7 @@ pub(crate) fn codegen_constant_operand<'tcx>(
127127

128128
pub(crate) fn codegen_const_value<'tcx>(
129129
fx: &mut FunctionCx<'_, '_, 'tcx>,
130-
const_val: ConstValue<'tcx>,
130+
const_val: ConstValue,
131131
ty: Ty<'tcx>,
132132
) -> CValue<'tcx> {
133133
let layout = fx.layout_of(ty);
@@ -231,7 +231,9 @@ pub(crate) fn codegen_const_value<'tcx>(
231231
layout,
232232
)
233233
}
234-
ConstValue::Slice { data, start, end } => {
234+
ConstValue::Slice { alloc_id: Some(alloc_id), start, end } => {
235+
let data = fx.tcx.global_alloc(alloc_id).unwrap_memory();
236+
// FIXME: avoid creating multiple allocations for the same AllocId?
235237
let ptr = pointer_for_allocation(fx, data)
236238
.offset_i64(fx, i64::try_from(start).unwrap())
237239
.get_addr(fx);
@@ -241,6 +243,15 @@ pub(crate) fn codegen_const_value<'tcx>(
241243
.iconst(fx.pointer_type, i64::try_from(end.checked_sub(start).unwrap()).unwrap());
242244
CValue::by_val_pair(ptr, len, layout)
243245
}
246+
ConstValue::Slice { alloc_id: None, start, end } => {
247+
assert_eq!(start, end);
248+
// Empty slice at `start`.
249+
// FIXME: `start` could in principle be big enough to overflow into the negative.
250+
// How should the clif value be constructed then?
251+
let addr = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(start).unwrap());
252+
let len = fx.bcx.ins().iconst(fx.pointer_type, 0);
253+
CValue::by_val_pair(addr, len, layout)
254+
}
244255
}
245256
}
246257

@@ -481,7 +492,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
481492
pub(crate) fn mir_operand_get_const_val<'tcx>(
482493
fx: &FunctionCx<'_, '_, 'tcx>,
483494
operand: &Operand<'tcx>,
484-
) -> Option<ConstValue<'tcx>> {
495+
) -> Option<ConstValue> {
485496
match operand {
486497
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
487498
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored

compiler/rustc_codegen_ssa/src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
194194
pub fn asm_const_to_str<'tcx>(
195195
tcx: TyCtxt<'tcx>,
196196
sp: Span,
197-
const_value: ConstValue<'tcx>,
197+
const_value: ConstValue,
198198
ty_and_layout: TyAndLayout<'tcx>,
199199
) -> String {
200200
let ConstValue::Scalar(scalar) = const_value else {

compiler/rustc_codegen_ssa/src/mir/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2323
pub fn eval_mir_constant(
2424
&self,
2525
constant: &mir::Constant<'tcx>,
26-
) -> Result<ConstValue<'tcx>, ErrorHandled> {
26+
) -> Result<ConstValue, ErrorHandled> {
2727
let ct = self.monomorphize(constant.literal);
2828
let uv = match ct {
2929
mir::ConstantKind::Ty(ct) => match ct.kind() {

compiler/rustc_codegen_ssa/src/mir/operand.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
8686

8787
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
8888
bx: &mut Bx,
89-
val: ConstValue<'tcx>,
89+
val: ConstValue,
9090
ty: Ty<'tcx>,
9191
) -> Self {
9292
let layout = bx.layout_of(ty);
@@ -100,12 +100,12 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
100100
OperandValue::Immediate(llval)
101101
}
102102
ConstValue::ZeroSized => return OperandRef::zero_sized(layout),
103-
ConstValue::Slice { data, start, end } => {
103+
ConstValue::Slice { alloc_id, start, end } => {
104104
let Abi::ScalarPair(a_scalar, _) = layout.abi else {
105105
bug!("from_const: invalid ScalarPair layout: {:#?}", layout);
106106
};
107-
let a = Scalar::from_pointer(
108-
Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)),
107+
let a = Scalar::from_maybe_pointer(
108+
Pointer::new(alloc_id, Size::from_bytes(start)),
109109
&bx.tcx(),
110110
);
111111
let a_llval = bx.scalar_to_backend(

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+8-18
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
1818
use crate::errors;
1919
use crate::interpret::eval_nullary_intrinsic;
2020
use crate::interpret::{
21-
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
22-
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
23-
RefTracking, StackPopCleanup,
21+
intern_const_alloc_recursive, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, Immediate,
22+
InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
23+
StackPopCleanup,
2424
};
2525

2626
// Returns a pointer to where the result lives
@@ -111,7 +111,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
111111
pub(super) fn op_to_const<'tcx>(
112112
ecx: &CompileTimeEvalContext<'_, 'tcx>,
113113
op: &OpTy<'tcx>,
114-
) -> ConstValue<'tcx> {
114+
) -> ConstValue {
115115
// Handle ZST consistently and early.
116116
if op.layout.is_zst() {
117117
return ConstValue::ZeroSized;
@@ -157,21 +157,11 @@ pub(super) fn op_to_const<'tcx>(
157157
Immediate::ScalarPair(a, b) => {
158158
debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
159159
// We know `offset` is relative to the allocation, so we can use `into_parts`.
160-
let (data, start) = match a.to_pointer(ecx).unwrap().into_parts() {
161-
(Some(alloc_id), offset) => {
162-
(ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())
163-
}
164-
(None, _offset) => (
165-
ecx.tcx.mk_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
166-
b"" as &[u8],
167-
)),
168-
0,
169-
),
170-
};
160+
let (alloc_id, start) = a.to_pointer(ecx).unwrap().into_parts();
171161
let len = b.to_target_usize(ecx).unwrap();
172-
let start = start.try_into().unwrap();
162+
let start = start.bytes().try_into().unwrap();
173163
let len: usize = len.try_into().unwrap();
174-
ConstValue::Slice { data, start, end: start + len }
164+
ConstValue::Slice { alloc_id, start, end: start + len }
175165
}
176166
Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
177167
},
@@ -183,7 +173,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
183173
tcx: TyCtxt<'tcx>,
184174
constant: ConstAlloc<'tcx>,
185175
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
186-
) -> ConstValue<'tcx> {
176+
) -> ConstValue {
187177
let cid = key.value;
188178
let def_id = cid.instance.def.def_id();
189179
let is_static = tcx.is_static(def_id);

compiler/rustc_const_eval/src/const_eval/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
2222
pub(crate) fn const_caller_location(
2323
tcx: TyCtxt<'_>,
2424
(file, line, col): (Symbol, u32, u32),
25-
) -> ConstValue<'_> {
25+
) -> ConstValue {
2626
trace!("const_caller_location: {}:{}:{}", file, line, col);
2727
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
2828

@@ -87,7 +87,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
8787
#[instrument(skip(tcx), level = "debug")]
8888
pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>(
8989
tcx: TyCtxt<'tcx>,
90-
val: ConstValue<'tcx>,
90+
val: ConstValue,
9191
ty: Ty<'tcx>,
9292
) -> Option<mir::DestructuredConstant<'tcx>> {
9393
let param_env = ty::ParamEnv::reveal_all();

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ pub fn valtree_to_const_value<'tcx>(
207207
tcx: TyCtxt<'tcx>,
208208
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
209209
valtree: ty::ValTree<'tcx>,
210-
) -> ConstValue<'tcx> {
210+
) -> ConstValue {
211211
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
212212
// (those for constants with type bool, int, uint, float or char).
213213
// For all other types we create an `MPlace` and fill that by walking

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
use rustc_hir::def_id::DefId;
66
use rustc_middle::mir::{
77
self,
8-
interpret::{
9-
Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar,
10-
},
8+
interpret::{Allocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
119
BinOp, NonDivergingIntrinsic,
1210
};
1311
use rustc_middle::ty;
@@ -43,28 +41,24 @@ fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<
4341
Scalar::from_uint(bits_out, size)
4442
}
4543

46-
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
47-
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
48-
let path = crate::util::type_name(tcx, ty);
49-
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
50-
tcx.mk_const_alloc(alloc)
51-
}
52-
5344
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
5445
/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
5546
pub(crate) fn eval_nullary_intrinsic<'tcx>(
5647
tcx: TyCtxt<'tcx>,
5748
param_env: ty::ParamEnv<'tcx>,
5849
def_id: DefId,
5950
args: GenericArgsRef<'tcx>,
60-
) -> InterpResult<'tcx, ConstValue<'tcx>> {
51+
) -> InterpResult<'tcx, ConstValue> {
6152
let tp_ty = args.type_at(0);
6253
let name = tcx.item_name(def_id);
6354
Ok(match name {
6455
sym::type_name => {
6556
ensure_monomorphic_enough(tcx, tp_ty)?;
66-
let alloc = alloc_type_name(tcx, tp_ty);
67-
ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() }
57+
let path = crate::util::type_name(tcx, tp_ty);
58+
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
59+
let alloc = tcx.mk_const_alloc(alloc);
60+
let alloc_id = tcx.create_memory_alloc(alloc);
61+
ConstValue::Slice { alloc_id: Some(alloc_id), start: 0, end: alloc.inner().len() }
6862
}
6963
sym::needs_drop => {
7064
ensure_monomorphic_enough(tcx, tp_ty)?;

compiler/rustc_const_eval/src/interpret/operand.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
743743

744744
pub(crate) fn const_val_to_op(
745745
&self,
746-
val_val: ConstValue<'tcx>,
746+
val_val: ConstValue,
747747
ty: Ty<'tcx>,
748748
layout: Option<TyAndLayout<'tcx>>,
749749
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
@@ -764,11 +764,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
764764
}
765765
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
766766
ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit),
767-
ConstValue::Slice { data, start, end } => {
767+
ConstValue::Slice { alloc_id: Some(alloc_id), start, end } => {
768768
// We rely on mutability being set correctly in `data` to prevent writes
769769
// where none should happen.
770770
let ptr = Pointer::new(
771-
self.tcx.create_memory_alloc(data),
771+
alloc_id,
772772
Size::from_bytes(start), // offset: `start`
773773
);
774774
Operand::Immediate(Immediate::new_slice(
@@ -777,6 +777,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
777777
self,
778778
))
779779
}
780+
ConstValue::Slice { alloc_id: None, start, end } => {
781+
assert_eq!(start, end);
782+
let ptr = Pointer::from_addr_invalid(start.try_into().unwrap());
783+
Operand::Immediate(Immediate::new_slice(
784+
Scalar::from_maybe_pointer(ptr, &*self.tcx),
785+
0, // len: `end - start`
786+
self,
787+
))
788+
}
780789
};
781790
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
782791
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl Into<ErrorGuaranteed> for ReportedErrorInfo {
7070
TrivialTypeTraversalAndLiftImpls! { ErrorHandled }
7171

7272
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
73-
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
73+
pub type EvalToConstValueResult<'tcx> = Result<ConstValue, ErrorHandled>;
7474
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
7575

7676
pub fn struct_error<'tcx>(

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub use self::error::{
149149
UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
150150
};
151151

152-
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
152+
pub use self::value::{ConstAlloc, ConstValue, Scalar};
153153

154154
pub use self::allocation::{
155155
alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,

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

+12-25
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ use rustc_target::abi::{HasDataLayout, Size};
1111

1212
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
1313

14-
use super::{
15-
AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
16-
ScalarSizeMismatch,
17-
};
14+
use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch};
1815

1916
/// Represents the result of const evaluation via the `eval_to_allocation` query.
2017
#[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
@@ -28,9 +25,9 @@ pub struct ConstAlloc<'tcx> {
2825
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
2926
/// array length computations, enum discriminants and the pattern matching logic.
3027
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
31-
#[derive(HashStable, Lift)]
32-
pub enum ConstValue<'tcx> {
33-
/// Used for types with `layout::abi::Scalar` ABI.
28+
#[derive(HashStable)]
29+
pub enum ConstValue {
30+
/// Used only for types with `layout::abi::Scalar` ABI.
3431
///
3532
/// Not using the enum `Value` to encode that this must not be `Uninit`.
3633
Scalar(Scalar),
@@ -41,7 +38,10 @@ pub enum ConstValue<'tcx> {
4138
/// Used for `&[u8]` and `&str`.
4239
///
4340
/// This is worth the optimization since Rust has literals of that type.
44-
Slice { data: ConstAllocation<'tcx>, start: usize, end: usize },
41+
/// See `Indirect` for why we are using an `AllocId`.
42+
/// We allow `None` for empty slices; in that case `start == end` and `start` is the absolute
43+
/// address of the slice.
44+
Slice { alloc_id: Option<AllocId>, start: usize, end: usize },
4545

4646
/// A value not representable by the other variants; needs to be stored in-memory.
4747
Indirect {
@@ -58,9 +58,11 @@ pub enum ConstValue<'tcx> {
5858
}
5959

6060
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
61-
static_assert_size!(ConstValue<'_>, 32);
61+
static_assert_size!(ConstValue, 32);
62+
63+
TrivialTypeTraversalAndLiftImpls! { ConstValue }
6264

63-
impl<'tcx> ConstValue<'tcx> {
65+
impl<'tcx> ConstValue {
6466
#[inline]
6567
pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
6668
match *self {
@@ -511,18 +513,3 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
511513
Ok(Double::from_bits(self.to_u64()?.into()))
512514
}
513515
}
514-
515-
/// Gets the bytes of a constant slice value.
516-
pub fn get_slice_bytes<'tcx>(cx: &impl HasDataLayout, val: ConstValue<'tcx>) -> &'tcx [u8] {
517-
if let ConstValue::Slice { data, start, end } = val {
518-
let len = end - start;
519-
data.inner()
520-
.get_bytes_strip_provenance(
521-
cx,
522-
AllocRange { start: Size::from_bytes(start), size: Size::from_bytes(len) },
523-
)
524-
.unwrap_or_else(|err| bug!("const slice is invalid: {:?}", err))
525-
} else {
526-
bug!("expected const slice, but found another const value");
527-
}
528-
}

0 commit comments

Comments
 (0)