Make maybe_codegen_consume_direct iterate instead of doing recursion

This commit is contained in:
Santiago Pastorino 2019-05-22 05:51:50 +02:00
parent 50a0defd5a
commit 3fd4b22bce

View File

@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<OperandRef<'tcx, Bx::Value>> {
debug!("maybe_codegen_consume_direct(place={:?})", place);
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Operand(Some(o)) => {
return Some(o);
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// use path below
}
}
}
// Moves out of scalar and scalar pair fields are trivial.
if let &mir::Place::Projection(ref proj) = place {
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
return Some(o.extract_field(bx, f.index()));
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
return Some(OperandRef::new_zst(bx, elem));
place.iterate(|place_base, place_projection| {
if let mir::PlaceBase::Local(index) = place_base {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for proj in place_projection {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
}
_ => return None,
}
}
}
_ => {}
}
}
}
None
Some(o)
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}
}
} else {
None
}
})
}
pub fn codegen_consume(