|
2 | 2 | //!
|
3 | 3 | //! The main entry point is the `step` method.
|
4 | 4 |
|
| 5 | +use crate::interpret::OpTy; |
5 | 6 | use rustc_middle::mir;
|
6 | 7 | use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
7 | 8 | use rustc_target::abi::LayoutOf;
|
@@ -115,35 +116,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
115 | 116 |
|
116 | 117 | // Call CopyNonOverlapping
|
117 | 118 | CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
|
118 |
| - let (src, size) = { |
119 |
| - let src = self.eval_operand(src, None)?; |
120 |
| - let size = src.layout.layout.size; |
121 |
| - let mplace = *src.assert_mem_place(self); |
122 |
| - let ptr = match mplace.ptr { |
123 |
| - Scalar::Ptr(ptr) => ptr, |
124 |
| - _ => panic!(), |
125 |
| - }; |
126 |
| - (ptr, size) |
127 |
| - }; |
128 |
| - |
129 |
| - let dst = { |
130 |
| - let dst = self.eval_operand(dst, None)?; |
131 |
| - let mplace = *dst.assert_mem_place(self); |
132 |
| - match mplace.ptr { |
133 |
| - Scalar::Ptr(ptr) => ptr, |
134 |
| - _ => panic!(), |
135 |
| - } |
136 |
| - }; |
137 |
| - |
138 | 119 | let count = self.eval_operand(count, None)?;
|
139 |
| - let count = self.read_immediate(count)?.to_scalar()?; |
140 |
| - let count = if let Scalar::Int(i) = count { |
141 |
| - core::convert::TryFrom::try_from(i).unwrap() |
142 |
| - } else { |
143 |
| - panic!(); |
144 |
| - }; |
145 | 120 |
|
146 |
| - self.memory.copy_repeatedly(src, dst, size, count, /*nonoverlapping*/ true)?; |
| 121 | + let src = self.eval_operand(src, None)?; |
| 122 | + let dst = self.eval_operand(dst, None)?; |
| 123 | + self.copy_nonoverlapping(src, dst, count)?; |
147 | 124 | }
|
148 | 125 |
|
149 | 126 | // Statements we do not track.
|
@@ -173,6 +150,31 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
173 | 150 | Ok(())
|
174 | 151 | }
|
175 | 152 |
|
| 153 | + pub(crate) fn copy_nonoverlapping( |
| 154 | + &mut self, |
| 155 | + src: OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>, |
| 156 | + dst: OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>, |
| 157 | + count: OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>, |
| 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 src = |
| 163 | + self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?; |
| 164 | + |
| 165 | + let dst = |
| 166 | + self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?; |
| 167 | + |
| 168 | + let size = size.checked_mul(count, self).ok_or_else(|| { |
| 169 | + err_ub_format!("overflow computing total size of `copy_nonoverlapping`") |
| 170 | + })?; |
| 171 | + |
| 172 | + if let (Some(src), Some(dst)) = (src, dst) { |
| 173 | + self.memory.copy(src, dst, size, /*nonoverlapping*/ true)?; |
| 174 | + } |
| 175 | + Ok(()) |
| 176 | + } |
| 177 | + |
176 | 178 | /// Evaluate an assignment statement.
|
177 | 179 | ///
|
178 | 180 | /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
|
|
0 commit comments