From d8190afbcb9b15eb8e04d3860a5bd018568a3980 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 28 Nov 2018 00:25:40 +0100 Subject: [PATCH] Fix alignment of stores to scalar pair The alignment for the second element of a scalar pair is not the same as for the first element. Make sure it is computed correctly based on the element size. --- src/librustc_codegen_ssa/mir/operand.rs | 20 +++++++++++++++----- src/test/codegen/issue-56267.rs | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/codegen/issue-56267.rs diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 92d0219caf06b..fefbc14e4973c 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -331,11 +331,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue { bx.store_with_flags(val, dest.llval, dest.align, flags); } OperandValue::Pair(a, b) => { - for (i, &x) in [a, b].iter().enumerate() { - let llptr = bx.struct_gep(dest.llval, i as u64); - let val = base::from_immediate(bx, x); - bx.store_with_flags(val, llptr, dest.align, flags); - } + let (a_scalar, b_scalar) = match dest.layout.abi { + layout::Abi::ScalarPair(ref a, ref b) => (a, b), + _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout) + }; + let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); + + let llptr = bx.struct_gep(dest.llval, 0); + let val = base::from_immediate(bx, a); + let align = dest.align; + bx.store_with_flags(val, llptr, align, flags); + + let llptr = bx.struct_gep(dest.llval, 1); + let val = base::from_immediate(bx, b); + let align = dest.align.restrict_for_offset(b_offset); + bx.store_with_flags(val, llptr, align, flags); } } } diff --git a/src/test/codegen/issue-56267.rs b/src/test/codegen/issue-56267.rs new file mode 100644 index 0000000000000..2c33f558931ed --- /dev/null +++ b/src/test/codegen/issue-56267.rs @@ -0,0 +1,18 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type="rlib"] + +#[allow(dead_code)] +pub struct Foo { + foo: u64, + bar: T, +} + +// The store writing to bar.1 should have alignment 4. Not checking +// other stores here, as the alignment will be platform-dependent. + +// CHECK: store i32 [[TMP1:%.+]], i32* [[TMP2:%.+]], align 4 +#[no_mangle] +pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> { + Foo { foo: 0, bar: x } +}