rustc_trans: use *[T; 0] for slice data pointers instead of *T.

This commit is contained in:
Eduard-Mihai Burtescu 2017-06-26 18:33:50 +03:00
parent 84b5a3d84d
commit 0a1fcc32a6
7 changed files with 29 additions and 33 deletions

View file

@ -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)])
}

View file

@ -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)

View file

@ -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) => {

View file

@ -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) => {

View file

@ -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 }
}

View file

@ -132,7 +132,7 @@ pub fn trait_borrow(_: &Drop) {
pub fn trait_box(_: Box<Drop>) {
}
// 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

View file

@ -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;