summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-10-11 15:36:51 +0200
committerGitHub <noreply@github.com>2024-10-11 15:36:51 +0200
commitfc81a7c1d58468e0380e6d396ffebed694e7bd56 (patch)
tree37485aecf00f076d61b3670fce4cd83b44f8e9ce /compiler
parent7c79621462e724d123fb5788e5d797067f5f1222 (diff)
parente502a7f13a4605503e1b73cfdfb69d64d11ea722 (diff)
downloadrust-fc81a7c1d58468e0380e6d396ffebed694e7bd56.tar.gz
rust-fc81a7c1d58468e0380e6d396ffebed694e7bd56.zip
Rollup merge of #131208 - mustartt:aix-call-abi, r=davidtwco
ABI: Pass aggregates by value on AIX

On AIX we pass aggregates byval. Adds new ABI for AIX for powerpc64.

https://github.com/llvm/llvm-project/blob/313ad85dfa40a18f2edefd7ce2edc0528d5a554a/clang/lib/CodeGen/Targets/PPC.cpp#L216

Fixes the following 2 testcases on AIX:
```
tests/ui/abi/extern/extern-pass-TwoU16s.rs
tests/ui/abi/extern/extern-pass-TwoU8s.rs
```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_target/src/abi/call/powerpc64.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs
index b9767bf906b..71e533b8cc5 100644
--- a/compiler/rustc_target/src/abi/call/powerpc64.rs
+++ b/compiler/rustc_target/src/abi/call/powerpc64.rs
@@ -10,6 +10,7 @@ use crate::spec::HasTargetSpec;
 enum ABI {
     ELFv1, // original ABI used for powerpc64 (big-endian)
     ELFv2, // newer ABI used for powerpc64le and musl (both endians)
+    AIX,   // used by AIX OS, big-endian only
 }
 use ABI::*;
 
@@ -23,9 +24,9 @@ where
     C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
-        // ELFv1 only passes one-member aggregates transparently.
+        // ELFv1 and AIX only passes one-member aggregates transparently.
         // ELFv2 passes up to eight uniquely addressable members.
-        if (abi == ELFv1 && arg.layout.size > unit.size)
+        if ((abi == ELFv1 || abi == AIX) && arg.layout.size > unit.size)
             || arg.layout.size > unit.size.checked_mul(8, cx).unwrap()
         {
             return None;
@@ -55,8 +56,15 @@ where
         return;
     }
 
+    // The AIX ABI expect byval for aggregates
+    // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp.
+    if !is_ret && abi == AIX {
+        arg.pass_by_stack_offset(None);
+        return;
+    }
+
     // The ELFv1 ABI doesn't return aggregates in registers
-    if is_ret && abi == ELFv1 {
+    if is_ret && (abi == ELFv1 || abi == AIX) {
         arg.make_indirect();
         return;
     }
@@ -93,6 +101,8 @@ where
 {
     let abi = if cx.target_spec().env == "musl" {
         ELFv2
+    } else if cx.target_spec().os == "aix" {
+        AIX
     } else {
         match cx.data_layout().endian {
             Endian::Big => ELFv1,