about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-11-29 00:37:38 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-11-29 00:37:38 +0200
commit51cf4e9e91ffcb1ab08bbcfa84841efb38c315e4 (patch)
tree04a41a7782430e6c2ab0befbd65eca671ce7275c /src
parentb68fc18c45350e1cdcd83cecf0f12e294e55af56 (diff)
downloadrust-51cf4e9e91ffcb1ab08bbcfa84841efb38c315e4.tar.gz
rust-51cf4e9e91ffcb1ab08bbcfa84841efb38c315e4.zip
rustc_codegen_llvm: don't overalign loads of pair operands.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_llvm/builder.rs12
-rw-r--r--src/test/codegen/issue-56267-2.rs18
2 files changed, 27 insertions, 3 deletions
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index d2a99eae340..f6bc348b8dc 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -589,9 +589,11 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             });
             OperandValue::Immediate(to_immediate(self, llval, place.layout))
         } else if let layout::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
-            let mut load = |i, scalar: &layout::Scalar| {
+            let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
+
+            let mut load = |i, scalar: &layout::Scalar, align| {
                 let llptr = self.struct_gep(place.llval, i as u64);
-                let load = self.load(llptr, place.align);
+                let load = self.load(llptr, align);
                 scalar_load_metadata(self, load, scalar);
                 if scalar.is_bool() {
                     self.trunc(load, self.cx().type_i1())
@@ -599,7 +601,11 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                     load
                 }
             };
-            OperandValue::Pair(load(0, a), load(1, b))
+
+            OperandValue::Pair(
+                load(0, a, place.align),
+                load(1, b, place.align.restrict_for_offset(b_offset)),
+            )
         } else {
             OperandValue::Ref(place.llval, None, place.align)
         };
diff --git a/src/test/codegen/issue-56267-2.rs b/src/test/codegen/issue-56267-2.rs
new file mode 100644
index 00000000000..53b83f4a530
--- /dev/null
+++ b/src/test/codegen/issue-56267-2.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+    foo: u64,
+    bar: T,
+}
+
+// The load from bar.1 should have alignment 4. Not checking
+// other loads here, as the alignment will be platform-dependent.
+
+// CHECK: %{{.+}} = load i32, i32* %{{.+}}, align 4
+#[no_mangle]
+pub fn test(x: Foo<(i32, i32)>) -> (i32, i32) {
+    x.bar
+}