]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/type_of.rs
Auto merge of #53002 - QuietMisdreavus:brother-may-i-have-some-loops, r=pnkfelix
[rust.git] / src / librustc_codegen_llvm / type_of.rs
index bfabf65dfd850976feda8a1798137181bb3be246..5fd4f15acd1574c719cda4a117994e0c2bd0f3b6 100644 (file)
@@ -23,8 +23,8 @@
 
 fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                 layout: TyLayout<'tcx>,
-                                defer: &mut Option<(Type, TyLayout<'tcx>)>)
-                                -> Type {
+                                defer: &mut Option<(&'a Type, TyLayout<'tcx>)>)
+                                -> &'a Type {
     match layout.abi {
         layout::Abi::Scalar(_) => bug!("handled elsewhere"),
         layout::Abi::Vector { ref element, count } => {
@@ -42,13 +42,13 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 return Type::x86_mmx(cx)
             } else {
                 let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
-                return Type::vector(&element, count);
+                return Type::vector(element, count);
             }
         }
         layout::Abi::ScalarPair(..) => {
             return Type::struct_(cx, &[
-                layout.scalar_pair_element_llvm_type(cx, 0),
-                layout.scalar_pair_element_llvm_type(cx, 1),
+                layout.scalar_pair_element_llvm_type(cx, 0, false),
+                layout.scalar_pair_element_llvm_type(cx, 1, false),
             ], false);
         }
         layout::Abi::Uninhabited |
@@ -96,7 +96,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             }
         }
         layout::FieldPlacement::Array { count, .. } => {
-            Type::array(&layout.field(cx, 0).llvm_type(cx), count)
+            Type::array(layout.field(cx, 0).llvm_type(cx), count)
         }
         layout::FieldPlacement::Arbitrary { .. } => {
             match name {
@@ -116,14 +116,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
 fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                              layout: TyLayout<'tcx>)
-                             -> (Vec<Type>, bool) {
+                             -> (Vec<&'a Type>, bool) {
     debug!("struct_llfields: {:#?}", layout);
     let field_count = layout.fields.count();
 
     let mut packed = false;
     let mut offset = Size::ZERO;
     let mut prev_align = layout.align;
-    let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
+    let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
     for i in layout.fields.index_by_increasing_offset() {
         let field = layout.field(cx, i);
         packed |= layout.align.abi() < field.align.abi();
@@ -201,12 +201,12 @@ pub struct PointeeInfo {
 pub trait LayoutLlvmExt<'tcx> {
     fn is_llvm_immediate(&self) -> bool;
     fn is_llvm_scalar_pair<'a>(&self) -> bool;
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type;
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type;
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize) -> Type;
+                                         index: usize, immediate: bool) -> &'a Type;
     fn llvm_field_index(&self, index: usize) -> u64;
     fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
                            -> Option<PointeeInfo>;
@@ -244,7 +244,7 @@ fn is_llvm_scalar_pair<'a>(&self) -> bool {
     /// with the inner-most trailing unsized field using the "minimal unit"
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
-    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
@@ -304,7 +304,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
 
         cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
 
-        if let Some((mut llty, layout)) = defer {
+        if let Some((llty, layout)) = defer {
             let (llfields, packed) = struct_llfields(cx, layout);
             llty.set_struct_body(&llfields, packed)
         }
@@ -312,7 +312,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         llty
     }
 
-    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
         if let layout::Abi::Scalar(ref scalar) = self.abi {
             if scalar.is_bool() {
                 return Type::i1(cx);
@@ -322,7 +322,7 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
     }
 
     fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                               scalar: &layout::Scalar, offset: Size) -> Type {
+                               scalar: &layout::Scalar, offset: Size) -> &'a Type {
         match scalar.value {
             layout::Int(i, _) => Type::from_integer(cx, i),
             layout::Float(FloatTy::F32) => Type::f32(cx),
@@ -340,7 +340,7 @@ fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
     }
 
     fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
-                                         index: usize) -> Type {
+                                         index: usize, immediate: bool) -> &'a Type {
         // HACK(eddyb) special-case fat pointers until LLVM removes
         // pointee types, to avoid bitcasting every `OperandRef::deref`.
         match self.ty.sty {
@@ -350,7 +350,7 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
             }
             ty::TyAdt(def, _) if def.is_box() => {
                 let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
-                return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index);
+                return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
             }
             _ => {}
         }
@@ -361,14 +361,13 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
         };
         let scalar = [a, b][index];
 
-        // Make sure to return the same type `immediate_llvm_type` would,
-        // to avoid dealing with two types and the associated conversions.
-        // This means that `(bool, bool)` is represented as `{i1, i1}`,
-        // both in memory and as an immediate, while `bool` is typically
-        // `i8` in memory and only `i1` when immediate. While we need to
-        // load/store `bool` as `i8` to avoid crippling LLVM optimizations,
-        // `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`.
-        if scalar.is_bool() {
+        // Make sure to return the same type `immediate_llvm_type` would when
+        // dealing with an immediate pair.  This means that `(bool, bool)` is
+        // effectively represented as `{i8, i8}` in memory and two `i1`s as an
+        // immediate, just like `bool` is typically `i8` in memory and only `i1`
+        // when immediate.  We need to load/store `bool` as `i8` to avoid
+        // crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
+        if immediate && scalar.is_bool() {
             return Type::i1(cx);
         }