]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/mir/operand.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc_trans / mir / operand.rs
index cb77fcbbff85dbea7f015394b73f77cc494d202f..c31142323c85f56f8514978e701f82d548b85ee6 100644 (file)
@@ -9,22 +9,24 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use rustc::ty::Ty;
-use rustc::ty::layout::Layout;
+use rustc::ty::{self, Ty};
+use rustc::ty::layout::{Layout, LayoutTyper};
 use rustc::mir;
+use rustc::mir::tcx::LvalueTy;
 use rustc_data_structures::indexed_vec::Idx;
 
 use base;
-use common;
+use common::{self, CrateContext, C_null};
 use builder::Builder;
 use value::Value;
 use type_of;
 use type_::Type;
 
 use std::fmt;
+use std::ptr;
 
 use super::{MirContext, LocalRef};
-use super::lvalue::Alignment;
+use super::lvalue::{Alignment, LvalueRef};
 
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
@@ -77,6 +79,22 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl<'a, 'tcx> OperandRef<'tcx> {
+    pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
+                   ty: Ty<'tcx>) -> OperandRef<'tcx> {
+        assert!(common::type_is_zero_size(ccx, ty));
+        let llty = type_of::type_of(ccx, ty);
+        let val = if common::type_is_imm_pair(ccx, ty) {
+            let fields = llty.field_types();
+            OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
+        } else {
+            OperandValue::Immediate(C_null(llty))
+        };
+        OperandRef {
+            val: val,
+            ty: ty
+        }
+    }
+
     /// Asserts that this operand refers to a scalar and returns
     /// a reference to its value.
     pub fn immediate(self) -> ValueRef {
@@ -86,6 +104,22 @@ pub fn immediate(self) -> ValueRef {
         }
     }
 
+    pub fn deref(self) -> LvalueRef<'tcx> {
+        let projected_ty = self.ty.builtin_deref(true, ty::NoPreference)
+            .unwrap().ty;
+        let (llptr, llextra) = match self.val {
+            OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
+            OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+            OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
+        };
+        LvalueRef {
+            llval: llptr,
+            llextra: llextra,
+            ty: LvalueTy::from_ty(projected_ty),
+            alignment: Alignment::AbiAligned,
+        }
+    }
+
     /// If this operand is a Pair, we return an
     /// Immediate aggregate with the two values.
     pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
@@ -236,7 +270,7 @@ pub fn trans_operand(&mut self,
             }
 
             mir::Operand::Constant(ref constant) => {
-                let val = self.trans_constant(bcx, constant);
+                let val = self.trans_constant(&bcx, constant);
                 let operand = val.to_operand(bcx.ccx);
                 if let OperandValue::Ref(ptr, align) = operand.val {
                     // If this is a OperandValue::Ref to an immediate constant, load it.
@@ -268,10 +302,17 @@ pub fn store_operand(&mut self,
                 bcx.store(base::from_immediate(bcx, s), lldest, align);
             }
             OperandValue::Pair(a, b) => {
+                let f_align = match *bcx.ccx.layout_of(operand.ty) {
+                    Layout::Univariant { ref variant, .. } if variant.packed => {
+                        Some(1)
+                    }
+                    _ => align
+                };
+
                 let a = base::from_immediate(bcx, a);
                 let b = base::from_immediate(bcx, b);
-                bcx.store(a, bcx.struct_gep(lldest, 0), align);
-                bcx.store(b, bcx.struct_gep(lldest, 1), align);
+                bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
+                bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
             }
         }
     }