|
4 | 4 |
|
5 | 5 | use std::assert_matches::assert_matches;
|
6 | 6 |
|
| 7 | +use either::Either; |
7 | 8 | use rustc_abi::{FieldIdx, HasDataLayout, Size};
|
8 | 9 | use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
9 | 10 | use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
|
@@ -866,18 +867,43 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
866 | 867 | count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
|
867 | 868 | name: &'static str,
|
868 | 869 | ) -> InterpResult<'tcx> {
|
869 |
| - let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?; |
| 870 | + let dst_layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?; |
| 871 | + let src_layout = self.layout_of(byte.layout.ty)?; |
| 872 | + |
| 873 | + if src_layout.size.bytes_usize() != 1 { |
| 874 | + throw_ub_custom!( |
| 875 | + fluent::const_eval_scalar_size_mismatch, |
| 876 | + target_size = 1, |
| 877 | + data_size = src_layout.size.bytes(), |
| 878 | + ); |
| 879 | + } |
870 | 880 |
|
871 | 881 | let dst = self.read_pointer(dst)?;
|
872 |
| - let byte = self.read_scalar(byte)?.to_u8()?; |
| 882 | + |
873 | 883 | let count = self.read_target_usize(count)?;
|
874 | 884 |
|
875 | 885 | // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
|
876 | 886 | // but no actual allocation can be big enough for the difference to be noticeable.
|
877 | 887 | let len = self
|
878 |
| - .compute_size_in_bytes(layout.size, count) |
| 888 | + .compute_size_in_bytes(dst_layout.size, count) |
879 | 889 | .ok_or_else(|| err_ub_custom!(fluent::const_eval_size_overflow, name = name))?;
|
880 | 890 |
|
| 891 | + let byte = match self.read_immediate_raw(byte)? { |
| 892 | + Either::Left(src_place) => { |
| 893 | + // val is not an immediate, possibly uninit. |
| 894 | + self.mem_copy_repeatedly( |
| 895 | + src_place.ptr(), |
| 896 | + dst, |
| 897 | + Size::from_bytes(1), |
| 898 | + len.bytes(), |
| 899 | + /* nonoverlapping: */ false, |
| 900 | + )?; |
| 901 | + return interp_ok(()); |
| 902 | + } |
| 903 | + Either::Right(imm) => imm, |
| 904 | + }; |
| 905 | + |
| 906 | + let byte = byte.to_scalar().to_u8()?; |
881 | 907 | let bytes = std::iter::repeat(byte).take(len.bytes_usize());
|
882 | 908 | self.write_bytes_ptr(dst, bytes)
|
883 | 909 | }
|
|
0 commit comments