adjust constValue::Slice to work for arbitrary slice types
This commit is contained in:
parent
0692db1a90
commit
ea22adbabd
12 changed files with 75 additions and 63 deletions
|
@ -151,19 +151,26 @@ pub(super) fn op_to_const<'tcx>(
|
|||
Immediate::Scalar(x) => ConstValue::Scalar(x),
|
||||
Immediate::ScalarPair(a, b) => {
|
||||
debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
|
||||
// FIXME: assert that this has an appropriate type.
|
||||
// Currently we actually get here for non-[u8] slices during valtree construction!
|
||||
let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to actually allocated memory";
|
||||
// This codepath solely exists for `valtree_to_const_value` to not need to generate
|
||||
// a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
|
||||
// that case.
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap().ty; // `false` = no raw ptrs
|
||||
debug_assert!(
|
||||
matches!(
|
||||
ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
|
||||
ty::Str | ty::Slice(..),
|
||||
),
|
||||
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
|
||||
imm.layout.ty,
|
||||
);
|
||||
let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
|
||||
// We know `offset` is relative to the allocation, so we can use `into_parts`.
|
||||
// We use `ConstValue::Slice` so that we don't have to generate an allocation for
|
||||
// `ConstValue::Indirect` here.
|
||||
let (alloc_id, offset) = a.to_pointer(ecx).expect(msg).into_parts();
|
||||
let alloc_id = alloc_id.expect(msg);
|
||||
let data = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
let start = offset.bytes_usize();
|
||||
let len = b.to_target_usize(ecx).expect(msg);
|
||||
let len: usize = len.try_into().unwrap();
|
||||
ConstValue::Slice { data, start, end: start + len }
|
||||
assert!(offset == abi::Size::ZERO, "{}", msg);
|
||||
let meta = b.to_target_usize(ecx).expect(msg);
|
||||
ConstValue::Slice { data, meta }
|
||||
}
|
||||
Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
|
||||
},
|
||||
|
|
|
@ -351,7 +351,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) {
|
||||
(&ty::Array(_, length), &ty::Slice(_)) => {
|
||||
let ptr = self.read_scalar(src)?;
|
||||
let ptr = self.read_pointer(src)?;
|
||||
// u64 cast is from usize to u64, which is always good
|
||||
let val = Immediate::new_slice(
|
||||
ptr,
|
||||
|
@ -367,6 +367,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
return self.write_immediate(*val, dest);
|
||||
}
|
||||
let (old_data, old_vptr) = val.to_scalar_pair();
|
||||
let old_data = old_data.to_pointer(self)?;
|
||||
let old_vptr = old_vptr.to_pointer(self)?;
|
||||
let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
|
||||
if old_trait != data_a.principal() {
|
||||
|
@ -378,7 +379,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
(_, &ty::Dynamic(data, _, ty::Dyn)) => {
|
||||
// Initial cast from sized to dyn trait
|
||||
let vtable = self.get_vtable_ptr(src_pointee_ty, data.principal())?;
|
||||
let ptr = self.read_scalar(src)?;
|
||||
let ptr = self.read_pointer(src)?;
|
||||
let val = Immediate::new_dyn_trait(ptr, vtable, &*self.tcx);
|
||||
self.write_immediate(val, dest)
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
|
|||
sym::type_name => {
|
||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
let alloc = alloc_type_name(tcx, tp_ty);
|
||||
ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() }
|
||||
ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() }
|
||||
}
|
||||
sym::needs_drop => {
|
||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
|
|
|
@ -43,24 +43,30 @@ impl<Prov: Provenance> From<Scalar<Prov>> for Immediate<Prov> {
|
|||
}
|
||||
|
||||
impl<Prov: Provenance> Immediate<Prov> {
|
||||
pub fn from_pointer(p: Pointer<Prov>, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::Scalar(Scalar::from_pointer(p, cx))
|
||||
pub fn from_pointer(ptr: Pointer<Prov>, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::Scalar(Scalar::from_pointer(ptr, cx))
|
||||
}
|
||||
|
||||
pub fn from_maybe_pointer(p: Pointer<Option<Prov>>, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::Scalar(Scalar::from_maybe_pointer(p, cx))
|
||||
pub fn from_maybe_pointer(ptr: Pointer<Option<Prov>>, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::Scalar(Scalar::from_maybe_pointer(ptr, cx))
|
||||
}
|
||||
|
||||
pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::ScalarPair(val, Scalar::from_target_usize(len, cx))
|
||||
pub fn new_slice(ptr: Pointer<Option<Prov>>, len: u64, cx: &impl HasDataLayout) -> Self {
|
||||
Immediate::ScalarPair(
|
||||
Scalar::from_maybe_pointer(ptr, cx),
|
||||
Scalar::from_target_usize(len, cx),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_dyn_trait(
|
||||
val: Scalar<Prov>,
|
||||
val: Pointer<Option<Prov>>,
|
||||
vtable: Pointer<Option<Prov>>,
|
||||
cx: &impl HasDataLayout,
|
||||
) -> Self {
|
||||
Immediate::ScalarPair(val, Scalar::from_maybe_pointer(vtable, cx))
|
||||
Immediate::ScalarPair(
|
||||
Scalar::from_maybe_pointer(val, cx),
|
||||
Scalar::from_maybe_pointer(vtable, cx),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -722,16 +728,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
mir::ConstValue::Scalar(x) => Operand::Immediate(adjust_scalar(x)?.into()),
|
||||
mir::ConstValue::ZeroSized => Operand::Immediate(Immediate::Uninit),
|
||||
mir::ConstValue::Slice { data, start, end } => {
|
||||
mir::ConstValue::Slice { data, meta } => {
|
||||
// We rely on mutability being set correctly in `data` to prevent writes
|
||||
// where none should happen.
|
||||
let ptr = Pointer::new(
|
||||
self.tcx.reserve_and_set_memory_alloc(data),
|
||||
Size::from_bytes(start), // offset: `start`
|
||||
);
|
||||
let ptr = Pointer::new(self.tcx.reserve_and_set_memory_alloc(data), Size::ZERO);
|
||||
Operand::Immediate(Immediate::new_slice(
|
||||
Scalar::from_pointer(self.global_base_pointer(ptr)?, &*self.tcx),
|
||||
u64::try_from(end.checked_sub(start).unwrap()).unwrap(), // len: `end - start`
|
||||
self.global_base_pointer(ptr)?.into(),
|
||||
meta,
|
||||
self,
|
||||
))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue