diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2018-09-06 18:42:15 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2018-09-06 20:56:20 +0300 |
| commit | b9e7574bf2d760fc011cc90890f3280c474746e4 (patch) | |
| tree | 99869076f83bb9c3abdd9a7d00c99039aa23de74 /src/librustc_codegen_llvm | |
| parent | 27e5457f3fa6c6e322e05352f0109f2cd511396c (diff) | |
| download | rust-b9e7574bf2d760fc011cc90890f3280c474746e4.tar.gz rust-b9e7574bf2d760fc011cc90890f3280c474746e4.zip | |
rustc_codegen_llvm: don't assume offsets are always aligned.
Diffstat (limited to 'src/librustc_codegen_llvm')
| -rw-r--r-- | src/librustc_codegen_llvm/mir/place.rs | 9 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/type_of.rs | 22 |
2 files changed, 19 insertions, 12 deletions
diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 833dca8c75f..05cee034d3f 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -174,7 +174,10 @@ impl PlaceRef<'ll, 'tcx> { let cx = bx.cx; let field = self.layout.field(cx, ix); let offset = self.layout.fields.offset(ix); - let align = self.align.min(self.layout.align).min(field.align); + let effective_field_align = self.align + .min(self.layout.align) + .min(field.align) + .restrict_for_offset(offset); let simple = || { // Unions and newtypes only use an offset of 0. @@ -196,7 +199,7 @@ impl PlaceRef<'ll, 'tcx> { None }, layout: field, - align, + align: effective_field_align, } }; @@ -269,7 +272,7 @@ impl PlaceRef<'ll, 'tcx> { llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()), llextra: self.llextra, layout: field, - align, + align: effective_field_align, } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index e6907030ae6..6eec0b0b68c 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -122,25 +122,29 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let mut packed = false; let mut offset = Size::ZERO; - let mut prev_align = layout.align; + let mut prev_effective_align = layout.align; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { - let field = layout.field(cx, i); - packed |= layout.align.abi() < field.align.abi(); - let target_offset = layout.fields.offset(i as usize); - debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}", - i, field, offset, target_offset); + let field = layout.field(cx, i); + let effective_field_align = layout.align + .min(field.align) + .restrict_for_offset(target_offset); + packed |= effective_field_align.abi() < field.align.abi(); + + debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ + effective_field_align: {}", + i, field, offset, target_offset, effective_field_align.abi()); assert!(target_offset >= offset); let padding = target_offset - offset; - let padding_align = layout.align.min(prev_align).min(field.align); + let padding_align = prev_effective_align.min(effective_field_align); assert_eq!(offset.abi_align(padding_align) + padding, target_offset); result.push(Type::padding_filler(cx, padding, padding_align)); debug!(" padding before: {:?}", padding); result.push(field.llvm_type(cx)); offset = target_offset + field.size; - prev_align = field.align; + prev_effective_align = effective_field_align; } if !layout.is_unsized() && field_count > 0 { if offset > layout.size { @@ -148,7 +152,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout, layout.size, offset); } let padding = layout.size - offset; - let padding_align = layout.align.min(prev_align); + let padding_align = prev_effective_align; assert_eq!(offset.abi_align(padding_align) + padding, layout.size); debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", padding, offset, layout.size); |
