Implement ConstantIndex handling and use that instead using our own ProjectionElem variant
This commit is contained in:
parent
2d99ea0be2
commit
d03eb339aa
@ -101,19 +101,19 @@ fn from(v: ImmTy<'tcx>) -> Self {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Value<'tcx> {
|
impl<'tcx> Value<'tcx> {
|
||||||
fn project(
|
fn project(&self, proj: impl Iterator<Item = Option<PlaceElem<'tcx>>>) -> Option<&Value<'tcx>> {
|
||||||
&self,
|
|
||||||
proj: impl Iterator<Item = Option<ProjectionElem<FieldIdx, Ty<'tcx>>>>,
|
|
||||||
) -> Option<&Value<'tcx>> {
|
|
||||||
let mut this = self;
|
let mut this = self;
|
||||||
for proj in proj {
|
for proj in proj {
|
||||||
this = match (proj?, this) {
|
this = match (proj?, this) {
|
||||||
(ProjectionElem::Field(idx, _), Value::Aggregate { fields, .. }) => {
|
(ProjectionElem::Field(idx, _), Value::Aggregate { fields, .. }) => {
|
||||||
fields.get(idx).unwrap_or(&Value::Uninit)
|
fields.get(idx).unwrap_or(&Value::Uninit)
|
||||||
}
|
}
|
||||||
(ProjectionElem::Index(idx), Value::Aggregate { fields, .. }) => {
|
(
|
||||||
fields.get(idx).unwrap_or(&Value::Uninit)
|
ProjectionElem::ConstantIndex { offset, min_length: 1, from_end: false },
|
||||||
}
|
Value::Aggregate { fields, .. },
|
||||||
|
) => fields
|
||||||
|
.get(FieldIdx::from_u32(offset.try_into().ok()?))
|
||||||
|
.unwrap_or(&Value::Uninit),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -205,7 +205,7 @@ fn local_decls(&self) -> &'mir LocalDecls<'tcx> {
|
|||||||
|
|
||||||
fn get_const(&self, place: Place<'tcx>) -> Option<&Value<'tcx>> {
|
fn get_const(&self, place: Place<'tcx>) -> Option<&Value<'tcx>> {
|
||||||
self.locals[place.local]
|
self.locals[place.local]
|
||||||
.project(place.projection.iter().map(|proj| self.simple_projection(proj)))
|
.project(place.projection.iter().map(|proj| self.try_eval_index_offset(proj)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove `local` from the pool of `Locals`. Allows writing to them,
|
/// Remove `local` from the pool of `Locals`. Allows writing to them,
|
||||||
@ -719,29 +719,18 @@ fn eval_rvalue(
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_projection(
|
fn try_eval_index_offset(&self, proj: PlaceElem<'tcx>) -> Option<PlaceElem<'tcx>> {
|
||||||
&self,
|
|
||||||
proj: ProjectionElem<Local, Ty<'tcx>>,
|
|
||||||
) -> Option<ProjectionElem<FieldIdx, Ty<'tcx>>> {
|
|
||||||
Some(match proj {
|
Some(match proj {
|
||||||
ProjectionElem::Deref => ProjectionElem::Deref,
|
|
||||||
ProjectionElem::Field(idx, ty) => ProjectionElem::Field(idx, ty),
|
|
||||||
ProjectionElem::Index(local) => {
|
ProjectionElem::Index(local) => {
|
||||||
let val = self.get_const(local.into())?;
|
let val = self.get_const(local.into())?;
|
||||||
let op = val.immediate()?;
|
let op = val.immediate()?;
|
||||||
ProjectionElem::Index(FieldIdx::from_u32(
|
ProjectionElem::ConstantIndex {
|
||||||
self.ecx.read_target_usize(op).ok()?.try_into().ok()?,
|
offset: self.ecx.read_target_usize(op).ok()?,
|
||||||
))
|
min_length: 1,
|
||||||
|
from_end: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
|
other => other,
|
||||||
ProjectionElem::ConstantIndex { offset, min_length, from_end }
|
|
||||||
}
|
|
||||||
ProjectionElem::Subslice { from, to, from_end } => {
|
|
||||||
ProjectionElem::Subslice { from, to, from_end }
|
|
||||||
}
|
|
||||||
ProjectionElem::Downcast(a, b) => ProjectionElem::Downcast(a, b),
|
|
||||||
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
|
|
||||||
ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user