about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2022-06-06 12:40:10 -0400
committerFelix S. Klock II <pnkfelix@pnkfx.org>2022-07-06 10:53:28 -0400
commit8ae5a55ba55a434995d2e2e87f8ef15237ff8124 (patch)
tree064a8e84390a309a0556a6e59f5a1d0f2882a5f3
parentb2777aba757dd92042932d79309132bd953e130d (diff)
downloadrust-8ae5a55ba55a434995d2e2e87f8ef15237ff8124.tar.gz
rust-8ae5a55ba55a434995d2e2e87f8ef15237ff8124.zip
fix issue 97463 using change suggested by nbdd0121.
parameterized on target details to decide value-extension policy on calls, in order to address how Apple's aarch64 ABI differs from that on Linux and Windows.

Updated to incorporate review feedback: adjust comment on new enum specifying
param extension policy.

Updated to incorporate review feedback: shorten enum names and those of its
variants to make it less unwieldy.

placate tidy.
-rw-r--r--compiler/rustc_target/src/abi/call/aarch64.rs41
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs9
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
3 files changed, 44 insertions, 8 deletions
diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs
index 4613a459c51..b307cc3e0be 100644
--- a/compiler/rustc_target/src/abi/call/aarch64.rs
+++ b/compiler/rustc_target/src/abi/call/aarch64.rs
@@ -1,6 +1,27 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
 use crate::abi::{HasDataLayout, TyAbiInterface};
 
+/// Given integer-types M and register width N (e.g. M=u16 and N=32 bits), the
+/// `ParamExtension` policy specifies how a uM value should be treated when
+/// passed via register or stack-slot of width N. See also rust-lang/rust#97463.
+#[derive(Copy, Clone, PartialEq)]
+pub enum ParamExtension {
+    /// Indicates that when passing an i8/i16, either as a function argument or
+    /// as a return value, it must be sign-extended to 32 bits, and likewise a
+    /// u8/u16 must be zero-extended to 32-bits. (This variant is here to
+    /// accommodate Apple's deviation from the usual AArch64 ABI as defined by
+    /// ARM.)
+    ///
+    /// See also: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-Arguments-to-Functions-Correctly
+    ExtendTo32Bits,
+
+    /// Indicates that no sign- nor zero-extension is performed: if a value of
+    /// type with bitwidth M is passed as function argument or return value,
+    /// then M bits are copied into the least significant M bits, and the
+    /// remaining bits of the register (or word of memory) are untouched.
+    NoExtension,
+}
+
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
     Ty: TyAbiInterface<'a, C> + Copy,
@@ -24,13 +45,16 @@ where
     })
 }
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
+fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
-        ret.extend_integer_width_to(32);
+        match param_policy {
+            ParamExtension::ExtendTo32Bits => ret.extend_integer_width_to(32),
+            ParamExtension::NoExtension => {}
+        }
         return;
     }
     if let Some(uniform) = is_homogeneous_aggregate(cx, ret) {
@@ -46,13 +70,16 @@ where
     ret.make_indirect();
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
+fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
-        arg.extend_integer_width_to(32);
+        match param_policy {
+            ParamExtension::ExtendTo32Bits => arg.extend_integer_width_to(32),
+            ParamExtension::NoExtension => {}
+        }
         return;
     }
     if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
@@ -68,19 +95,19 @@ where
     arg.make_indirect();
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
+pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, param_policy: ParamExtension)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
-        classify_ret(cx, &mut fn_abi.ret);
+        classify_ret(cx, &mut fn_abi.ret, param_policy);
     }
 
     for arg in &mut fn_abi.args {
         if arg.is_ignore() {
             continue;
         }
-        classify_arg(cx, arg);
+        classify_arg(cx, arg, param_policy);
     }
 }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index ca1d1302ec6..c87c726cb87 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -687,7 +687,14 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                     }
                 }
             },
-            "aarch64" => aarch64::compute_abi_info(cx, self),
+            "aarch64" => {
+                let param_policy = if cx.target_spec().is_like_osx {
+                    aarch64::ParamExtension::ExtendTo32Bits
+                } else {
+                    aarch64::ParamExtension::NoExtension
+                };
+                aarch64::compute_abi_info(cx, self, param_policy)
+            }
             "amdgpu" => amdgpu::compute_abi_info(cx, self),
             "arm" => arm::compute_abi_info(cx, self),
             "avr" => avr::compute_abi_info(self),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index a08603da040..e78fefdcfad 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1250,6 +1250,8 @@ pub struct TargetOptions {
     pub abi_return_struct_as_int: bool,
     /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS,
     /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
+    /// Also indiates whether to use Apple-specific ABI changes, such as extending function
+    /// parameters to 32-bits.
     pub is_like_osx: bool,
     /// Whether the target toolchain is like Solaris's.
     /// Only useful for compiling against Illumos/Solaris,