Skip to content

Commit 993d146

Browse files
committed
Auto merge of #115764 - RalfJung:const-by-ref-alloc-id, r=<try>
use AllocId instead of Allocation in ConstValue::ByRef This helps avoid redundant AllocIds when a `ByRef` constant gets put back into the interpreter. r? `@oli-obk`
2 parents 3ebb562 + 50ad68a commit 993d146

File tree

15 files changed

+75
-57
lines changed

15 files changed

+75
-57
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,15 @@ pub(crate) fn codegen_const_value<'tcx>(
222222
CValue::by_val(val, layout)
223223
}
224224
},
225-
ConstValue::ByRef { alloc, offset } => CValue::by_ref(
226-
pointer_for_allocation(fx, alloc)
227-
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
228-
layout,
229-
),
225+
ConstValue::ByRef { alloc_id, offset } => {
226+
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
227+
// FIXME: avoid creating multiple allocations for the same AllocId?
228+
CValue::by_ref(
229+
pointer_for_allocation(fx, alloc)
230+
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
231+
layout,
232+
)
233+
}
230234
ConstValue::Slice { data, start, end } => {
231235
let ptr = pointer_for_allocation(fx, data)
232236
.offset_i64(fx, i64::try_from(start).unwrap())

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
172172
.expect("simd_shuffle idx not const");
173173

174174
let idx_bytes = match idx_const {
175-
ConstValue::ByRef { alloc, offset } => {
175+
ConstValue::ByRef { alloc_id, offset } => {
176+
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
176177
let size = Size::from_bytes(
177178
4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */
178179
);

compiler/rustc_codegen_ssa/src/mir/operand.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
116116
let b_llval = bx.const_usize((end - start) as u64);
117117
OperandValue::Pair(a_llval, b_llval)
118118
}
119-
ConstValue::ByRef { alloc, offset } => {
119+
ConstValue::ByRef { alloc_id, offset } => {
120+
let alloc = bx.tcx().global_alloc(alloc_id).unwrap_memory();
121+
// FIXME: should we attempt to avoid building the same AllocId multiple times?
120122
return Self::from_const_alloc(bx, layout, alloc, offset);
121123
}
122124
};

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,7 @@ pub(super) fn op_to_const<'tcx>(
148148
let to_const_value = |mplace: &MPlaceTy<'_>| {
149149
debug!("to_const_value(mplace: {:?})", mplace);
150150
match mplace.ptr().into_parts() {
151-
(Some(alloc_id), offset) => {
152-
let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
153-
ConstValue::ByRef { alloc, offset }
154-
}
151+
(Some(alloc_id), offset) => ConstValue::ByRef { alloc_id, offset },
155152
(None, offset) => {
156153
assert!(mplace.layout.is_zst());
157154
assert_eq!(

compiler/rustc_const_eval/src/interpret/intern.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
2424
use rustc_ast::Mutability;
2525

2626
use super::{
27-
AllocId, Allocation, ConstAllocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy,
28-
Projectable, ValueVisitor,
27+
AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, Projectable,
28+
ValueVisitor,
2929
};
3030
use crate::const_eval;
3131
use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
@@ -455,19 +455,23 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
455455
{
456456
/// A helper function that allocates memory for the layout given and gives you access to mutate
457457
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
458-
/// current `Memory` and returned.
458+
/// current `Memory` and interned as read-only into the global memory.
459459
pub fn intern_with_temp_alloc(
460460
&mut self,
461461
layout: TyAndLayout<'tcx>,
462462
f: impl FnOnce(
463463
&mut InterpCx<'mir, 'tcx, M>,
464464
&PlaceTy<'tcx, M::Provenance>,
465465
) -> InterpResult<'tcx, ()>,
466-
) -> InterpResult<'tcx, ConstAllocation<'tcx>> {
466+
) -> InterpResult<'tcx, AllocId> {
467+
// `allocate` picks a fresh AllocId that we will associate with its data below.
467468
let dest = self.allocate(layout, MemoryKind::Stack)?;
468469
f(self, &dest.clone().into())?;
469470
let mut alloc = self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap()).unwrap().1;
470471
alloc.mutability = Mutability::Not;
471-
Ok(self.tcx.mk_const_alloc(alloc))
472+
let alloc = self.tcx.mk_const_alloc(alloc);
473+
let alloc_id = dest.ptr().provenance.unwrap(); // this was just allocated, it must have provenance
474+
self.tcx.set_alloc_id_memory(alloc_id, alloc);
475+
Ok(alloc_id)
472476
}
473477
}

compiler/rustc_const_eval/src/interpret/operand.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
756756
};
757757
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
758758
let op = match val_val {
759-
ConstValue::ByRef { alloc, offset } => {
760-
let id = self.tcx.create_memory_alloc(alloc);
759+
ConstValue::ByRef { alloc_id, offset } => {
761760
// We rely on mutability being set correctly in that allocation to prevent writes
762761
// where none should happen.
763-
let ptr = self.global_base_pointer(Pointer::new(id, offset))?;
762+
let ptr = self.global_base_pointer(Pointer::new(alloc_id, offset))?;
764763
Operand::Indirect(MemPlace::from_ptr(ptr.into()))
765764
}
766765
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ pub enum ConstValue<'tcx> {
4343

4444
/// A value not represented/representable by `Scalar` or `Slice`
4545
ByRef {
46-
/// The backing memory of the value, may contain more memory than needed for just the value
47-
/// in order to share `ConstAllocation`s between values
48-
alloc: ConstAllocation<'tcx>,
46+
/// The backing memory of the value. May contain more memory than needed for just the value
47+
/// if this points into some other larger ConstValue.
48+
///
49+
/// We use an `AllocId` here instead of a `ConstAllocation<'tcx>` to make sure that when a
50+
/// raw constant (which is basically just an `AllocId`) is turned into a `ConstValue` and
51+
/// back, we can preserve the original `AllocId`.
52+
alloc_id: AllocId,
4953
/// Offset into `alloc`
5054
offset: Size,
5155
},

compiler/rustc_middle/src/mir/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2883,8 +2883,9 @@ fn pretty_print_const_value<'tcx>(
28832883
_ => {}
28842884
}
28852885
}
2886-
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
2886+
(ConstValue::ByRef { alloc_id, offset }, ty::Array(t, n)) if *t == u8_type => {
28872887
let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
2888+
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
28882889
// cast is ok because we already checked for pointer size (32 or 64 bit) above
28892890
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
28902891
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();

compiler/rustc_middle/src/mir/pretty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -707,8 +707,9 @@ pub fn write_allocations<'tcx>(
707707
Either::Left(Either::Right(std::iter::empty()))
708708
}
709709
ConstValue::ZeroSized => Either::Left(Either::Right(std::iter::empty())),
710-
ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => {
711-
Either::Right(alloc_ids_from_alloc(alloc))
710+
ConstValue::Slice { data, .. } => Either::Right(alloc_ids_from_alloc(data)),
711+
ConstValue::ByRef { alloc_id, .. } => {
712+
Either::Left(Either::Left(std::iter::once(alloc_id)))
712713
}
713714
}
714715
}

compiler/rustc_middle/src/ty/structural_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ TrivialTypeTraversalAndLiftImpls! {
502502
::rustc_span::symbol::Ident,
503503
::rustc_errors::ErrorGuaranteed,
504504
interpret::Scalar,
505+
interpret::AllocId,
505506
rustc_target::abi::Size,
506507
ty::BoundVar,
507508
}

compiler/rustc_mir_transform/src/const_prop.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
570570
Some(self.operand_from_scalar(scalar, value.layout.ty))
571571
}
572572
Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
573-
let alloc = self
573+
let alloc_id = self
574574
.ecx
575575
.intern_with_temp_alloc(value.layout, |ecx, dest| {
576576
ecx.write_immediate(*imm, dest)
577577
})
578578
.ok()?;
579579

580580
let literal = ConstantKind::Val(
581-
ConstValue::ByRef { alloc, offset: Size::ZERO },
581+
ConstValue::ByRef { alloc_id, offset: Size::ZERO },
582582
value.layout.ty,
583583
);
584584
Some(Operand::Constant(Box::new(Constant {

compiler/rustc_mir_transform/src/large_enums.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ impl EnumSizeOpt {
139139

140140
let (adt_def, num_variants, alloc_id) =
141141
self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
142-
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
143142

144143
let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
145144

@@ -154,7 +153,7 @@ impl EnumSizeOpt {
154153
span,
155154
user_ty: None,
156155
literal: ConstantKind::Val(
157-
interpret::ConstValue::ByRef { alloc, offset: Size::ZERO },
156+
interpret::ConstValue::ByRef { alloc_id, offset: Size::ZERO },
158157
tmp_ty,
159158
),
160159
};

compiler/rustc_monomorphize/src/collector.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1470,8 +1470,9 @@ fn collect_const_value<'tcx>(
14701470
) {
14711471
match value {
14721472
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_alloc(tcx, ptr.provenance, output),
1473-
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
1474-
for &id in alloc.inner().provenance().ptrs().values() {
1473+
ConstValue::ByRef { alloc_id, .. } => collect_alloc(tcx, alloc_id, output),
1474+
ConstValue::Slice { data, start: _, end: _ } => {
1475+
for &id in data.inner().provenance().ptrs().values() {
14751476
collect_alloc(tcx, id, output);
14761477
}
14771478
}

compiler/rustc_smir/src/rustc_smir/alloc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ pub fn new_allocation<'tcx>(
7272
.unwrap();
7373
allocation.stable(tables)
7474
}
75-
ConstValue::ByRef { alloc, offset } => {
75+
ConstValue::ByRef { alloc_id, offset } => {
76+
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
7677
let ty_size = tables
7778
.tcx
7879
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))

src/tools/clippy/clippy_utils/src/consts.rs

+28-25
Original file line numberDiff line numberDiff line change
@@ -684,34 +684,37 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
684684
},
685685
_ => None,
686686
},
687-
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
688-
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
689-
ty::Array(sub_type, len) => match sub_type.kind() {
690-
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
691-
Some(len) => alloc
692-
.inner()
693-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
694-
.to_owned()
695-
.array_chunks::<4>()
696-
.map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
697-
.collect::<Option<Vec<Constant<'tcx>>>>()
698-
.map(Constant::Vec),
699-
_ => None,
700-
},
701-
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
702-
Some(len) => alloc
703-
.inner()
704-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
705-
.to_owned()
706-
.array_chunks::<8>()
707-
.map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
708-
.collect::<Option<Vec<Constant<'tcx>>>>()
709-
.map(Constant::Vec),
687+
mir::ConstantKind::Val(ConstValue::ByRef { alloc_id, offset: _ }, _) => {
688+
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
689+
match result.ty().kind() {
690+
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
691+
ty::Array(sub_type, len) => match sub_type.kind() {
692+
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
693+
Some(len) => alloc
694+
.inner()
695+
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
696+
.to_owned()
697+
.array_chunks::<4>()
698+
.map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
699+
.collect::<Option<Vec<Constant<'tcx>>>>()
700+
.map(Constant::Vec),
701+
_ => None,
702+
},
703+
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
704+
Some(len) => alloc
705+
.inner()
706+
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
707+
.to_owned()
708+
.array_chunks::<8>()
709+
.map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
710+
.collect::<Option<Vec<Constant<'tcx>>>>()
711+
.map(Constant::Vec),
712+
_ => None,
713+
},
710714
_ => None,
711715
},
712716
_ => None,
713-
},
714-
_ => None,
717+
}
715718
},
716719
_ => None,
717720
}

0 commit comments

Comments
 (0)