rustc_trans: use *[T; 0] for slice data pointers instead of *T.
This commit is contained in:
parent
84b5a3d84d
commit
0a1fcc32a6
7 changed files with 29 additions and 33 deletions
|
@ -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)])
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue