about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2018-09-16 16:34:15 +0000
committerSamuel Holland <samuel@sholland.org>2018-11-15 13:43:01 +0000
commit346e97600bafd916c41c24d01ef8671511d691c2 (patch)
tree4dc6e154a0ab39adf41c7edbfa31e273b3355be6
parent81303d7d90b483b8e2611cef09adc56c02ccfc50 (diff)
downloadrust-346e97600bafd916c41c24d01ef8671511d691c2.tar.gz
rust-346e97600bafd916c41c24d01ef8671511d691c2.zip
Fix powerpc64 ELFv2 big-endian struct-passing ABI
The requirements here are not "ELFv1" requirements, but big-endian
requirements, as the extension or non-extension of the argument is
necessary to put the argument in the correct half of the register.
Parameter passing in the ELFv2 ABI needs these same transformations.
Since this code makes no difference on little-endian machines, simplify
it to use the same code path everywhere.
-rw-r--r--src/librustc_target/abi/call/powerpc64.rs29
-rw-r--r--src/librustc_target/abi/mod.rs2
2 files changed, 13 insertions, 18 deletions
diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs
index 80a4d693dc3..56d09c07292 100644
--- a/src/librustc_target/abi/call/powerpc64.rs
+++ b/src/librustc_target/abi/call/powerpc64.rs
@@ -75,7 +75,9 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>, abi: ABI)
     let size = ret.layout.size;
     let bits = size.bits();
     if bits <= 128 {
-        let unit = if bits <= 8 {
+        let unit = if cx.data_layout().endian == Endian::Big {
+            Reg { kind: RegKind::Integer, size }
+        } else if bits <= 8 {
             Reg::i8()
         } else if bits <= 16 {
             Reg::i16()
@@ -110,22 +112,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI)
     }
 
     let size = arg.layout.size;
-    let (unit, total) = match abi {
-        ELFv1 => {
-            // In ELFv1, aggregates smaller than a doubleword should appear in
-            // the least-significant bits of the parameter doubleword.  The rest
-            // should be padded at their tail to fill out multiple doublewords.
-            if size.bits() <= 64 {
-                (Reg { kind: RegKind::Integer, size }, size)
-            } else {
-                let align = Align::from_bits(64, 64).unwrap();
-                (Reg::i64(), size.abi_align(align))
-            }
-        },
-        ELFv2 => {
-            // In ELFv2, we can just cast directly.
-            (Reg::i64(), size)
-        },
+    let (unit, total) = if size.bits() <= 64 {
+        // Aggregates smaller than a doubleword should appear in
+        // the least-significant bits of the parameter doubleword.
+        (Reg { kind: RegKind::Integer, size }, size)
+    } else {
+        // Aggregates larger than a doubleword should be padded
+        // at the tail to fill out a whole number of doublewords.
+        let align = Align::from_bits(64, 64).unwrap();
+        (Reg::i64(), size.abi_align(align))
     };
 
     arg.cast_to(Uniform {
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 88f22912fa6..22afb0da05b 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -229,7 +229,7 @@ impl HasDataLayout for TargetDataLayout {
 }
 
 /// Endianness of the target, which must match cfg(target-endian).
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Endian {
     Little,
     Big