Add a pointer to address cast kind
A pointer to address cast are often special-cased. Introduce a dedicated cast kind to make them easy distinguishable.
This commit is contained in:
parent
d35d972e69
commit
dff602fc18
15 changed files with 96 additions and 94 deletions
|
@ -1,3 +1,4 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
|
@ -30,6 +31,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.unsize_into(src, cast_ty, dest)?;
|
||||
}
|
||||
|
||||
PointerAddress => {
|
||||
let src = self.read_immediate(src)?;
|
||||
let res = self.pointer_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)?;
|
||||
|
@ -174,23 +181,23 @@ 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()?;
|
||||
Ok(self.cast_from_int_like(scalar, 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
|
||||
}
|
||||
};
|
||||
}
|
||||
pub fn pointer_address_cast(
|
||||
&mut self,
|
||||
src: &ImmTy<'tcx, M::PointerTag>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
|
||||
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_) | ty::FnPtr(_));
|
||||
assert!(cast_ty.is_integral());
|
||||
|
||||
let scalar = src.to_scalar()?;
|
||||
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())
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt;
|
|||
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
|
||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
||||
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
|
||||
|
@ -543,16 +542,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
// in the type of any local, which also excludes casts).
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
|
||||
let operand_ty = operand.ty(self.body, self.tcx);
|
||||
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
|
||||
let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
|
||||
|
||||
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
|
||||
self.check_op(ops::RawPtrToIntCast);
|
||||
}
|
||||
Rvalue::Cast(CastKind::PointerAddress, _, _) => {
|
||||
self.check_op(ops::RawPtrToIntCast);
|
||||
}
|
||||
|
||||
Rvalue::Cast(CastKind::Misc, _, _) => {}
|
||||
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
||||
Rvalue::ShallowInitBox(_, _) => {}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ use rustc_hir as hir;
|
|||
use rustc_middle::mir::traversal::ReversePostorderIter;
|
||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::cast::CastTy;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
|
@ -502,18 +501,11 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
|
||||
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
|
||||
|
||||
Rvalue::Cast(kind, operand, cast_ty) => {
|
||||
if matches!(kind, CastKind::Misc) {
|
||||
let operand_ty = operand.ty(self.body, self.tcx);
|
||||
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
|
||||
let cast_out = CastTy::from_ty(*cast_ty).expect("bad output type for cast");
|
||||
if let (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) = (cast_in, cast_out) {
|
||||
// ptr-to-int casts are not possible in consts and thus not promotable
|
||||
return Err(Unpromotable);
|
||||
}
|
||||
// int-to-ptr casts are fine, they just use the integer value at pointer type.
|
||||
}
|
||||
// ptr-to-int casts are not possible in consts and thus not promotable
|
||||
Rvalue::Cast(CastKind::PointerAddress, _, _) => return Err(Unpromotable),
|
||||
|
||||
// int-to-ptr casts are fine, they just use the integer value at pointer type.
|
||||
Rvalue::Cast(_, operand, _) => {
|
||||
self.validate_operand(operand)?;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue