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
|
@ -2147,6 +2147,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CastKind::PointerAddress => {
|
||||||
|
let ty_from = op.ty(body, tcx);
|
||||||
|
let cast_ty_from = CastTy::from_ty(ty_from);
|
||||||
|
let cast_ty_to = CastTy::from_ty(*ty);
|
||||||
|
match (cast_ty_from, cast_ty_to) {
|
||||||
|
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
|
||||||
|
_ => {
|
||||||
|
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CastKind::Misc => {
|
CastKind::Misc => {
|
||||||
let ty_from = op.ty(body, tcx);
|
let ty_from = op.ty(body, tcx);
|
||||||
let cast_ty_from = CastTy::from_ty(ty_from);
|
let cast_ty_from = CastTy::from_ty(ty_from);
|
||||||
|
@ -2155,7 +2167,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
(None, _)
|
(None, _)
|
||||||
| (_, None | Some(CastTy::FnPtr))
|
| (_, None | Some(CastTy::FnPtr))
|
||||||
| (Some(CastTy::Float), Some(CastTy::Ptr(_)))
|
| (Some(CastTy::Float), Some(CastTy::Ptr(_)))
|
||||||
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Float)) => {
|
| (
|
||||||
|
Some(CastTy::Ptr(_) | CastTy::FnPtr),
|
||||||
|
Some(CastTy::Float | CastTy::Int(_)),
|
||||||
|
) => {
|
||||||
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
|
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
@ -2163,8 +2178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
|
Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
|
||||||
)
|
)
|
||||||
| (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
|
| (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
|
||||||
| (Some(CastTy::Ptr(_)), Some(CastTy::Int(_) | CastTy::Ptr(_)))
|
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
|
||||||
| (Some(CastTy::FnPtr), Some(CastTy::Int(_) | CastTy::Ptr(_))) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,7 +607,7 @@ fn codegen_stmt<'tcx>(
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
||||||
}
|
}
|
||||||
Rvalue::Cast(CastKind::Misc, ref operand, to_ty) => {
|
Rvalue::Cast(CastKind::Misc | CastKind::PointerAddress, ref operand, to_ty) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
let from_ty = operand.layout().ty;
|
let from_ty = operand.layout().ty;
|
||||||
let to_ty = fx.monomorphize(to_ty);
|
let to_ty = fx.monomorphize(to_ty);
|
||||||
|
|
|
@ -181,6 +181,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let cast = bx.cx().layout_of(self.monomorphize(mir_cast_ty));
|
let cast = bx.cx().layout_of(self.monomorphize(mir_cast_ty));
|
||||||
|
|
||||||
let val = match *kind {
|
let val = match *kind {
|
||||||
|
mir::CastKind::PointerAddress => {
|
||||||
|
assert!(bx.cx().is_backend_immediate(cast));
|
||||||
|
let llptr = operand.immediate();
|
||||||
|
let llcast_ty = bx.cx().immediate_backend_type(cast);
|
||||||
|
let lladdr = bx.ptrtoint(llptr, llcast_ty);
|
||||||
|
OperandValue::Immediate(lladdr)
|
||||||
|
}
|
||||||
mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => {
|
mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => {
|
||||||
match *operand.layout.ty.kind() {
|
match *operand.layout.ty.kind() {
|
||||||
ty::FnDef(def_id, substs) => {
|
ty::FnDef(def_id, substs) => {
|
||||||
|
@ -362,9 +369,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Ptr(_)) => {
|
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Ptr(_)) => {
|
||||||
bx.pointercast(llval, ll_t_out)
|
bx.pointercast(llval, ll_t_out)
|
||||||
}
|
}
|
||||||
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
|
|
||||||
bx.ptrtoint(llval, ll_t_out)
|
|
||||||
}
|
|
||||||
(CastTy::Int(_), CastTy::Ptr(_)) => {
|
(CastTy::Int(_), CastTy::Ptr(_)) => {
|
||||||
let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
|
let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
|
||||||
bx.inttoptr(usize_llval, ll_t_out)
|
bx.inttoptr(usize_llval, ll_t_out)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::assert_matches::assert_matches;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
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)?;
|
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 => {
|
Misc => {
|
||||||
let src = self.read_immediate(src)?;
|
let src = self.read_immediate(src)?;
|
||||||
let res = self.misc_cast(&src, cast_ty)?;
|
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".
|
// # The remaining source values are scalar and "int-like".
|
||||||
let scalar = src.to_scalar()?;
|
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
|
pub fn pointer_address_cast(
|
||||||
// that is not a pointer, mark the pointer as exposed
|
&mut self,
|
||||||
if src.layout.ty.is_any_ptr() && !cast_ty.is_any_ptr() {
|
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)?;
|
let ptr = self.scalar_to_ptr(scalar)?;
|
||||||
|
|
||||||
match ptr.into_pointer_or_addr() {
|
match ptr.into_pointer_or_addr() {
|
||||||
Ok(ptr) => {
|
Ok(ptr) => M::expose_ptr(self, ptr)?,
|
||||||
M::expose_ptr(self, ptr)?;
|
Err(_) => {} // do nothing, exposing an invalid pointer has no meaning
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
// do nothing, exposing an invalid pointer
|
|
||||||
// has no meaning
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
|
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_infer::traits::{ImplSource, Obligation, ObligationCause};
|
||||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::cast::CastTy;
|
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
||||||
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
|
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
|
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
|
||||||
|
@ -543,15 +542,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
// in the type of any local, which also excludes casts).
|
// in the type of any local, which also excludes casts).
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
|
Rvalue::Cast(CastKind::PointerAddress, _, _) => {
|
||||||
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);
|
self.check_op(ops::RawPtrToIntCast);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Rvalue::Cast(CastKind::Misc, _, _) => {}
|
||||||
|
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
||||||
Rvalue::ShallowInitBox(_, _) => {}
|
Rvalue::ShallowInitBox(_, _) => {}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use rustc_hir as hir;
|
||||||
use rustc_middle::mir::traversal::ReversePostorderIter;
|
use rustc_middle::mir::traversal::ReversePostorderIter;
|
||||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::cast::CastTy;
|
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -502,18 +501,11 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
|
|
||||||
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
|
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
|
// ptr-to-int casts are not possible in consts and thus not promotable
|
||||||
return Err(Unpromotable);
|
Rvalue::Cast(CastKind::PointerAddress, _, _) => return Err(Unpromotable),
|
||||||
}
|
|
||||||
// int-to-ptr casts are fine, they just use the integer value at pointer type.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// int-to-ptr casts are fine, they just use the integer value at pointer type.
|
||||||
|
Rvalue::Cast(_, operand, _) => {
|
||||||
self.validate_operand(operand)?;
|
self.validate_operand(operand)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2604,9 +2604,19 @@ pub enum Rvalue<'tcx> {
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
static_assert_size!(Rvalue<'_>, 40);
|
static_assert_size!(Rvalue<'_>, 40);
|
||||||
|
|
||||||
|
impl<'tcx> Rvalue<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
pub fn is_pointer_int_cast(&self) -> bool {
|
||||||
|
matches!(self, Rvalue::Cast(CastKind::PointerAddress, _, _))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
pub enum CastKind {
|
pub enum CastKind {
|
||||||
Misc,
|
Misc,
|
||||||
|
/// A pointer to address cast. A cast between a pointer and an integer type,
|
||||||
|
/// or between a function pointer and an integer type.
|
||||||
|
PointerAddress,
|
||||||
Pointer(PointerCast),
|
Pointer(PointerCast),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::mir::*;
|
use crate::mir::*;
|
||||||
use crate::ty::cast::CastTy;
|
|
||||||
use crate::ty::subst::Subst;
|
use crate::ty::subst::Subst;
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -224,22 +223,6 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
_ => RvalueInitializationState::Deep,
|
_ => RvalueInitializationState::Deep,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pointer_int_cast<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> bool
|
|
||||||
where
|
|
||||||
D: HasLocalDecls<'tcx>,
|
|
||||||
{
|
|
||||||
if let Rvalue::Cast(CastKind::Misc, src_op, dest_ty) = self {
|
|
||||||
if let Some(CastTy::Int(_)) = CastTy::from_ty(*dest_ty) {
|
|
||||||
let src_ty = src_op.ty(local_decls, tcx);
|
|
||||||
if let Some(CastTy::FnPtr | CastTy::Ptr(_)) = CastTy::from_ty(src_ty) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Operand<'tcx> {
|
impl<'tcx> Operand<'tcx> {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use rustc_middle::mir::AssertKind;
|
||||||
use rustc_middle::mir::Place;
|
use rustc_middle::mir::Place;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
|
use rustc_middle::ty::cast::CastTy;
|
||||||
use rustc_middle::ty::{self, Ty, UpvarSubsts};
|
use rustc_middle::ty::{self, Ty, UpvarSubsts};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -188,11 +189,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
|
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
|
||||||
}
|
}
|
||||||
ExprKind::Cast { source } => {
|
ExprKind::Cast { source } => {
|
||||||
|
let source = &this.thir[source];
|
||||||
|
let from_ty = CastTy::from_ty(source.ty);
|
||||||
|
let cast_ty = CastTy::from_ty(expr.ty);
|
||||||
|
let cast_kind = match (from_ty, cast_ty) {
|
||||||
|
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
|
||||||
|
CastKind::PointerAddress
|
||||||
|
}
|
||||||
|
(_, _) => CastKind::Misc,
|
||||||
|
};
|
||||||
let source = unpack!(
|
let source = unpack!(
|
||||||
block =
|
block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
|
||||||
this.as_operand(block, scope, &this.thir[source], None, NeedsTemporary::No)
|
|
||||||
);
|
);
|
||||||
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
|
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
|
||||||
}
|
}
|
||||||
ExprKind::Pointer { cast, source } => {
|
ExprKind::Pointer { cast, source } => {
|
||||||
let source = unpack!(
|
let source = unpack!(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
|
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
|
||||||
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::{self, Local, LocalDecls, Location, Place, StatementKind};
|
use rustc_middle::mir::{self, Local, Location, Place, StatementKind};
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
|
|
||||||
use crate::{Analysis, AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
|
use crate::{Analysis, AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
|
||||||
|
|
||||||
|
@ -193,27 +192,21 @@ impl DefUse {
|
||||||
/// This is basically written for dead store elimination and nothing else.
|
/// This is basically written for dead store elimination and nothing else.
|
||||||
///
|
///
|
||||||
/// All of the caveats of `MaybeLiveLocals` apply.
|
/// All of the caveats of `MaybeLiveLocals` apply.
|
||||||
pub struct MaybeTransitiveLiveLocals<'a, 'tcx> {
|
pub struct MaybeTransitiveLiveLocals<'a> {
|
||||||
always_live: &'a BitSet<Local>,
|
always_live: &'a BitSet<Local>,
|
||||||
local_decls: &'a LocalDecls<'tcx>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MaybeTransitiveLiveLocals<'a, 'tcx> {
|
impl<'a> MaybeTransitiveLiveLocals<'a> {
|
||||||
/// The `always_alive` set is the set of locals to which all stores should unconditionally be
|
/// The `always_alive` set is the set of locals to which all stores should unconditionally be
|
||||||
/// considered live.
|
/// considered live.
|
||||||
///
|
///
|
||||||
/// This should include at least all locals that are ever borrowed.
|
/// This should include at least all locals that are ever borrowed.
|
||||||
pub fn new(
|
pub fn new(always_live: &'a BitSet<Local>) -> Self {
|
||||||
always_live: &'a BitSet<Local>,
|
MaybeTransitiveLiveLocals { always_live }
|
||||||
local_decls: &'a LocalDecls<'tcx>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
MaybeTransitiveLiveLocals { always_live, local_decls, tcx }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
|
impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
||||||
type Domain = ChunkedBitSet<Local>;
|
type Domain = ChunkedBitSet<Local>;
|
||||||
type Direction = Backward;
|
type Direction = Backward;
|
||||||
|
|
||||||
|
@ -241,7 +234,7 @@ impl<'a> GenKill<Local> for TransferWrapper<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
|
impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
|
||||||
fn apply_statement_effect(
|
fn apply_statement_effect(
|
||||||
&self,
|
&self,
|
||||||
trans: &mut Self::Domain,
|
trans: &mut Self::Domain,
|
||||||
|
@ -251,7 +244,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a, 'tcx> {
|
||||||
// Compute the place that we are storing to, if any
|
// Compute the place that we are storing to, if any
|
||||||
let destination = match &statement.kind {
|
let destination = match &statement.kind {
|
||||||
StatementKind::Assign(assign) => {
|
StatementKind::Assign(assign) => {
|
||||||
if assign.1.is_pointer_int_cast(self.local_decls, self.tcx) {
|
if assign.1.is_pointer_int_cast() {
|
||||||
// Pointer to int casts may be side-effects due to exposing the provenance.
|
// Pointer to int casts may be side-effects due to exposing the provenance.
|
||||||
// While the model is undecided, we should be conservative. See
|
// While the model is undecided, we should be conservative. See
|
||||||
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
||||||
|
|
|
@ -24,7 +24,7 @@ use rustc_mir_dataflow::{impls::MaybeTransitiveLiveLocals, Analysis};
|
||||||
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
|
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
|
||||||
/// can be generated via the [`get_borrowed_locals`] function.
|
/// can be generated via the [`get_borrowed_locals`] function.
|
||||||
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
|
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
|
||||||
let mut live = MaybeTransitiveLiveLocals::new(borrowed, &body.local_decls, tcx)
|
let mut live = MaybeTransitiveLiveLocals::new(borrowed)
|
||||||
.into_engine(tcx, body)
|
.into_engine(tcx, body)
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
@ -34,7 +34,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
|
||||||
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
|
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
|
||||||
let loc = Location { block: bb, statement_index };
|
let loc = Location { block: bb, statement_index };
|
||||||
if let StatementKind::Assign(assign) = &statement.kind {
|
if let StatementKind::Assign(assign) = &statement.kind {
|
||||||
if assign.1.is_pointer_int_cast(&body.local_decls, tcx) {
|
if assign.1.is_pointer_int_cast() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
// + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
|
// + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
|
||||||
// + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
|
// + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
|
||||||
_2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
|
_2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
|
||||||
_1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
|
_1 = move _2 as usize (PointerAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
|
||||||
StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
|
StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
|
||||||
StorageDead(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:39: 7:40
|
StorageDead(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:39: 7:40
|
||||||
StorageLive(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
|
StorageLive(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:8:5: 8:12
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/reify_fn_ptr.rs:4:13: 4:17
|
// + span: $DIR/reify_fn_ptr.rs:4:13: 4:17
|
||||||
// + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: fn() {main}, val: Value(Scalar(<ZST>)) }
|
||||||
_2 = move _3 as usize (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
|
_2 = move _3 as usize (PointerAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26
|
||||||
StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26
|
StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26
|
||||||
_1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
|
_1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41
|
||||||
StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41
|
StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41
|
||||||
|
|
|
@ -19,12 +19,12 @@
|
||||||
StorageLive(_2); // scope 0 at $DIR/provenance_soundness.rs:8:9: 8:11
|
StorageLive(_2); // scope 0 at $DIR/provenance_soundness.rs:8:9: 8:11
|
||||||
StorageLive(_3); // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
|
StorageLive(_3); // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
|
||||||
_3 = _1; // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
|
_3 = _1; // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:15
|
||||||
_2 = move _3 as usize (Misc); // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:24
|
_2 = move _3 as usize (PointerAddress); // scope 0 at $DIR/provenance_soundness.rs:8:14: 8:24
|
||||||
StorageDead(_3); // scope 0 at $DIR/provenance_soundness.rs:8:23: 8:24
|
StorageDead(_3); // scope 0 at $DIR/provenance_soundness.rs:8:23: 8:24
|
||||||
StorageLive(_4); // scope 1 at $DIR/provenance_soundness.rs:9:9: 9:11
|
StorageLive(_4); // scope 1 at $DIR/provenance_soundness.rs:9:9: 9:11
|
||||||
StorageLive(_5); // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
|
StorageLive(_5); // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
|
||||||
_5 = _1; // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
|
_5 = _1; // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:15
|
||||||
_4 = move _5 as isize (Misc); // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:24
|
_4 = move _5 as isize (PointerAddress); // scope 1 at $DIR/provenance_soundness.rs:9:14: 9:24
|
||||||
StorageDead(_5); // scope 1 at $DIR/provenance_soundness.rs:9:23: 9:24
|
StorageDead(_5); // scope 1 at $DIR/provenance_soundness.rs:9:23: 9:24
|
||||||
_0 = const (); // scope 0 at $DIR/provenance_soundness.rs:7:32: 10:2
|
_0 = const (); // scope 0 at $DIR/provenance_soundness.rs:7:32: 10:2
|
||||||
StorageDead(_4); // scope 1 at $DIR/provenance_soundness.rs:10:1: 10:2
|
StorageDead(_4); // scope 1 at $DIR/provenance_soundness.rs:10:1: 10:2
|
||||||
|
|
|
@ -125,16 +125,11 @@ fn check_rvalue<'tcx>(
|
||||||
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||||
check_place(tcx, *place, span, body)
|
check_place(tcx, *place, span, body)
|
||||||
},
|
},
|
||||||
Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
|
Rvalue::Cast(CastKind::PointerAddress, _, _) => {
|
||||||
use rustc_middle::ty::cast::CastTy;
|
|
||||||
let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
|
|
||||||
let cast_out = CastTy::from_ty(*cast_ty).expect("bad output type for cast");
|
|
||||||
match (cast_in, cast_out) {
|
|
||||||
(CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
|
|
||||||
Err((span, "casting pointers to ints is unstable in const fn".into()))
|
Err((span, "casting pointers to ints is unstable in const fn".into()))
|
||||||
},
|
},
|
||||||
_ => check_operand(tcx, operand, span, body),
|
Rvalue::Cast(CastKind::Misc, operand, _) => {
|
||||||
}
|
check_operand(tcx, operand, span, body)
|
||||||
},
|
},
|
||||||
Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
|
Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
|
||||||
check_operand(tcx, operand, span, body)
|
check_operand(tcx, operand, span, body)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue