Skip to content

Commit 41d5524

Browse files
Rollup merge of rust-lang#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`
2 parents acf233f + 0b94338 commit 41d5524

File tree

2 files changed

+34
-34
lines changed

2 files changed

+34
-34
lines changed

compiler/rustc_mir/src/interpret/intrinsics.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
323323
self.write_scalar(result, dest)?;
324324
}
325325
sym::copy => {
326-
self.copy(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
326+
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
327327
}
328328
sym::offset => {
329329
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> {
530530
)?;
531531
Ok(offset_ptr)
532532
}
533+
534+
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
535+
pub(crate) fn copy_intrinsic(
536+
&mut self,
537+
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
538+
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
539+
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
540+
nonoverlapping: bool,
541+
) -> InterpResult<'tcx> {
542+
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
543+
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
544+
let (size, align) = (layout.size, layout.align.abi);
545+
let size = size.checked_mul(count, self).ok_or_else(|| {
546+
err_ub_format!(
547+
"overflow computing total size of `{}`",
548+
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
549+
)
550+
})?;
551+
552+
// Make sure we check both pointers for an access of the total size and aligment,
553+
// *even if* the total size is 0.
554+
let src =
555+
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
556+
557+
let dst =
558+
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
559+
560+
if let (Some(src), Some(dst)) = (src, dst) {
561+
self.memory.copy(src, dst, size, nonoverlapping)?;
562+
}
563+
Ok(())
564+
}
533565
}

compiler/rustc_mir/src/interpret/step.rs

+1-33
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//!
33
//! The main entry point is the `step` method.
44
5-
use crate::interpret::OpTy;
65
use rustc_middle::mir;
76
use rustc_middle::mir::interpret::{InterpResult, Scalar};
87
use rustc_target::abi::LayoutOf;
@@ -119,7 +118,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
119118
let src = self.eval_operand(src, None)?;
120119
let dst = self.eval_operand(dst, None)?;
121120
let count = self.eval_operand(count, None)?;
122-
self.copy(&src, &dst, &count, /* nonoverlapping */ true)?;
121+
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
123122
}
124123

125124
// Statements we do not track.
@@ -149,37 +148,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
149148
Ok(())
150149
}
151150

152-
pub(crate) fn copy(
153-
&mut self,
154-
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
155-
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
156-
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
157-
nonoverlapping: bool,
158-
) -> InterpResult<'tcx> {
159-
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
160-
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
161-
let (size, align) = (layout.size, layout.align.abi);
162-
let size = size.checked_mul(count, self).ok_or_else(|| {
163-
err_ub_format!(
164-
"overflow computing total size of `{}`",
165-
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
166-
)
167-
})?;
168-
169-
// Make sure we check both pointers for an access of the total size and aligment,
170-
// *even if* the total size is 0.
171-
let src =
172-
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
173-
174-
let dst =
175-
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
176-
177-
if let (Some(src), Some(dst)) = (src, dst) {
178-
self.memory.copy(src, dst, size, nonoverlapping)?;
179-
}
180-
Ok(())
181-
}
182-
183151
/// Evaluate an assignment statement.
184152
///
185153
/// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue

0 commit comments

Comments
 (0)