about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-06-09 18:14:47 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-06-20 23:18:21 +0300
commiteb9cb4dbca6eab5b7a50934fe7385e1a99d9dc62 (patch)
tree1e4b5eb623ce0bc2a0a4811f5992d5ce3a0c246b
parent93c32b55e2f03bc88d3d1601626bcd9059924005 (diff)
downloadrust-eb9cb4dbca6eab5b7a50934fe7385e1a99d9dc62.tar.gz
rust-eb9cb4dbca6eab5b7a50934fe7385e1a99d9dc62.zip
trans: derefs don't need the pointer in an alloca.
-rw-r--r--src/librustc_trans/mir/analyze.rs7
-rw-r--r--src/librustc_trans/mir/lvalue.rs31
2 files changed, 29 insertions, 9 deletions
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index d1c1053ac46..93ac002f2a9 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -151,6 +151,13 @@ impl<'mir, 'bcx, 'tcx> Visitor<'tcx> for TempAnalyzer<'mir, 'bcx, 'tcx> {
             }
         }
 
+        // A deref projection only reads the pointer, never needs the lvalue.
+        if let mir::Lvalue::Projection(ref proj) = *lvalue {
+            if let mir::ProjectionElem::Deref = proj.elem {
+                return self.visit_lvalue(&proj.base, LvalueContext::Consume);
+            }
+        }
+
         self.super_lvalue(lvalue, context);
     }
 }
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index 0a66a147568..f7e15979747 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -27,6 +27,7 @@ use Disr;
 use std::ptr;
 
 use super::{MirContext, TempRef};
+use super::operand::OperandValue;
 
 #[derive(Copy, Clone, Debug)]
 pub struct LvalueRef<'tcx> {
@@ -121,6 +122,26 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let return_ty = fn_return_ty.unwrap();
                 LvalueRef::new_sized(llval, LvalueTy::from_ty(return_ty))
             },
+            mir::Lvalue::Projection(box mir::Projection {
+                ref base,
+                elem: mir::ProjectionElem::Deref
+            }) => {
+                // Load the pointer from its location.
+                let ptr = self.trans_consume(bcx, base);
+                let projected_ty = LvalueTy::from_ty(ptr.ty)
+                    .projection_ty(tcx, &mir::ProjectionElem::Deref);
+                let projected_ty = bcx.monomorphize(&projected_ty);
+                let (llptr, llextra) = match ptr.val {
+                    OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
+                    OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+                    OperandValue::Ref(_) => bug!("Deref of by-Ref type {:?}", ptr.ty)
+                };
+                LvalueRef {
+                    llval: llptr,
+                    llextra: llextra,
+                    ty: projected_ty,
+                }
+            }
             mir::Lvalue::Projection(ref projection) => {
                 let tr_base = self.trans_lvalue(bcx, &projection.base);
                 let projected_ty = tr_base.ty.projection_ty(tcx, &projection.elem);
@@ -138,15 +159,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 };
 
                 let (llprojected, llextra) = match projection.elem {
-                    mir::ProjectionElem::Deref => {
-                        let base_ty = tr_base.ty.to_ty(tcx);
-                        if common::type_is_sized(tcx, projected_ty.to_ty(tcx)) {
-                            (base::load_ty_builder(bcx, tr_base.llval, base_ty),
-                             ptr::null_mut())
-                        } else {
-                            load_fat_ptr(bcx, tr_base.llval)
-                        }
-                    }
+                    mir::ProjectionElem::Deref => bug!(),
                     mir::ProjectionElem::Field(ref field, _) => {
                         let base_ty = tr_base.ty.to_ty(tcx);
                         let base_repr = adt::represent_type(ccx, base_ty);