mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 11:44:28 +00:00
Rollup merge of #84905 - RalfJung:copy, r=oli-obk
CTFE engine: rename copy → copy_intrinsic, move to intrinsics.rs The `copy` name is confusing for this function because we also have `copy_op` which is pretty different. I hope `copy_intrinsic` is clearer. Also `step.rs` should really just contain the main loop and opcode dispatch, so move this helper function to a more appropriate place. r? ``````@oli-obk``````
This commit is contained in:
commit
eec3ae3feb
@ -323,7 +323,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
self.write_scalar(result, dest)?;
|
||||
}
|
||||
sym::copy => {
|
||||
self.copy(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
|
||||
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
|
||||
}
|
||||
sym::offset => {
|
||||
let ptr = self.read_scalar(&args[0])?.check_init()?;
|
||||
@ -530,4 +530,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
)?;
|
||||
Ok(offset_ptr)
|
||||
}
|
||||
|
||||
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
|
||||
pub(crate) fn copy_intrinsic(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
let size = size.checked_mul(count, self).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"overflow computing total size of `{}`",
|
||||
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
|
||||
)
|
||||
})?;
|
||||
|
||||
// Make sure we check both pointers for an access of the total size and aligment,
|
||||
// *even if* the total size is 0.
|
||||
let src =
|
||||
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
|
||||
|
||||
let dst =
|
||||
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
|
||||
|
||||
if let (Some(src), Some(dst)) = (src, dst) {
|
||||
self.memory.copy(src, dst, size, nonoverlapping)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
//!
|
||||
//! The main entry point is the `step` method.
|
||||
|
||||
use crate::interpret::OpTy;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||
use rustc_target::abi::LayoutOf;
|
||||
@ -119,7 +118,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let src = self.eval_operand(src, None)?;
|
||||
let dst = self.eval_operand(dst, None)?;
|
||||
let count = self.eval_operand(count, None)?;
|
||||
self.copy(&src, &dst, &count, /* nonoverlapping */ true)?;
|
||||
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
|
||||
}
|
||||
|
||||
// Statements we do not track.
|
||||
@ -149,37 +148,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn copy(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
let size = size.checked_mul(count, self).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"overflow computing total size of `{}`",
|
||||
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
|
||||
)
|
||||
})?;
|
||||
|
||||
// Make sure we check both pointers for an access of the total size and aligment,
|
||||
// *even if* the total size is 0.
|
||||
let src =
|
||||
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
|
||||
|
||||
let dst =
|
||||
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
|
||||
|
||||
if let (Some(src), Some(dst)) = (src, dst) {
|
||||
self.memory.copy(src, dst, size, nonoverlapping)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Evaluate an assignment statement.
|
||||
///
|
||||
/// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
|
||||
|
Loading…
Reference in New Issue
Block a user