summaryrefslogtreecommitdiff
path: root/user/rust/0008-Fix-powerpc64-ELFv2-big-endian-struct-passing-ABI.patch
blob: 1c4c813fc715f8418b5ed03cae5fd83f1e85d089 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
From 8a2c9af2ea8b21d38f5ff779fde29f612bb63575 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sun, 16 Sep 2018 16:34:15 +0000
Subject: [PATCH 08/23] 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.
---
 src/librustc_target/abi/call/powerpc64.rs | 29 ++++++++++-------------
 src/librustc_target/abi/mod.rs            |  2 +-
 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 0c5ec77a39..934d2b1138 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 1a5d2801af..0ec2cc0d7b 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -214,7 +214,7 @@ impl<'a> HasDataLayout for &'a TargetDataLayout {
 }
 
 /// Endianness of the target, which must match cfg(target-endian).
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Endian {
     Little,
     Big
-- 
2.19.2