提交 95c0ad0c 编写于 作者: E Eduard-Mihai Burtescu

rustc: unpack newtyped of #[repr(simd)] vector types.

上级 707d0708
......@@ -758,7 +758,10 @@ pub enum Abi {
Uninhabited,
Scalar(Scalar),
ScalarPair(Scalar, Scalar),
Vector,
Vector {
element: Scalar,
count: u64
},
Aggregate {
/// If true, the size is exact, otherwise it's only a lower bound.
sized: bool,
......@@ -773,7 +776,7 @@ pub fn is_unsized(&self) -> bool {
Abi::Uninhabited |
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector => false,
Abi::Vector { .. } => false,
Abi::Aggregate { sized, .. } => !sized
}
}
......@@ -784,7 +787,7 @@ pub fn is_packed(&self) -> bool {
Abi::Uninhabited |
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector => false,
Abi::Vector { .. } => false,
Abi::Aggregate { packed, .. } => packed
}
}
......@@ -1083,9 +1086,9 @@ enum StructKind {
align.abi() == field.align.abi() &&
size == field.size {
match field.abi {
// For plain scalars we can't unpack newtypes
// for `#[repr(C)]`, as that affects C ABIs.
Abi::Scalar(_) if optimize => {
// For plain scalars, or vectors of them, we can't unpack
// newtypes for `#[repr(C)]`, as that affects C ABIs.
Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
abi = field.abi.clone();
}
// But scalar pairs are Rust-specific and get
......@@ -1320,16 +1323,17 @@ enum StructKind {
// SIMD vector types.
ty::TyAdt(def, ..) if def.repr.simd() => {
let count = ty.simd_size(tcx) as u64;
let element = cx.layout_of(ty.simd_type(tcx))?;
match element.abi {
Abi::Scalar(_) => {}
let count = ty.simd_size(tcx) as u64;
assert!(count > 0);
let scalar = match element.abi {
Abi::Scalar(ref scalar) => scalar.clone(),
_ => {
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
a non-machine element type `{}`",
ty, element.ty));
}
}
};
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;
let align = dl.vector_align(size);
......@@ -1341,7 +1345,10 @@ enum StructKind {
stride: element.size,
count
},
abi: Abi::Vector,
abi: Abi::Vector {
element: scalar,
count
},
size,
align,
})
......@@ -2266,8 +2273,9 @@ pub fn is_packed(&self) -> bool {
pub fn is_zst(&self) -> bool {
match self.abi {
Abi::Uninhabited => true,
Abi::Scalar(_) | Abi::ScalarPair(..) => false,
Abi::Vector => self.size.bytes() == 0,
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector { .. } => false,
Abi::Aggregate { sized, .. } => sized && self.size.bytes() == 0
}
}
......@@ -2322,6 +2330,9 @@ fn find_niche<C>(&self, cx: C, count: u128)
scalar_component(b, a.value.size(cx).abi_align(b.value.align(cx)))
}));
}
Abi::Vector { ref element, .. } => {
return Ok(scalar_component(element, Size::from_bytes(0)));
}
_ => {}
}
......@@ -2424,7 +2435,10 @@ fn hash_stable<W: StableHasherResult>(&self,
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher);
}
Vector => {}
Vector { ref element, count } => {
element.hash_stable(hcx, hasher);
count.hash_stable(hcx, hasher);
}
Aggregate { packed, sized } => {
packed.hash_stable(hcx, hasher);
sized.hash_stable(hcx, hasher);
......
......@@ -315,7 +315,7 @@ fn is_aggregate(&self) -> bool {
match self.abi {
layout::Abi::Uninhabited |
layout::Abi::Scalar(_) |
layout::Abi::Vector => false,
layout::Abi::Vector { .. } => false,
layout::Abi::ScalarPair(..) |
layout::Abi::Aggregate { .. } => true
}
......@@ -339,7 +339,7 @@ fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg>
})
}
layout::Abi::Vector => {
layout::Abi::Vector { .. } => {
Some(Reg {
kind: RegKind::Vector,
size: self.size
......
......@@ -77,13 +77,14 @@ fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
unify(cls, off, reg);
}
layout::Abi::Vector => {
layout::Abi::Vector { ref element, count } => {
unify(cls, off, Class::Sse);
// everything after the first one is the upper
// half of a register.
for i in 1..layout.fields.count() {
let field_off = off + layout.fields.offset(i);
let stride = element.value.size(ccx);
for i in 1..count {
let field_off = off + stride * i;
unify(cls, field_off, Class::SseUp);
}
}
......
......@@ -28,7 +28,7 @@ pub fn compute_abi_info(fty: &mut FnType) {
_ => a.make_indirect()
}
}
layout::Abi::Vector => {
layout::Abi::Vector { .. } => {
// FIXME(eddyb) there should be a size cap here
// (probably what clang calls "illegal vectors").
}
......
......@@ -122,17 +122,17 @@ fn get_field(&self, ccx: &CrateContext<'a, 'tcx>, i: usize) -> ValueRef {
if field.is_zst() {
return C_undef(field.immediate_llvm_type(ccx));
}
let offset = layout.fields.offset(i);
match layout.abi {
layout::Abi::Scalar(_) => self.llval,
layout::Abi::Scalar(_) |
layout::Abi::ScalarPair(..) |
layout::Abi::Vector { .. }
if offset.bytes() == 0 && field.size == layout.size => self.llval,
layout::Abi::ScalarPair(ref a, ref b) => {
let offset = layout.fields.offset(i);
if offset.bytes() == 0 {
if field.size == layout.size {
self.llval
} else {
assert_eq!(field.size, a.value.size(ccx));
const_get_elt(self.llval, 0)
}
assert_eq!(field.size, a.value.size(ccx));
const_get_elt(self.llval, 0)
} else {
assert_eq!(offset, a.value.size(ccx)
.abi_align(b.value.align(ccx)));
......@@ -1131,9 +1131,7 @@ fn trans_const_adt<'a, 'tcx>(
match l.variants {
layout::Variants::Single { index } => {
assert_eq!(variant_index, index);
if let layout::Abi::Vector = l.abi {
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
} else if let layout::FieldPlacement::Union(_) = l.fields {
if let layout::FieldPlacement::Union(_) = l.fields {
assert_eq!(variant_index, 0);
assert_eq!(vals.len(), 1);
let contents = [
......@@ -1143,6 +1141,12 @@ fn trans_const_adt<'a, 'tcx>(
Const::new(C_struct(ccx, &contents, l.is_packed()), t)
} else {
if let layout::Abi::Vector { .. } = l.abi {
if let layout::FieldPlacement::Array { .. } = l.fields {
return Const::new(C_vector(&vals.iter().map(|x| x.llval)
.collect::<Vec<_>>()), t);
}
}
build_const_struct(ccx, l, vals, None)
}
}
......@@ -1206,7 +1210,8 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
match layout.abi {
layout::Abi::Scalar(_) |
layout::Abi::ScalarPair(..) if discr.is_none() => {
layout::Abi::ScalarPair(..) |
layout::Abi::Vector { .. } if discr.is_none() => {
let mut non_zst_fields = vals.iter().enumerate().map(|(i, f)| {
(f, layout.fields.offset(i))
}).filter(|&(f, _)| !ccx.layout_of(f.ty).is_zst());
......
......@@ -163,7 +163,7 @@ pub fn extract_field(&self, bcx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tc
};
}
// Newtype of a scalar or scalar pair.
// Newtype of a scalar, scalar pair or vector.
(OperandValue::Immediate(_), _) |
(OperandValue::Pair(..), _) if field.size == self.layout.size => {
assert_eq!(offset.bytes(), 0);
......@@ -184,7 +184,7 @@ pub fn extract_field(&self, bcx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tc
}
// `#[repr(simd)]` types are also immediate.
(OperandValue::Immediate(llval), &layout::Abi::Vector) => {
(OperandValue::Immediate(llval), &layout::Abi::Vector { .. }) => {
OperandValue::Immediate(
bcx.extract_element(llval, C_usize(bcx.ccx, i as u64)))
}
......
......@@ -25,7 +25,7 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-> Type {
match layout.abi {
layout::Abi::Scalar(_) => bug!("handled elsewhere"),
layout::Abi::Vector => {
layout::Abi::Vector { ref element, count } => {
// LLVM has a separate type for 64-bit SIMD vectors on X86 called
// `x86_mmx` which is needed for some SIMD operations. As a bit of a
// hack (all SIMD definitions are super unstable anyway) we
......@@ -33,15 +33,14 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// x86_mmx" type. In general there shouldn't be a need for other
// one-element SIMD vectors, so it's assumed this won't clash with
// much else.
let use_x86_mmx = layout.fields.count() == 1 &&
layout.size.bits() == 64 &&
let use_x86_mmx = count == 1 && layout.size.bits() == 64 &&
(ccx.sess().target.target.arch == "x86" ||
ccx.sess().target.target.arch == "x86_64");
if use_x86_mmx {
return Type::x86_mmx(ccx)
} else {
return Type::vector(&layout.field(ccx, 0).llvm_type(ccx),
layout.fields.count() as u64);
let element = layout.scalar_llvm_type_at(ccx, element, Size::from_bytes(0));
return Type::vector(&element, count);
}
}
layout::Abi::ScalarPair(..) => {
......@@ -198,6 +197,8 @@ pub trait LayoutLlvmExt<'tcx> {
fn is_llvm_scalar_pair<'a>(&self) -> bool;
fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;
fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
scalar: &layout::Scalar, offset: Size) -> Type;
fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
index: usize) -> Type;
fn llvm_field_index(&self, index: usize) -> u64;
......@@ -210,7 +211,7 @@ fn is_llvm_immediate(&self) -> bool {
match self.abi {
layout::Abi::Uninhabited |
layout::Abi::Scalar(_) |
layout::Abi::Vector => true,
layout::Abi::Vector { .. } => true,
layout::Abi::ScalarPair(..) => false,
layout::Abi::Aggregate { .. } => self.is_zst()
}
......@@ -221,7 +222,7 @@ fn is_llvm_scalar_pair<'a>(&self) -> bool {
layout::Abi::ScalarPair(..) => true,
layout::Abi::Uninhabited |
layout::Abi::Scalar(_) |
layout::Abi::Vector |
layout::Abi::Vector { .. } |
layout::Abi::Aggregate { .. } => false
}
}
......@@ -244,34 +245,19 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
if let Some(&llty) = ccx.scalar_lltypes().borrow().get(&self.ty) {
return llty;
}
let llty = match scalar.value {
layout::Int(i, _) => Type::from_integer(ccx, i),
layout::F32 => Type::f32(ccx),
layout::F64 => Type::f64(ccx),
layout::Pointer => {
let pointee = match self.ty.sty {
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
ccx.layout_of(ty).llvm_type(ccx)
}
ty::TyAdt(def, _) if def.is_box() => {
ccx.layout_of(self.ty.boxed_ty()).llvm_type(ccx)
}
ty::TyFnPtr(sig) => {
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
FnType::new(ccx, sig, &[]).llvm_type(ccx)
}
_ => {
// If we know the alignment, pick something better than i8.
if let Some(pointee) = self.pointee_info_at(ccx, Size::from_bytes(0)) {
Type::pointee_for_abi_align(ccx, pointee.align)
} else {
Type::i8(ccx)
}
}
};
pointee.ptr_to()
let llty = match self.ty.sty {
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
ccx.layout_of(ty).llvm_type(ccx).ptr_to()
}
ty::TyAdt(def, _) if def.is_box() => {
ccx.layout_of(self.ty.boxed_ty()).llvm_type(ccx).ptr_to()
}
ty::TyFnPtr(sig) => {
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
FnType::new(ccx, sig, &[]).llvm_type(ccx).ptr_to()
}
_ => self.scalar_llvm_type_at(ccx, scalar, Size::from_bytes(0))
};
ccx.scalar_lltypes().borrow_mut().insert(self.ty, llty);
return llty;
......@@ -325,6 +311,24 @@ fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
self.llvm_type(ccx)
}
fn scalar_llvm_type_at<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
scalar: &layout::Scalar, offset: Size) -> Type {
match scalar.value {
layout::Int(i, _) => Type::from_integer(ccx, i),
layout::F32 => Type::f32(ccx),
layout::F64 => Type::f64(ccx),
layout::Pointer => {
// If we know the alignment, pick something better than i8.
let pointee = if let Some(pointee) = self.pointee_info_at(ccx, offset) {
Type::pointee_for_abi_align(ccx, pointee.align)
} else {
Type::i8(ccx)
};
pointee.ptr_to()
}
}
}
fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
index: usize) -> Type {
// HACK(eddyb) special-case fat pointers until LLVM removes
......@@ -358,25 +362,12 @@ fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
return Type::i1(ccx);
}
match scalar.value {
layout::Int(i, _) => Type::from_integer(ccx, i),
layout::F32 => Type::f32(ccx),
layout::F64 => Type::f64(ccx),
layout::Pointer => {
// If we know the alignment, pick something better than i8.
let offset = if index == 0 {
Size::from_bytes(0)
} else {
a.value.size(ccx).abi_align(b.value.align(ccx))
};
let pointee = if let Some(pointee) = self.pointee_info_at(ccx, offset) {
Type::pointee_for_abi_align(ccx, pointee.align)
} else {
Type::i8(ccx)
};
pointee.ptr_to()
}
}
let offset = if index == 0 {
Size::from_bytes(0)
} else {
a.value.size(ccx).abi_align(b.value.align(ccx))
};
self.scalar_llvm_type_at(ccx, scalar, offset)
}
fn llvm_field_index(&self, index: usize) -> u64 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册