LLVM codegen: Don't emit zero-sized padding for fields
LLVM codegen: Don't emit zero-sized padding for whiles because that has no use and makes it impossible to generate the return types that LLVM expects for certain ARM SIMD intrinsics.
This commit is contained in:
parent
d54fbb9855
commit
738868b2ff
2 changed files with 36 additions and 17 deletions
|
@ -262,7 +262,7 @@ impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
layout.is_llvm_scalar_pair()
|
layout.is_llvm_scalar_pair()
|
||||||
}
|
}
|
||||||
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 {
|
fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 {
|
||||||
layout.llvm_field_index(index)
|
layout.llvm_field_index(self, index)
|
||||||
}
|
}
|
||||||
fn scalar_pair_element_backend_type(
|
fn scalar_pair_element_backend_type(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -116,11 +116,12 @@ fn struct_llfields<'a, 'tcx>(
|
||||||
);
|
);
|
||||||
assert!(target_offset >= offset);
|
assert!(target_offset >= offset);
|
||||||
let padding = target_offset - offset;
|
let padding = target_offset - offset;
|
||||||
|
if padding != Size::ZERO {
|
||||||
let padding_align = prev_effective_align.min(effective_field_align);
|
let padding_align = prev_effective_align.min(effective_field_align);
|
||||||
assert_eq!(offset.align_to(padding_align) + padding, target_offset);
|
assert_eq!(offset.align_to(padding_align) + padding, target_offset);
|
||||||
result.push(cx.type_padding_filler(padding, padding_align));
|
result.push(cx.type_padding_filler(padding, padding_align));
|
||||||
debug!(" padding before: {:?}", padding);
|
debug!(" padding before: {:?}", padding);
|
||||||
|
}
|
||||||
result.push(field.llvm_type(cx));
|
result.push(field.llvm_type(cx));
|
||||||
offset = target_offset + field.size;
|
offset = target_offset + field.size;
|
||||||
prev_effective_align = effective_field_align;
|
prev_effective_align = effective_field_align;
|
||||||
|
@ -130,6 +131,7 @@ fn struct_llfields<'a, 'tcx>(
|
||||||
bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset);
|
bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset);
|
||||||
}
|
}
|
||||||
let padding = layout.size - offset;
|
let padding = layout.size - offset;
|
||||||
|
if padding != Size::ZERO {
|
||||||
let padding_align = prev_effective_align;
|
let padding_align = prev_effective_align;
|
||||||
assert_eq!(offset.align_to(padding_align) + padding, layout.size);
|
assert_eq!(offset.align_to(padding_align) + padding, layout.size);
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -137,7 +139,7 @@ fn struct_llfields<'a, 'tcx>(
|
||||||
padding, offset, layout.size
|
padding, offset, layout.size
|
||||||
);
|
);
|
||||||
result.push(cx.type_padding_filler(padding, padding_align));
|
result.push(cx.type_padding_filler(padding, padding_align));
|
||||||
assert_eq!(result.len(), 1 + field_count * 2);
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
|
debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +179,7 @@ pub trait LayoutLlvmExt<'tcx> {
|
||||||
index: usize,
|
index: usize,
|
||||||
immediate: bool,
|
immediate: bool,
|
||||||
) -> &'a Type;
|
) -> &'a Type;
|
||||||
fn llvm_field_index(&self, index: usize) -> u64;
|
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64;
|
||||||
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +342,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
self.scalar_llvm_type_at(cx, scalar, offset)
|
self.scalar_llvm_type_at(cx, scalar, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_field_index(&self, index: usize) -> u64 {
|
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 {
|
||||||
match self.abi {
|
match self.abi {
|
||||||
Abi::Scalar(_) | Abi::ScalarPair(..) => {
|
Abi::Scalar(_) | Abi::ScalarPair(..) => {
|
||||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
||||||
|
@ -354,7 +356,24 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
|
|
||||||
FieldsShape::Array { .. } => index as u64,
|
FieldsShape::Array { .. } => index as u64,
|
||||||
|
|
||||||
FieldsShape::Arbitrary { .. } => 1 + (self.fields.memory_index(index) as u64) * 2,
|
FieldsShape::Arbitrary { .. } => {
|
||||||
|
let mut llvm_index = 0;
|
||||||
|
let mut offset = Size::ZERO;
|
||||||
|
for i in self.fields.index_by_increasing_offset() {
|
||||||
|
let target_offset = self.fields.offset(i as usize);
|
||||||
|
let field = self.field(cx, i);
|
||||||
|
let padding = target_offset - offset;
|
||||||
|
if padding != Size::ZERO {
|
||||||
|
llvm_index += 1;
|
||||||
|
}
|
||||||
|
if i == index {
|
||||||
|
return llvm_index;
|
||||||
|
}
|
||||||
|
offset = target_offset + field.size;
|
||||||
|
llvm_index += 1;
|
||||||
|
}
|
||||||
|
bug!("TyAndLayout::llvm_field_index({:?}): index {} out of range", self, index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue