From 0a1fcc32a65c87646fe1613ea00c9447f04a646b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 26 Jun 2017 18:33:50 +0300 Subject: [PATCH] rustc_trans: use *[T; 0] for slice data pointers instead of *T. --- src/librustc_trans/common.rs | 3 ++- src/librustc_trans/context.rs | 4 +++- src/librustc_trans/mir/lvalue.rs | 26 ++++++++------------------ src/librustc_trans/type_of.rs | 14 ++++++++------ src/test/codegen/adjustments.rs | 7 ++++--- src/test/codegen/function-arguments.rs | 2 +- src/test/codegen/refs.rs | 6 +++--- 7 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 109c111efa95..749c5393e43e 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -265,7 +265,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va // you will be kicked off fast isel. See issue #4352 for an example of this. pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef { let len = s.len(); - let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx)); + 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)]) } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 5e12be5a22c9..4e003edac3c6 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -395,7 +395,9 @@ 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"); - str_slice_ty.set_struct_body(&[Type::i8p(&dummy_ccx), + + 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); (Type::isize(&dummy_ccx), str_slice_ty) diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index 77d99427da30..8bd4142f2c1a 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -456,18 +456,8 @@ impl<'a, 'tcx> LvalueRef<'tcx> { pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef) -> LvalueRef<'tcx> { - let ty = self.ty.to_ty(bcx.tcx()); - let (ptr, elem_ty) = match ty.sty { - ty::TySlice(ty) => { - // Slices already point to the array element type. - (bcx.inbounds_gep(self.llval, &[llindex]), ty) - } - ty::TyArray(ty, _) => { - let zero = common::C_usize(bcx.ccx, 0); - (bcx.inbounds_gep(self.llval, &[zero, llindex]), ty) - } - _ => bug!("unexpected type `{}` in LvalueRef::project_index", ty) - }; + let ptr = bcx.inbounds_gep(self.llval, &[common::C_usize(bcx.ccx, 0), llindex]); + let elem_ty = self.ty.to_ty(bcx.tcx()).builtin_index().unwrap(); LvalueRef::new_sized(ptr, elem_ty, self.alignment) } @@ -577,12 +567,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { subslice.ty = self.monomorphize(&subslice.ty); match subslice.ty.to_ty(tcx).sty { - ty::TyArray(..) => { - // must cast the lvalue pointer type to the new - // array type (*[%_; new_len]). - subslice.llval = bcx.pointercast(subslice.llval, - bcx.ccx.llvm_type_of(subslice.ty.to_ty(tcx)).ptr_to()) - } + ty::TyArray(..) => {} ty::TySlice(..) => { assert!(tr_base.has_extra()); subslice.llextra = bcx.sub(tr_base.llextra, @@ -591,6 +576,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { _ => bug!("unexpected type {:?} in Subslice", subslice.ty) } + // Cast the lvalue pointer type to the new + // array or slice type (*[%_; new_len]). + subslice.llval = bcx.pointercast(subslice.llval, + bcx.ccx.llvm_type_of(subslice.ty.to_ty(tcx)).ptr_to()); + subslice } mir::ProjectionElem::Downcast(_, v) => { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index e3f6485d4624..d13059576344 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -115,12 +115,14 @@ fn compute_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type Type::array(&llty, size) } - // Unsized slice types (and str) have the type of their element, and - // traits have the type of u8. This is so that the data pointer inside - // fat pointers is of the right type (e.g. for array accesses), even - // when taking the address of an unsized field in a struct. - ty::TySlice(ty) => cx.llvm_type_of(ty), - ty::TyStr | ty::TyDynamic(..) | ty::TyForeign(..) => Type::i8(cx), + ty::TySlice(ty) => { + Type::array(&cx.llvm_type_of(ty), 0) + } + ty::TyStr => { + Type::array(&Type::i8(cx), 0) + } + ty::TyDynamic(..) | + ty::TyForeign(..) => adt::type_of(cx, t), ty::TyFnDef(..) => Type::nil(cx), ty::TyFnPtr(sig) => { diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs index 342a4f0d085c..56f9b98b4829 100644 --- a/src/test/codegen/adjustments.rs +++ b/src/test/codegen/adjustments.rs @@ -23,9 +23,10 @@ pub fn helper(_: usize) { 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: %0 = insertvalue { i8*, [[USIZE]] } undef, i8* %x.ptr, 0 -// CHECK: %1 = insertvalue { i8*, [[USIZE]] } %0, [[USIZE]] %x.meta, 1 -// CHECK: ret { i8*, [[USIZE]] } %1 +// 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 { x } } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 29e2840c8817..0bacb8162412 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -132,7 +132,7 @@ pub fn trait_borrow(_: &Drop) { pub fn trait_box(_: Box) { } -// CHECK: { i16*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta) +// CHECK: { [0 x i16]*, [[USIZE]] } @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 4b713e28b052..d191bedee5d9 100644 --- a/src/test/codegen/refs.rs +++ b/src/test/codegen/refs.rs @@ -23,9 +23,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 {{.*}} { i8*, [[USIZE]] }* %x, i32 0, i32 0 -// CHECK: store i8* %s.ptr, i8** [[X0]] -// CHECK: [[X1:%[0-9]+]] = getelementptr {{.*}} { i8*, [[USIZE]] }* %x, i32 0, i32 1 +// CHECK: [[X0:%[0-9]+]] = getelementptr {{.*}} { [0 x i8]*, [[USIZE]] }* %x, i32 0, i32 0 +// 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: store [[USIZE]] %s.meta, [[USIZE]]* [[X1]] let x = &*s;