about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2025-05-08 14:30:33 -0700
committerJubilee Young <workingjubilee@gmail.com>2025-05-17 06:42:46 +0200
commit0c157b51d339fbfe51b6ef21acd4b21452c76f2c (patch)
tree8ca1e01cad9d2a78a2dba64764f962a6c1842458
parentc8bda740ea5c21af42fe4afa907f89805ab2b905 (diff)
downloadrust-0c157b51d339fbfe51b6ef21acd4b21452c76f2c.tar.gz
rust-0c157b51d339fbfe51b6ef21acd4b21452c76f2c.zip
aarch64-linux: Default to FramePointer::NonLeaf
For aarch64-apple and aarch64-windows, platform docs state that code
must use frame pointers correctly. This is because the AAPCS64 mandates
that a platform specify its frame pointer conformance requirements:
- Apple: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers
- Windows: https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers
- AAPCS64: https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer

Unwinding code either requires unwind tables or frame pointers, and
on aarch64 the expectation is that one can use frame pointers for this.
Most Linux targets represent a motley variety of possible distributions,
so it is unclear who to defer to on conformance, other than perhaps Arm.
In the absence of a specific edict for a given aarch64-linux target,
Rust will assume aarch64-linux targets use non-leaf frame pointers.
This reflects what compilers like clang do.
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs12
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs8
-rw-r--r--tests/assembly/asm/aarch64-types.rs7
-rw-r--r--tests/codegen/frame-pointer.rs4
9 files changed, 52 insertions, 13 deletions
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index 87c07cd3109..4b75a6e5dbf 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,6 +16,10 @@ pub(crate) fn target() -> Target {
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index e785069c78a..2a16d1de3b5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
@@ -20,6 +20,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "ilp32".into(),
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
             endian: Endian::Big,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index 41c25393e12..d8651f305fe 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
 // for target ABI requirements.
@@ -20,6 +22,10 @@ pub(crate) fn target() -> Target {
             // As documented in https://developer.android.com/ndk/guides/cpu-features.html
             // the neon (ASIMD) and FP must exist on all android aarch64 targets.
             features: "+v8a,+neon,+fp-armv8".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             stack_probes: StackProbeType::Inline,
             supported_sanitizers: SanitizerSet::CFI
                 | SanitizerSet::HWADDRESS
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index c6be2c20ea2..4220d74dfc8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -14,6 +16,10 @@ pub(crate) fn target() -> Target {
         arch: "aarch64".into(),
         options: TargetOptions {
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             mcount: "\u{1}_mcount".into(),
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index 166bb1ed215..a22c1289677 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -1,4 +1,4 @@
-use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,6 +15,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             abi: "ilp32".into(),
             features: "+v8a,+outline-atomics".into(),
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             max_atomic_width: Some(128),
             stack_probes: StackProbeType::Inline,
             mcount: "\u{1}_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 58ba06e124c..58daaa03675 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -26,6 +28,12 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
-        options: TargetOptions { mcount: "\u{1}_mcount".into(), ..base },
+        options: TargetOptions {
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
+             mcount: "\u{1}_mcount".into(), ..base
+         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index f2994b1232e..51cdebf22db 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -1,4 +1,6 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_ohos::opts();
@@ -16,6 +18,10 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: "aarch64".into(),
         options: TargetOptions {
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
             mcount: "\u{1}_mcount".into(),
             stack_probes: StackProbeType::Inline,
             supported_sanitizers: SanitizerSet::ADDRESS
diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
index ad2770d43e3..b7abeb02298 100644
--- a/tests/assembly/asm/aarch64-types.rs
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -86,12 +86,11 @@ pub unsafe fn sym_static() {
 
 // Regression test for #75761
 // CHECK-LABEL: {{("#)?}}issue_75761{{"?}}
-// aarch64: str {{.*}}x30
-// arm64ec: stp {{.*}}x30
+// x29 holds the frame pointer, right next to x30, so ldp/stp happens sometimes
+// CHECK: st[[MAY_PAIR:(r|p).*]]x30
 // CHECK: //APP
 // CHECK: //NO_APP
-// aarch64: ldr {{.*}}x30
-// arm64ec: ldp {{.*}}x30
+// CHECK: ld[[MAY_PAIR]]x30
 #[no_mangle]
 pub unsafe fn issue_75761() {
     asm!("", out("v0") _, out("x30") _);
diff --git a/tests/codegen/frame-pointer.rs b/tests/codegen/frame-pointer.rs
index 1f7c9a59c98..23989653fa8 100644
--- a/tests/codegen/frame-pointer.rs
+++ b/tests/codegen/frame-pointer.rs
@@ -26,8 +26,10 @@ pub fn peach(x: u32) -> u32 {
 
 // CHECK: attributes [[PEACH_ATTRS]] = {
 // x64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
-// aarch64-linux-NOT: {{.*}}"frame-pointer"{{.*}}
 // x64-apple-SAME: {{.*}}"frame-pointer"="all"
 // force-SAME: {{.*}}"frame-pointer"="all"
+//
+// AAPCS64 demands frame pointers:
+// aarch64-linux-SAME: {{.*}}"frame-pointer"="non-leaf"
 // aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf"
 // CHECK-SAME: }