about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-25 12:42:55 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-19 02:14:28 +0200
commit8afa3a01e61906459a25d305176137e14ba3f835 (patch)
treed41af664e548e4364deb5cbf662fb15137ae1c3f
parent0a1fcc32a65c87646fe1613ea00c9447f04a646b (diff)
downloadrust-8afa3a01e61906459a25d305176137e14ba3f835.tar.gz
rust-8afa3a01e61906459a25d305176137e14ba3f835.zip
rustc_trans: always insert alignment padding, even before the first field.
-rw-r--r--src/librustc_trans/adt.rs19
-rw-r--r--src/librustc_trans/common.rs25
-rw-r--r--src/librustc_trans/context.rs12
-rw-r--r--src/librustc_trans/mir/constant.rs18
-rw-r--r--src/librustc_trans/type_of.rs15
-rw-r--r--src/test/codegen/adjustments.rs7
-rw-r--r--src/test/codegen/consts.rs4
-rw-r--r--src/test/codegen/function-arguments.rs3
-rw-r--r--src/test/codegen/refs.rs5
9 files changed, 66 insertions, 42 deletions
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index c2988cd3da3..c1242f57139 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -202,9 +202,9 @@ fn union_fill(cx: &CrateContext, size: Size, align: Align) -> Type {
     Type::array(&elem_ty, size / abi_align)
 }
 
-/// Double an index to account for padding.
+/// Double an index and add 1 to account for padding.
 pub fn memory_index_to_gep(index: u64) -> u64 {
-    index * 2
+    1 + index * 2
 }
 
 pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
@@ -213,9 +213,8 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                  discr: Option<Ty<'tcx>>) -> Vec<Type> {
     let field_count = (discr.is_some() as usize) + layout.field_count();
     debug!("struct_llfields: variant: {:?}", variant);
-    let mut first_field = true;
     let mut offset = Size::from_bytes(0);
-    let mut result: Vec<Type> = Vec::with_capacity(field_count * 2);
+    let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
     let field_iter = variant.field_index_by_increasing_offset().map(|i| {
         let ty = if i == 0 && discr.is_some() {
             cx.layout_of(discr.unwrap())
@@ -229,13 +228,9 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             index, field, offset, target_offset);
         assert!(target_offset >= offset);
         let padding = target_offset - offset;
-        if first_field {
-            assert_eq!(padding.bytes(), 0);
-            first_field = false;
-        } else {
-            result.push(Type::array(&Type::i8(cx), padding.bytes()));
-            debug!("    padding before: {:?}", padding);
-        }
+        result.push(Type::array(&Type::i8(cx), padding.bytes()));
+        debug!("    padding before: {:?}", padding);
+
         let llty = cx.llvm_type_of(field.ty);
         result.push(llty);
 
@@ -259,7 +254,7 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         debug!("struct_llfields: pad_bytes: {:?} offset: {:?} min_size: {:?} stride: {:?}",
             padding, offset, variant.min_size, variant.stride());
         result.push(Type::array(&Type::i8(cx), padding.bytes()));
-        assert!(result.len() == (field_count * 2));
+        assert!(result.len() == 1 + field_count * 2);
     } else {
         debug!("struct_llfields: offset: {:?} min_size: {:?} stride: {:?}",
                offset, variant.min_size, variant.stride());
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 749c5393e43..2e010ccee48 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -18,6 +18,7 @@ use llvm::{True, False, Bool, OperandBundleDef};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::middle::lang_items::LangItem;
+use abi;
 use base;
 use builder::Builder;
 use consts;
@@ -267,7 +268,29 @@ pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.llvm_type_of(cx.tcx().mk_str()).ptr_to());
-    C_named_struct(cx.str_slice_type(), &[cs, C_usize(cx, len as u64)])
+    let empty = C_array(Type::i8(cx), &[]);
+    assert_eq!(abi::FAT_PTR_ADDR, 0);
+    assert_eq!(abi::FAT_PTR_EXTRA, 1);
+    C_named_struct(cx.str_slice_type(), &[
+        empty,
+        cs,
+        empty,
+        C_usize(cx, len as u64),
+        empty
+    ])
+}
+
+pub fn C_fat_ptr(cx: &CrateContext, ptr: ValueRef, meta: ValueRef) -> ValueRef {
+    let empty = C_array(Type::i8(cx), &[]);
+    assert_eq!(abi::FAT_PTR_ADDR, 0);
+    assert_eq!(abi::FAT_PTR_EXTRA, 1);
+    C_struct(cx, &[
+        empty,
+        ptr,
+        empty,
+        meta,
+        empty
+    ], false)
 }
 
 pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 4e003edac3c..ac5f4372286 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -395,11 +395,13 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
                     let dummy_ccx = LocalCrateContext::dummy_ccx(shared,
                                                                  local_ccxs.as_mut_slice());
                     let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice");
-
-                    let llptrty = dummy_ccx.llvm_type_of(shared.tcx.mk_str()).ptr_to();
-                    str_slice_ty.set_struct_body(&[llptrty,
-                                                   Type::isize(&dummy_ccx)],
-                                                 false);
+                    str_slice_ty.set_struct_body(&[
+                        Type::array(&Type::i8(&dummy_ccx), 0),
+                        dummy_ccx.llvm_type_of(shared.tcx.mk_str()).ptr_to(),
+                        Type::array(&Type::i8(&dummy_ccx), 0),
+                        Type::isize(&dummy_ccx),
+                        Type::array(&Type::i8(&dummy_ccx), 0)
+                    ], false);
                     (Type::isize(&dummy_ccx), str_slice_ty)
                 };
                 (isize_ty, str_slice_ty, local_ccxs.pop().unwrap())
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index e253701903f..1b3559a50e3 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -29,7 +29,7 @@ use callee;
 use builder::Builder;
 use common::{self, CrateContext, const_get_elt, val_ty};
 use common::{C_array, C_bool, C_bytes, C_int, C_uint, C_big_integral, C_u32, C_u64};
-use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector};
+use common::{C_null, C_struct, C_str_slice, C_undef, C_usize, C_vector, C_fat_ptr};
 use common::const_to_opt_u128;
 use consts;
 use type_of::{self, LayoutLlvmExt};
@@ -675,9 +675,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                                                      .insert(base, operand.llval);
                             assert!(prev_const.is_none() || prev_const == Some(operand.llval));
                         }
-                        assert_eq!(abi::FAT_PTR_ADDR, 0);
-                        assert_eq!(abi::FAT_PTR_EXTRA, 1);
-                        C_struct(self.ccx, &[base, info], false)
+                        C_fat_ptr(self.ccx, base, info)
                     }
                     mir::CastKind::Misc if common::type_is_immediate(self.ccx, operand.ty) => {
                         debug_assert!(common::type_is_immediate(self.ccx, cast_ty));
@@ -734,7 +732,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                             if common::type_is_fat_ptr(self.ccx, cast_ty) {
                                 let llcast_ty = type_of::fat_ptr_base_ty(self.ccx, cast_ty);
                                 let data_cast = consts::ptrcast(data_ptr, llcast_ty);
-                                C_struct(self.ccx, &[data_cast, meta], false)
+                                C_fat_ptr(self.ccx, data_cast, meta)
                             } else { // cast to thin-ptr
                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
                                 // pointer-cast of that pointer to desired pointer type.
@@ -777,7 +775,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                 let ptr = if self.ccx.shared().type_is_sized(ty) {
                     base
                 } else {
-                    C_struct(self.ccx, &[base, tr_lvalue.llextra], false)
+                    C_fat_ptr(self.ccx, base, tr_lvalue.llextra)
                 };
                 Const::new(ptr, ref_ty)
             }
@@ -1176,14 +1174,8 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let parts = st.field_index_by_increasing_offset().map(|i| {
         (vals[i], st.offsets[i])
     });
-    let mut first_field = true;
     for (val, target_offset) in parts {
-        if first_field {
-            first_field = false;
-            assert_eq!(target_offset.bytes(), 0);
-        } else {
-            cfields.push(padding(ccx, target_offset - offset));
-        }
+        cfields.push(padding(ccx, target_offset - offset));
         cfields.push(val.llval);
         offset = target_offset + ccx.size_of(val.ty);
     }
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index d1305957634..f86bc17d20a 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -76,7 +76,13 @@ fn compute_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type
             } else {
                 let ptr_ty = cx.llvm_type_of(ty).ptr_to();
                 let info_ty = unsized_info_ty(cx, ty);
-                Type::struct_(cx, &[ptr_ty, info_ty], false)
+                Type::struct_(cx, &[
+                    Type::array(&Type::i8(cx), 0),
+                    ptr_ty,
+                    Type::array(&Type::i8(cx), 0),
+                    info_ty,
+                    Type::array(&Type::i8(cx), 0)
+                ], false)
             }
         } else {
             cx.llvm_type_of(ty).ptr_to()
@@ -240,11 +246,14 @@ impl<'tcx> LayoutLlvmExt for TyLayout<'tcx> {
             }
 
             Layout::Vector { .. } |
-            Layout::Array { .. } |
-            Layout::FatPointer { .. } => {
+            Layout::Array { .. } => {
                 index as u64
             }
 
+            Layout::FatPointer { .. } => {
+                adt::memory_index_to_gep(index as u64)
+            }
+
             Layout::Univariant { ref variant, .. } => {
                 adt::memory_index_to_gep(variant.memory_index[index] as u64)
             }
diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs
index 56f9b98b482..8a680f1c9d6 100644
--- a/src/test/codegen/adjustments.rs
+++ b/src/test/codegen/adjustments.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
 
 #![crate_type = "lib"]
 
@@ -24,9 +25,9 @@ pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
     // We used to generate an extra alloca and memcpy for the block's trailing expression value, so
     // check that we copy directly to the return value slot
 // CHECK: %x.ptr = bitcast i8* %0 to [0 x i8]*
-// CHECK: %1 = insertvalue { [0 x i8]*, [[USIZE]] } undef, [0 x i8]* %x.ptr, 0
-// CHECK: %2 = insertvalue { [0 x i8]*, [[USIZE]] } %1, [[USIZE]] %x.meta, 1
-// CHECK: ret { [0 x i8]*, [[USIZE]] } %2
+// CHECK: %1 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } undef, [0 x i8]* %x.ptr, 1
+// CHECK: %2 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %1, [[USIZE]] %x.meta, 3
+// CHECK: ret { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %2
     { x }
 }
 
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index a75b8f3992d..705488b7757 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -54,7 +54,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
 #[no_mangle]
 pub fn low_align_const() -> E<i16, [i16; 3]> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: load {{.*}} bitcast ({ i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
+// CHECK: load {{.*}} bitcast ({ [0 x i8], i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
     *&E::A(0)
 }
 
@@ -62,6 +62,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
 #[no_mangle]
 pub fn high_align_const() -> E<i16, i32> {
 // Check that low_align_const and high_align_const use the same constant
-// CHECK: load {{.*}} bitcast ({ i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
+// CHECK: load {{.*}} bitcast ({ [0 x i8], i16, [0 x i8], i16, [4 x i8] }** [[LOW_HIGH_REF]]
     *&E::A(0)
 }
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index 0bacb816241..5d073670d86 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
 
 #![crate_type = "lib"]
 #![feature(custom_attribute)]
@@ -132,7 +133,7 @@ pub fn trait_borrow(_: &Drop) {
 pub fn trait_box(_: Box<Drop>) {
 }
 
-// CHECK: { [0 x i16]*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta)
+// CHECK: { [0 x i8], [0 x i16]*, [0 x i8], [[USIZE]], [0 x i8] } @return_slice(i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta)
 #[no_mangle]
 pub fn return_slice(x: &[u16]) -> &[u16] {
   x
diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs
index d191bedee5d..ad799247f59 100644
--- a/src/test/codegen/refs.rs
+++ b/src/test/codegen/refs.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -C no-prepopulate-passes
+// ignore-tidy-linelength
 
 #![crate_type = "lib"]
 
@@ -23,9 +24,9 @@ pub fn helper(_: usize) {
 pub fn ref_dst(s: &[u8]) {
     // We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
     // directly to the alloca for "x"
-// CHECK: [[X0:%[0-9]+]] = getelementptr {{.*}} { [0 x i8]*, [[USIZE]] }* %x, i32 0, i32 0
+// CHECK: [[X0:%[0-9]+]] = getelementptr {{.*}} { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] }* %x, i32 0, i32 1
 // CHECK: store [0 x i8]* %s.ptr, [0 x i8]** [[X0]]
-// CHECK: [[X1:%[0-9]+]] = getelementptr {{.*}} { [0 x i8]*, [[USIZE]] }* %x, i32 0, i32 1
+// CHECK: [[X1:%[0-9]+]] = getelementptr {{.*}} { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] }* %x, i32 0, i32 3
 // CHECK: store [[USIZE]] %s.meta, [[USIZE]]* [[X1]]
 
     let x = &*s;