use AllocId instead of Allocation in ConstValue::ByRef
This commit is contained in:
parent
c728bf3963
commit
551f481ffb
15 changed files with 80 additions and 63 deletions
|
@ -200,11 +200,15 @@ pub(crate) fn codegen_const_value<'tcx>(
|
||||||
CValue::by_val(val, layout)
|
CValue::by_val(val, layout)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ConstValue::ByRef { alloc, offset } => CValue::by_ref(
|
ConstValue::ByRef { alloc_id, offset } => {
|
||||||
|
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||||
|
// FIXME: avoid creating multiple allocations for the same AllocId?
|
||||||
|
CValue::by_ref(
|
||||||
pointer_for_allocation(fx, alloc)
|
pointer_for_allocation(fx, alloc)
|
||||||
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
|
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
|
||||||
layout,
|
layout,
|
||||||
),
|
)
|
||||||
|
}
|
||||||
ConstValue::Slice { data, start, end } => {
|
ConstValue::Slice { data, start, end } => {
|
||||||
let ptr = pointer_for_allocation(fx, data)
|
let ptr = pointer_for_allocation(fx, data)
|
||||||
.offset_i64(fx, i64::try_from(start).unwrap())
|
.offset_i64(fx, i64::try_from(start).unwrap())
|
||||||
|
|
|
@ -172,7 +172,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||||
.expect("simd_shuffle idx not const");
|
.expect("simd_shuffle idx not const");
|
||||||
|
|
||||||
let idx_bytes = match idx_const {
|
let idx_bytes = match idx_const {
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
ConstValue::ByRef { alloc_id, offset } => {
|
||||||
|
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||||
let size = Size::from_bytes(
|
let size = Size::from_bytes(
|
||||||
4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */
|
4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */
|
||||||
);
|
);
|
||||||
|
|
|
@ -116,7 +116,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||||
let b_llval = bx.const_usize((end - start) as u64);
|
let b_llval = bx.const_usize((end - start) as u64);
|
||||||
OperandValue::Pair(a_llval, b_llval)
|
OperandValue::Pair(a_llval, b_llval)
|
||||||
}
|
}
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
ConstValue::ByRef { alloc_id, offset } => {
|
||||||
|
let alloc = bx.tcx().global_alloc(alloc_id).unwrap_memory();
|
||||||
|
// FIXME: should we attempt to avoid building the same AllocId multiple times?
|
||||||
return Self::from_const_alloc(bx, layout, alloc, offset);
|
return Self::from_const_alloc(bx, layout, alloc, offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -148,10 +148,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||||
let to_const_value = |mplace: &MPlaceTy<'_>| {
|
let to_const_value = |mplace: &MPlaceTy<'_>| {
|
||||||
debug!("to_const_value(mplace: {:?})", mplace);
|
debug!("to_const_value(mplace: {:?})", mplace);
|
||||||
match mplace.ptr().into_parts() {
|
match mplace.ptr().into_parts() {
|
||||||
(Some(alloc_id), offset) => {
|
(Some(alloc_id), offset) => ConstValue::ByRef { alloc_id, offset },
|
||||||
let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
|
|
||||||
ConstValue::ByRef { alloc, offset }
|
|
||||||
}
|
|
||||||
(None, offset) => {
|
(None, offset) => {
|
||||||
assert!(mplace.layout.is_zst());
|
assert!(mplace.layout.is_zst());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -24,8 +24,8 @@ use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocId, Allocation, ConstAllocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy,
|
AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, Projectable,
|
||||||
Projectable, ValueVisitor,
|
ValueVisitor,
|
||||||
};
|
};
|
||||||
use crate::const_eval;
|
use crate::const_eval;
|
||||||
use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
|
use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
|
||||||
|
@ -455,7 +455,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||||
{
|
{
|
||||||
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
||||||
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
||||||
/// current `Memory` and returned.
|
/// current `Memory` and interned as read-only into the global memory.
|
||||||
pub fn intern_with_temp_alloc(
|
pub fn intern_with_temp_alloc(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
|
@ -463,11 +463,15 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||||
&mut InterpCx<'mir, 'tcx, M>,
|
&mut InterpCx<'mir, 'tcx, M>,
|
||||||
&PlaceTy<'tcx, M::Provenance>,
|
&PlaceTy<'tcx, M::Provenance>,
|
||||||
) -> InterpResult<'tcx, ()>,
|
) -> InterpResult<'tcx, ()>,
|
||||||
) -> InterpResult<'tcx, ConstAllocation<'tcx>> {
|
) -> InterpResult<'tcx, AllocId> {
|
||||||
|
// `allocate` picks a fresh AllocId that we will associate with its data below.
|
||||||
let dest = self.allocate(layout, MemoryKind::Stack)?;
|
let dest = self.allocate(layout, MemoryKind::Stack)?;
|
||||||
f(self, &dest.clone().into())?;
|
f(self, &dest.clone().into())?;
|
||||||
let mut alloc = self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap()).unwrap().1;
|
let mut alloc = self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap()).unwrap().1;
|
||||||
alloc.mutability = Mutability::Not;
|
alloc.mutability = Mutability::Not;
|
||||||
Ok(self.tcx.mk_const_alloc(alloc))
|
let alloc = self.tcx.mk_const_alloc(alloc);
|
||||||
|
let alloc_id = dest.ptr().provenance.unwrap(); // this was just allocated, it must have provenance
|
||||||
|
self.tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||||
|
Ok(alloc_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,11 +756,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
};
|
};
|
||||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
|
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
|
||||||
let op = match val_val {
|
let op = match val_val {
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
ConstValue::ByRef { alloc_id, offset } => {
|
||||||
let id = self.tcx.create_memory_alloc(alloc);
|
|
||||||
// We rely on mutability being set correctly in that allocation to prevent writes
|
// We rely on mutability being set correctly in that allocation to prevent writes
|
||||||
// where none should happen.
|
// where none should happen.
|
||||||
let ptr = self.global_base_pointer(Pointer::new(id, offset))?;
|
let ptr = self.global_base_pointer(Pointer::new(alloc_id, offset))?;
|
||||||
Operand::Indirect(MemPlace::from_ptr(ptr.into()))
|
Operand::Indirect(MemPlace::from_ptr(ptr.into()))
|
||||||
}
|
}
|
||||||
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
|
ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
|
||||||
|
|
|
@ -43,9 +43,13 @@ pub enum ConstValue<'tcx> {
|
||||||
|
|
||||||
/// A value not represented/representable by `Scalar` or `Slice`
|
/// A value not represented/representable by `Scalar` or `Slice`
|
||||||
ByRef {
|
ByRef {
|
||||||
/// The backing memory of the value, may contain more memory than needed for just the value
|
/// The backing memory of the value. May contain more memory than needed for just the value
|
||||||
/// in order to share `ConstAllocation`s between values
|
/// if this points into some other larger ConstValue.
|
||||||
alloc: ConstAllocation<'tcx>,
|
///
|
||||||
|
/// We use an `AllocId` here instead of a `ConstAllocation<'tcx>` to make sure that when a
|
||||||
|
/// raw constant (which is basically just an `AllocId`) is turned into a `ConstValue` and
|
||||||
|
/// back, we can preserve the original `AllocId`.
|
||||||
|
alloc_id: AllocId,
|
||||||
/// Offset into `alloc`
|
/// Offset into `alloc`
|
||||||
offset: Size,
|
offset: Size,
|
||||||
},
|
},
|
||||||
|
|
|
@ -2914,8 +2914,9 @@ fn pretty_print_const_value<'tcx>(
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
(ConstValue::ByRef { alloc_id, offset }, ty::Array(t, n)) if *t == u8_type => {
|
||||||
let n = n.try_to_target_usize(tcx).unwrap();
|
let n = n.try_to_target_usize(tcx).unwrap();
|
||||||
|
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
|
||||||
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
||||||
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
||||||
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
|
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
|
||||||
|
|
|
@ -701,15 +701,15 @@ pub fn write_allocations<'tcx>(
|
||||||
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
|
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
|
||||||
match val {
|
match val {
|
||||||
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
|
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
|
||||||
Either::Left(Either::Left(std::iter::once(ptr.provenance)))
|
Either::Left(std::iter::once(ptr.provenance))
|
||||||
}
|
}
|
||||||
ConstValue::Scalar(interpret::Scalar::Int { .. }) => {
|
ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()),
|
||||||
Either::Left(Either::Right(std::iter::empty()))
|
ConstValue::ZeroSized => Either::Right(std::iter::empty()),
|
||||||
}
|
ConstValue::Slice { .. } => {
|
||||||
ConstValue::ZeroSized => Either::Left(Either::Right(std::iter::empty())),
|
// `u8`/`str` slices, shouldn't contain pointers that we want to print.
|
||||||
ConstValue::ByRef { alloc, .. } | ConstValue::Slice { data: alloc, .. } => {
|
Either::Right(std::iter::empty())
|
||||||
Either::Right(alloc_ids_from_alloc(alloc))
|
|
||||||
}
|
}
|
||||||
|
ConstValue::ByRef { alloc_id, .. } => Either::Left(std::iter::once(alloc_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct CollectAllocIds(BTreeSet<AllocId>);
|
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||||
|
|
|
@ -510,6 +510,7 @@ TrivialTypeTraversalAndLiftImpls! {
|
||||||
::rustc_span::symbol::Ident,
|
::rustc_span::symbol::Ident,
|
||||||
::rustc_errors::ErrorGuaranteed,
|
::rustc_errors::ErrorGuaranteed,
|
||||||
interpret::Scalar,
|
interpret::Scalar,
|
||||||
|
interpret::AllocId,
|
||||||
rustc_target::abi::Size,
|
rustc_target::abi::Size,
|
||||||
ty::BoundVar,
|
ty::BoundVar,
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,7 +535,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
trace!("replacing {:?} with {:?}", place, value);
|
trace!("replacing {:?} with {:?}", place, value);
|
||||||
|
|
||||||
// FIXME> figure out what to do when read_immediate_raw fails
|
// FIXME: figure out what to do when read_immediate_raw fails
|
||||||
let imm = self.ecx.read_immediate_raw(&value).ok()?;
|
let imm = self.ecx.read_immediate_raw(&value).ok()?;
|
||||||
|
|
||||||
let Right(imm) = imm else { return None };
|
let Right(imm) = imm else { return None };
|
||||||
|
@ -544,7 +544,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
Some(ConstantKind::from_scalar(self.tcx, scalar, value.layout.ty))
|
Some(ConstantKind::from_scalar(self.tcx, scalar, value.layout.ty))
|
||||||
}
|
}
|
||||||
Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
|
Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
|
||||||
let alloc = self
|
let alloc_id = self
|
||||||
.ecx
|
.ecx
|
||||||
.intern_with_temp_alloc(value.layout, |ecx, dest| {
|
.intern_with_temp_alloc(value.layout, |ecx, dest| {
|
||||||
ecx.write_immediate(*imm, dest)
|
ecx.write_immediate(*imm, dest)
|
||||||
|
@ -552,7 +552,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
Some(ConstantKind::Val(
|
Some(ConstantKind::Val(
|
||||||
ConstValue::ByRef { alloc, offset: Size::ZERO },
|
ConstValue::ByRef { alloc_id, offset: Size::ZERO },
|
||||||
value.layout.ty,
|
value.layout.ty,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,6 @@ impl EnumSizeOpt {
|
||||||
|
|
||||||
let (adt_def, num_variants, alloc_id) =
|
let (adt_def, num_variants, alloc_id) =
|
||||||
self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
|
self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
|
||||||
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
|
|
||||||
|
|
||||||
let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
|
let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64);
|
||||||
|
|
||||||
|
@ -154,7 +153,7 @@ impl EnumSizeOpt {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ConstantKind::Val(
|
literal: ConstantKind::Val(
|
||||||
interpret::ConstValue::ByRef { alloc, offset: Size::ZERO },
|
interpret::ConstValue::ByRef { alloc_id, offset: Size::ZERO },
|
||||||
tmp_ty,
|
tmp_ty,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1470,8 +1470,9 @@ fn collect_const_value<'tcx>(
|
||||||
) {
|
) {
|
||||||
match value {
|
match value {
|
||||||
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_alloc(tcx, ptr.provenance, output),
|
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_alloc(tcx, ptr.provenance, output),
|
||||||
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
|
ConstValue::ByRef { alloc_id, .. } => collect_alloc(tcx, alloc_id, output),
|
||||||
for &id in alloc.inner().provenance().ptrs().values() {
|
ConstValue::Slice { data, start: _, end: _ } => {
|
||||||
|
for &id in data.inner().provenance().ptrs().values() {
|
||||||
collect_alloc(tcx, id, output);
|
collect_alloc(tcx, id, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,8 @@ pub fn new_allocation<'tcx>(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
allocation.stable(tables)
|
allocation.stable(tables)
|
||||||
}
|
}
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
ConstValue::ByRef { alloc_id, offset } => {
|
||||||
|
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||||
let ty_size = tables
|
let ty_size = tables
|
||||||
.tcx
|
.tcx
|
||||||
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
|
.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty))
|
||||||
|
|
|
@ -684,7 +684,9 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
mir::ConstantKind::Val(ConstValue::ByRef { alloc_id, offset: _ }, _) => {
|
||||||
|
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||||
|
match result.ty().kind() {
|
||||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||||
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
|
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
|
||||||
|
@ -712,6 +714,7 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue