about summary refs log tree commit diff
path: root/src/librustc_codegen_ssa
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-06-06 22:39:12 +0200
committerGitHub <noreply@github.com>2019-06-06 22:39:12 +0200
commit3fd632aa7ec9b4ad356a1ec5b3fe0794e6e3d8c3 (patch)
treef1ad6b575920076bb634fc06b00da6534a1bd9fa /src/librustc_codegen_ssa
parent4c74056867e2df800b0932e5b78d8464d8dc449f (diff)
parent0cfaa28bc5edda198571fca9410cbc9f71b8d17a (diff)
downloadrust-3fd632aa7ec9b4ad356a1ec5b3fe0794e6e3d8c3.tar.gz
rust-3fd632aa7ec9b4ad356a1ec5b3fe0794e6e3d8c3.zip
Rollup merge of #61559 - spastorino:make-visitors-iterate, r=oli-obk
Make visitors iterate

r? @oli-obk

The second commit is not completely equivalent, unsure if the code is wrong or not. Tests pass though, otherwise we would need to iterate in the opposite direction as it happened in other parts of the code.
Diffstat (limited to 'src/librustc_codegen_ssa')
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs85
1 files changed, 48 insertions, 37 deletions
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index bb6a13ed15a..549608bf7ee 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                    context: PlaceContext,
                    location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
+        let mut context = context;
         let cx = self.fx.cx;
 
-        if let mir::Place::Projection(ref proj) = *place {
-            // Allow uses of projections that are ZSTs or from scalar fields.
-            let is_consume = match context {
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
-                _ => false
-            };
-            if is_consume {
-                let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
-                let base_ty = self.fx.monomorphize(&base_ty);
-
-                // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty
-                    .projection_ty(cx.tcx(), &proj.elem)
-                    .ty;
-                let elem_ty = self.fx.monomorphize(&elem_ty);
-                if cx.layout_of(elem_ty).is_zst() {
-                    return;
-                }
-
-                if let mir::ProjectionElem::Field(..) = proj.elem {
-                    let layout = cx.layout_of(base_ty.ty);
-                    if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
-                        // Recurse with the same context, instead of `Projection`,
-                        // potentially stopping at non-operand projections,
-                        // which would trigger `not_ssa` on locals.
-                        self.visit_place(&proj.base, context, location);
+        place.iterate(|place_base, place_projections| {
+            for proj in place_projections {
+                // Allow uses of projections that are ZSTs or from scalar fields.
+                let is_consume = match context {
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
+                    _ => false
+                };
+                if is_consume {
+                    let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
+                    let base_ty = self.fx.monomorphize(&base_ty);
+
+                    // ZSTs don't require any actual memory access.
+                    let elem_ty = base_ty
+                        .projection_ty(cx.tcx(), &proj.elem)
+                        .ty;
+                    let elem_ty = self.fx.monomorphize(&elem_ty);
+                    if cx.layout_of(elem_ty).is_zst() {
                         return;
                     }
+
+                    if let mir::ProjectionElem::Field(..) = proj.elem {
+                        let layout = cx.layout_of(base_ty.ty);
+                        if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
+                            // Recurse with the same context, instead of `Projection`,
+                            // potentially stopping at non-operand projections,
+                            // which would trigger `not_ssa` on locals.
+                            continue;
+                        }
+                    }
                 }
-            }
 
-            // A deref projection only reads the pointer, never needs the place.
-            if let mir::ProjectionElem::Deref = proj.elem {
-                return self.visit_place(
-                    &proj.base,
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                    location
-                );
+                // A deref projection only reads the pointer, never needs the place.
+                if let mir::ProjectionElem::Deref = proj.elem {
+                    return self.visit_place(
+                        &proj.base,
+                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+                        location
+                    );
+                }
+
+                context = if context.is_mutating_use() {
+                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
+                } else {
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+                };
             }
-        }
 
-        self.super_place(place, context, location);
+            // Default base visit behavior
+            if let mir::PlaceBase::Local(local) = place_base {
+                self.visit_local(local, context, location);
+            }
+        });
     }
 
     fn visit_local(&mut self,