simplify some code that depend on Deref
This commit is contained in:
parent
41419e7036
commit
c0e4230bf5
3 changed files with 32 additions and 28 deletions
|
@ -435,16 +435,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
LocalRef::Place(place) => place,
|
LocalRef::Place(place) => place,
|
||||||
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
|
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
|
||||||
LocalRef::Operand(..) => {
|
LocalRef::Operand(..) => {
|
||||||
if let Some(elem) = place_ref
|
if place_ref.ret_deref().is_some() {
|
||||||
.projection
|
base = 1;
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|elem| matches!(elem.1, mir::ProjectionElem::Deref))
|
|
||||||
{
|
|
||||||
base = elem.0 + 1;
|
|
||||||
let cg_base = self.codegen_consume(
|
let cg_base = self.codegen_consume(
|
||||||
bx,
|
bx,
|
||||||
mir::PlaceRef { projection: &place_ref.projection[..elem.0], ..place_ref },
|
mir::PlaceRef { projection: &place_ref.projection[..0], ..place_ref },
|
||||||
);
|
);
|
||||||
|
|
||||||
cg_base.deref(bx.cx())
|
cg_base.deref(bx.cx())
|
||||||
|
|
|
@ -1461,6 +1461,16 @@ impl<'tcx> Place<'tcx> {
|
||||||
self.projection.iter().any(|elem| elem.is_indirect())
|
self.projection.iter().any(|elem| elem.is_indirect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If MirPhase >= Derefered and if projection contains Deref,
|
||||||
|
/// It's guaranteed to be in the first place
|
||||||
|
pub fn ret_deref(&self) -> Option<PlaceElem<'tcx>> {
|
||||||
|
if !self.projection.is_empty() && self.projection[0] == PlaceElem::Deref {
|
||||||
|
return Some(self.projection[0]);
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
|
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
|
||||||
/// a single deref of a local.
|
/// a single deref of a local.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -1533,6 +1543,16 @@ impl<'tcx> PlaceRef<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If MirPhase >= Derefered and if projection contains Deref,
|
||||||
|
/// It's guaranteed to be in the first place
|
||||||
|
pub fn ret_deref(&self) -> Option<PlaceElem<'tcx>> {
|
||||||
|
if !self.projection.is_empty() && self.projection[0] == PlaceElem::Deref {
|
||||||
|
return Some(self.projection[0]);
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// If this place represents a local variable like `_X` with no
|
/// If this place represents a local variable like `_X` with no
|
||||||
/// projections, return `Some(_X)`.
|
/// projections, return `Some(_X)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -15,22 +15,13 @@ pub struct AddRetag;
|
||||||
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
|
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
|
||||||
/// copies. Data races are UB.)
|
/// copies. Data races are UB.)
|
||||||
fn is_stable(place: PlaceRef<'_>) -> bool {
|
fn is_stable(place: PlaceRef<'_>) -> bool {
|
||||||
place.projection.iter().all(|elem| {
|
if place.ret_deref().is_some() {
|
||||||
match elem {
|
|
||||||
// Which place this evaluates to can change with any memory write,
|
// Which place this evaluates to can change with any memory write,
|
||||||
// so cannot assume this to be stable.
|
// so cannot assume deref to be stable.
|
||||||
ProjectionElem::Deref => false,
|
return false;
|
||||||
// Array indices are interesting, but MIR building generates a *fresh*
|
} else {
|
||||||
// temporary for every array access, so the index cannot be changed as
|
return true;
|
||||||
// a side-effect.
|
|
||||||
ProjectionElem::Index { .. } |
|
|
||||||
// The rest is completely boring, they just offset by a constant.
|
|
||||||
ProjectionElem::Field { .. } |
|
|
||||||
ProjectionElem::ConstantIndex { .. } |
|
|
||||||
ProjectionElem::Subslice { .. } |
|
|
||||||
ProjectionElem::Downcast { .. } => true,
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
|
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
|
||||||
|
@ -91,10 +82,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
||||||
};
|
};
|
||||||
let place_base_raw = |place: &Place<'tcx>| {
|
let place_base_raw = |place: &Place<'tcx>| {
|
||||||
// If this is a `Deref`, get the type of what we are deref'ing.
|
// If this is a `Deref`, get the type of what we are deref'ing.
|
||||||
let deref_base =
|
if place.ret_deref().is_some() {
|
||||||
place.projection.iter().rposition(|p| matches!(p, ProjectionElem::Deref));
|
let base_proj = &place.projection[..0];
|
||||||
if let Some(deref_base) = deref_base {
|
|
||||||
let base_proj = &place.projection[..deref_base];
|
|
||||||
let ty = Place::ty_from(place.local, base_proj, &*local_decls, tcx).ty;
|
let ty = Place::ty_from(place.local, base_proj, &*local_decls, tcx).ty;
|
||||||
ty.is_unsafe_ptr()
|
ty.is_unsafe_ptr()
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue