add cast kind of from_exposed_addr (int-to-ptr casts)

This commit is contained in:
Ralf Jung 2022-06-02 09:05:37 -04:00
parent 5e6bb83268
commit fafccdced3
10 changed files with 93 additions and 39 deletions

View file

@ -37,6 +37,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_immediate(res, dest)?;
}
PointerFromExposedAddress => {
let src = self.read_immediate(src)?;
let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
self.write_immediate(res, dest)?;
}
Misc => {
let src = self.read_immediate(src)?;
let res = self.misc_cast(&src, cast_ty)?;
@ -201,6 +207,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
}
pub fn pointer_from_exposed_address_cast(
&mut self,
src: &ImmTy<'tcx, M::PointerTag>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
assert!(src.layout.ty.is_integral());
assert_matches!(cast_ty.kind(), ty::RawPtr(_));
// First cast to usize.
let scalar = src.to_scalar()?;
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
let addr = addr.to_machine_usize(self)?;
// Then turn address into pointer.
let ptr = M::ptr_from_addr_cast(&self, addr);
Ok(Scalar::from_maybe_pointer(ptr, self).into())
}
pub fn cast_from_int_like(
&self,
scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
@ -225,16 +249,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Scalar::from_uint(v, size)
}
RawPtr(_) => {
assert!(src_layout.ty.is_integral());
let size = self.pointer_size();
let addr = u64::try_from(size.truncate(v)).unwrap();
let ptr = M::ptr_from_addr_cast(&self, addr);
Scalar::from_maybe_pointer(ptr, self)
}
Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),

View file

@ -519,32 +519,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}
Rvalue::Cast(
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
_,
_,
) => {}
Rvalue::Cast(
CastKind::Pointer(
PointerCast::UnsafeFnPointer
PointerCast::MutToConstPointer
| PointerCast::ArrayToPointer
| PointerCast::UnsafeFnPointer
| PointerCast::ClosureFnPointer(_)
| PointerCast::ReifyFnPointer,
),
_,
_,
) => {
// Nothing to do here. Function pointer casts are allowed now.
// These are all okay; they only change the type, not the data.
}
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
// Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
// in the type of any local, which also excludes casts).
// Unsizing is implemented for CTFE.
}
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
self.check_op(ops::RawPtrToIntCast);
}
Rvalue::Cast(CastKind::PointerFromExposedAddress, _, _) => {
// Since no pointer can ever get exposed (rejected above), this is easy to support.
}
Rvalue::Cast(CastKind::Misc, _, _) => {}

View file

@ -504,7 +504,8 @@ impl<'tcx> Validator<'_, 'tcx> {
// ptr-to-int casts are not possible in consts and thus not promotable
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
// int-to-ptr casts are fine, they just use the integer value at pointer type.
// all ohter casts including int-to-ptr casts are fine, they just use the integer value
// at pointer type.
Rvalue::Cast(_, operand, _) => {
self.validate_operand(operand)?;
}