diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-06-25 12:42:55 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-11-19 02:14:28 +0200 |
| commit | 8afa3a01e61906459a25d305176137e14ba3f835 (patch) | |
| tree | d41af664e548e4364deb5cbf662fb15137ae1c3f | |
| parent | 0a1fcc32a65c87646fe1613ea00c9447f04a646b (diff) | |
| download | rust-8afa3a01e61906459a25d305176137e14ba3f835.tar.gz rust-8afa3a01e61906459a25d305176137e14ba3f835.zip | |
rustc_trans: always insert alignment padding, even before the first field.
| -rw-r--r-- | src/librustc_trans/adt.rs | 19 | ||||
| -rw-r--r-- | src/librustc_trans/common.rs | 25 | ||||
| -rw-r--r-- | src/librustc_trans/context.rs | 12 | ||||
| -rw-r--r-- | src/librustc_trans/mir/constant.rs | 18 | ||||
| -rw-r--r-- | src/librustc_trans/type_of.rs | 15 | ||||
| -rw-r--r-- | src/test/codegen/adjustments.rs | 7 | ||||
| -rw-r--r-- | src/test/codegen/consts.rs | 4 | ||||
| -rw-r--r-- | src/test/codegen/function-arguments.rs | 3 | ||||
| -rw-r--r-- | src/test/codegen/refs.rs | 5 |
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; |
