Directly intern values instead of copying them.
This commit is contained in:
@@ -450,6 +450,50 @@ pub fn intern_const_alloc_recursive<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Intern `ret`, checking it references no other allocation.
|
||||
#[instrument(level = "debug", skip(ecx))]
|
||||
pub fn intern_const_alloc_for_constprop<
|
||||
'mir,
|
||||
'tcx: 'mir,
|
||||
T,
|
||||
M: CompileTimeMachine<'mir, 'tcx, T>,
|
||||
>(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
ret: &MPlaceTy<'tcx>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let Some((size, _align)) = ecx.size_and_align_of_mplace(ret)? else {
|
||||
throw_inval!(ConstPropNonsense)
|
||||
};
|
||||
|
||||
let alloc_ref = ecx.get_ptr_alloc(ret.ptr(), size)?.unwrap();
|
||||
// Do not try interning a value that contains provenance.
|
||||
if alloc_ref.has_provenance() {
|
||||
throw_inval!(ConstPropNonsense)
|
||||
}
|
||||
|
||||
// remove allocation
|
||||
let alloc_id = ret.ptr().provenance.unwrap();
|
||||
let Some((_, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else {
|
||||
// Pointer not found in local memory map. It is either a pointer to the global
|
||||
// map, or dangling.
|
||||
if ecx.tcx.try_get_global_alloc(alloc_id).is_none() {
|
||||
throw_ub!(DeadLocal)
|
||||
}
|
||||
// The constant is already in global memory. Do nothing.
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
alloc.mutability = Mutability::Not;
|
||||
|
||||
// link the alloc id to the actual allocation
|
||||
assert!(alloc.provenance().ptrs().is_empty());
|
||||
|
||||
let alloc = ecx.tcx.mk_const_alloc(alloc);
|
||||
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||
InterpCx<'mir, 'tcx, M>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user