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:
Dylan DPC 2021-05-07 00:38:43 +02:00 committed by GitHub
commit eec3ae3feb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 34 deletions

View File

@ -323,7 +323,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_scalar(result, dest)?; self.write_scalar(result, dest)?;
} }
sym::copy => { 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 => { sym::offset => {
let ptr = self.read_scalar(&args[0])?.check_init()?; 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) 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(())
}
} }

View File

@ -2,7 +2,6 @@
//! //!
//! The main entry point is the `step` method. //! The main entry point is the `step` method.
use crate::interpret::OpTy;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_target::abi::LayoutOf; 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 src = self.eval_operand(src, None)?;
let dst = self.eval_operand(dst, None)?; let dst = self.eval_operand(dst, None)?;
let count = self.eval_operand(count, 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. // Statements we do not track.
@ -149,37 +148,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(()) 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. /// Evaluate an assignment statement.
/// ///
/// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue