about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2019-05-22 05:51:50 +0200
committerSantiago Pastorino <spastorino@gmail.com>2019-05-22 14:22:37 +0200
commit3fd4b22bce195e5c12e478296c8e0c03de6c8331 (patch)
tree1645a435d3c9b4152161b101ff60118f75111f56 /src
parent50a0defd5a93523067ef239936cc2e0755220904 (diff)
downloadrust-3fd4b22bce195e5c12e478296c8e0c03de6c8331.tar.gz
rust-3fd4b22bce195e5c12e478296c8e0c03de6c8331.zip
Make maybe_codegen_consume_direct iterate instead of doing recursion
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs70
1 files changed, 36 insertions, 34 deletions
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 3b8e5b44953..3db05b7214d 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -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
-                }
-            }
-        }
+        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,
+                            }
+                        }
 
-        // 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()));
+                        Some(o)
                     }
-                    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));
-                        }
+                    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
             }
-        }
-
-        None
+        })
     }
 
     pub fn codegen_consume(