Rustc changes for permissive provenance
This commit is contained in:
parent
0034bbca26
commit
bd5fce65c6
12 changed files with 142 additions and 45 deletions
|
@ -98,7 +98,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
pub fn misc_cast(
|
||||
&self,
|
||||
&mut self,
|
||||
src: &ImmTy<'tcx, M::PointerTag>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
|
||||
|
@ -139,7 +139,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
|
||||
assert!(src.layout.is_zst());
|
||||
let discr_layout = self.layout_of(discr.ty)?;
|
||||
return Ok(self.cast_from_int_like(discr.val, discr_layout, cast_ty).into());
|
||||
|
||||
let scalar = Scalar::from_uint(discr.val, discr_layout.layout.size());
|
||||
return Ok(self.cast_from_int_like(scalar, discr_layout, cast_ty)?.into());
|
||||
}
|
||||
}
|
||||
Variants::Multiple { .. } => {}
|
||||
|
@ -170,38 +172,65 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
// # The remaining source values are scalar and "int-like".
|
||||
let scalar = src.to_scalar()?;
|
||||
|
||||
// For all remaining casts, we either
|
||||
// (a) cast a raw ptr to usize, or
|
||||
// (b) cast from an integer-like (including bool, char, enums).
|
||||
// In both cases we want the bits.
|
||||
let bits = src.to_scalar()?.to_bits(src.layout.size)?;
|
||||
Ok(self.cast_from_int_like(bits, src.layout, cast_ty).into())
|
||||
// If we are casting from a pointer to something
|
||||
// that is not a pointer, mark the pointer as exposed
|
||||
if src.layout.ty.is_any_ptr() && !cast_ty.is_any_ptr() {
|
||||
let ptr = self.scalar_to_ptr(scalar)?;
|
||||
|
||||
match ptr.into_pointer_or_addr() {
|
||||
Ok(ptr) => {
|
||||
M::expose_ptr(self, ptr)?;
|
||||
}
|
||||
Err(_) => {
|
||||
// do nothing, exposing an invalid pointer
|
||||
// has no meaning
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
|
||||
}
|
||||
|
||||
fn cast_from_int_like(
|
||||
pub fn cast_from_int_like(
|
||||
&self,
|
||||
v: u128, // raw bits (there is no ScalarTy so we separate data+layout)
|
||||
scalar: Scalar<M::PointerTag>, // input value (there is no ScalarTy so we separate data+layout)
|
||||
src_layout: TyAndLayout<'tcx>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> Scalar<M::PointerTag> {
|
||||
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
|
||||
// Let's make sure v is sign-extended *if* it has a signed type.
|
||||
let signed = src_layout.abi.is_signed(); // Also asserts that abi is `Scalar`.
|
||||
|
||||
let v = scalar.to_bits(src_layout.size)?;
|
||||
let v = if signed { self.sign_extend(v, src_layout) } else { v };
|
||||
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
|
||||
use rustc_middle::ty::TyKind::*;
|
||||
match *cast_ty.kind() {
|
||||
Int(_) | Uint(_) | RawPtr(_) => {
|
||||
|
||||
Ok(match *cast_ty.kind() {
|
||||
Int(_) | Uint(_) => {
|
||||
let size = match *cast_ty.kind() {
|
||||
Int(t) => Integer::from_int_ty(self, t).size(),
|
||||
Uint(t) => Integer::from_uint_ty(self, t).size(),
|
||||
RawPtr(_) => self.pointer_size(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let v = size.truncate(v);
|
||||
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);
|
||||
if addr == 0 {
|
||||
assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId");
|
||||
}
|
||||
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),
|
||||
|
@ -214,7 +243,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
// Casts to bool are not permitted by rustc, no need to handle them here.
|
||||
_ => span_bug!(self.cur_span(), "invalid int to {:?} cast", cast_ty),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::PointerTag>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue