Skip to content

Commit dfd30d7

Browse files
Rollup merge of #86652 - nagisa:nagisa/non-leaf-fp, r=petrochenkov
Add support for leaf function frame pointer elimination This PR adds ability for the target specifications to specify frame pointer emission type that's not just “always” or “whatever cg decides”. In particular there's a new mode that allows omission of the frame pointer for leaf functions (those that don't call any other functions). We then set this new mode for Aarch64-based Apple targets. Fixes #86196
2 parents 052e8d5 + 9b67cba commit dfd30d7

24 files changed

+149
-60
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt};
1212
use rustc_session::config::OptLevel;
1313
use rustc_session::Session;
1414
use rustc_target::spec::abi::Abi;
15-
use rustc_target::spec::{SanitizerSet, StackProbeType};
15+
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType};
1616

1717
use crate::attributes;
1818
use crate::llvm::AttributePlace::Function;
@@ -69,15 +69,25 @@ fn naked(val: &'ll Value, is_naked: bool) {
6969
Attribute::Naked.toggle_llfn(Function, val, is_naked);
7070
}
7171

72-
pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
73-
if cx.sess().must_not_eliminate_frame_pointers() {
74-
llvm::AddFunctionAttrStringValue(
75-
llfn,
76-
llvm::AttributePlace::Function,
77-
cstr!("frame-pointer"),
78-
cstr!("all"),
79-
);
72+
pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
73+
let mut fp = cx.sess().target.frame_pointer;
74+
// "mcount" function relies on stack pointer.
75+
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
76+
if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true))
77+
{
78+
fp = FramePointer::Always;
8079
}
80+
let attr_value = match fp {
81+
FramePointer::Always => cstr!("all"),
82+
FramePointer::NonLeaf => cstr!("non-leaf"),
83+
FramePointer::MayOmit => return,
84+
};
85+
llvm::AddFunctionAttrStringValue(
86+
llfn,
87+
llvm::AttributePlace::Function,
88+
cstr!("frame-pointer"),
89+
attr_value,
90+
);
8191
}
8292

8393
/// Tell LLVM what instrument function to insert.
@@ -254,7 +264,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
254264
}
255265

256266
// FIXME: none of these three functions interact with source level attributes.
257-
set_frame_pointer_elimination(cx, llfn);
267+
set_frame_pointer_type(cx, llfn);
258268
set_instrument_function(cx, llfn);
259269
set_probestack(cx, llfn);
260270

compiler/rustc_codegen_llvm/src/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
410410
&self.used_statics
411411
}
412412

413-
fn set_frame_pointer_elimination(&self, llfn: &'ll Value) {
414-
attributes::set_frame_pointer_elimination(self, llfn)
413+
fn set_frame_pointer_type(&self, llfn: &'ll Value) {
414+
attributes::set_frame_pointer_type(self, llfn)
415415
}
416416

417417
fn apply_target_cpu_attr(&self, llfn: &'ll Value) {

compiler/rustc_codegen_llvm/src/intrinsic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ fn gen_fn<'ll, 'tcx>(
674674
) -> &'ll Value {
675675
let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
676676
let llfn = cx.declare_fn(name, &fn_abi);
677-
cx.set_frame_pointer_elimination(llfn);
677+
cx.set_frame_pointer_type(llfn);
678678
cx.apply_target_cpu_attr(llfn);
679679
// FIXME(eddyb) find a nicer way to do this.
680680
unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };

compiler/rustc_codegen_ssa/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
406406
};
407407

408408
// `main` should respect same config for frame pointer elimination as rest of code
409-
cx.set_frame_pointer_elimination(llfn);
409+
cx.set_frame_pointer_type(llfn);
410410
cx.apply_target_cpu_attr(llfn);
411411

412412
let llbb = Bx::append_block(&cx, llfn, "top");

compiler/rustc_codegen_ssa/src/traits/misc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub trait MiscMethods<'tcx>: BackendTypes {
1616
fn sess(&self) -> &Session;
1717
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
1818
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
19-
fn set_frame_pointer_elimination(&self, llfn: Self::Function);
19+
fn set_frame_pointer_type(&self, llfn: Self::Function);
2020
fn apply_target_cpu_attr(&self, llfn: Self::Function);
2121
fn create_used_variable(&self);
2222
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.

compiler/rustc_session/src/session.rs

-12
Original file line numberDiff line numberDiff line change
@@ -792,18 +792,6 @@ impl Session {
792792
!self.target.is_like_windows && !self.target.is_like_osx
793793
}
794794

795-
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
796-
// "mcount" function relies on stack pointer.
797-
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
798-
if self.instrument_mcount() {
799-
true
800-
} else if let Some(x) = self.opts.cg.force_frame_pointers {
801-
x
802-
} else {
803-
!self.target.eliminate_frame_pointer
804-
}
805-
}
806-
807795
pub fn must_emit_unwind_tables(&self) -> bool {
808796
// This is used to control the emission of the `uwtable` attribute on
809797
// LLVM functions.

compiler/rustc_target/src/spec/aarch64_apple_darwin.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
1+
use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions};
22

33
pub fn target() -> Target {
44
let mut base = super::apple_base::opts("macos");
@@ -20,6 +20,10 @@ pub fn target() -> Target {
2020
pointer_width: 64,
2121
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
2222
arch: arch.to_string(),
23-
options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
23+
options: TargetOptions {
24+
mcount: "\u{1}mcount".to_string(),
25+
frame_pointer: FramePointer::NonLeaf,
26+
..base
27+
},
2428
}
2529
}

compiler/rustc_target/src/spec/aarch64_apple_ios.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::apple_sdk_base::{opts, Arch};
2-
use crate::spec::{Target, TargetOptions};
2+
use crate::spec::{FramePointer, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let base = opts("ios", Arch::Arm64);
@@ -13,6 +13,7 @@ pub fn target() -> Target {
1313
max_atomic_width: Some(128),
1414
unsupported_abis: super::arm_base::unsupported_abis(),
1515
forces_embed_bitcode: true,
16+
frame_pointer: FramePointer::NonLeaf,
1617
// Taken from a clang build on Xcode 11.4.1.
1718
// These arguments are not actually invoked - they just have
1819
// to look right to pass App Store validation.

compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::apple_sdk_base::{opts, Arch};
2-
use crate::spec::{Target, TargetOptions};
2+
use crate::spec::{FramePointer, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let base = opts("ios", Arch::Arm64_macabi);
@@ -13,6 +13,7 @@ pub fn target() -> Target {
1313
max_atomic_width: Some(128),
1414
unsupported_abis: super::arm_base::unsupported_abis(),
1515
forces_embed_bitcode: true,
16+
frame_pointer: FramePointer::NonLeaf,
1617
// Taken from a clang build on Xcode 11.4.1.
1718
// These arguments are not actually invoked - they just have
1819
// to look right to pass App Store validation.

compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::apple_sdk_base::{opts, Arch};
2-
use crate::spec::{Target, TargetOptions};
2+
use crate::spec::{FramePointer, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let base = opts("ios", Arch::Arm64_sim);
@@ -21,6 +21,7 @@ pub fn target() -> Target {
2121
max_atomic_width: Some(128),
2222
unsupported_abis: super::arm_base::unsupported_abis(),
2323
forces_embed_bitcode: true,
24+
frame_pointer: FramePointer::NonLeaf,
2425
// Taken from a clang build on Xcode 11.4.1.
2526
// These arguments are not actually invoked - they just have
2627
// to look right to pass App Store validation.

compiler/rustc_target/src/spec/aarch64_apple_tvos.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::apple_sdk_base::{opts, Arch};
2-
use crate::spec::{Target, TargetOptions};
2+
use crate::spec::{FramePointer, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let base = opts("tvos", Arch::Arm64);
@@ -13,6 +13,7 @@ pub fn target() -> Target {
1313
max_atomic_width: Some(128),
1414
unsupported_abis: super::arm_base::unsupported_abis(),
1515
forces_embed_bitcode: true,
16+
frame_pointer: FramePointer::NonLeaf,
1617
..base
1718
},
1819
}

compiler/rustc_target/src/spec/apple_base.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::env;
22

3-
use crate::spec::{SplitDebuginfo, TargetOptions};
3+
use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions};
44

55
pub fn opts(os: &str) -> TargetOptions {
66
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
@@ -27,7 +27,7 @@ pub fn opts(os: &str) -> TargetOptions {
2727
families: vec!["unix".to_string()],
2828
is_like_osx: true,
2929
dwarf_version: Some(2),
30-
eliminate_frame_pointer: false,
30+
frame_pointer: FramePointer::Always,
3131
has_rpath: true,
3232
dll_suffix: ".dylib".to_string(),
3333
archive_format: "darwin".to_string(),

compiler/rustc_target/src/spec/freebsd_base.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{RelroLevel, TargetOptions};
1+
use crate::spec::{FramePointer, RelroLevel, TargetOptions};
22

33
pub fn opts() -> TargetOptions {
44
TargetOptions {
@@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions {
88
families: vec!["unix".to_string()],
99
has_rpath: true,
1010
position_independent_executables: true,
11-
eliminate_frame_pointer: false, // FIXME 43575
11+
frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
1212
relro_level: RelroLevel::Full,
1313
abi_return_struct_as_int: true,
1414
dwarf_version: Some(2),

compiler/rustc_target/src/spec/i686_apple_darwin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
1+
use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions};
22

33
pub fn target() -> Target {
44
let mut base = super::apple_base::opts("macos");
@@ -8,7 +8,7 @@ pub fn target() -> Target {
88
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
99
// don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
1010
base.stack_probes = StackProbeType::Call;
11-
base.eliminate_frame_pointer = false;
11+
base.frame_pointer = FramePointer::Always;
1212

1313
// Clang automatically chooses a more specific target based on
1414
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work

compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use crate::spec::{LinkerFlavor, LldFlavor, Target};
1+
use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::windows_gnu_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.pre_link_args
77
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
88
base.max_atomic_width = Some(64);
9-
base.eliminate_frame_pointer = false; // Required for backtraces
9+
base.frame_pointer = FramePointer::Always; // Required for backtraces
1010
base.linker = Some("i686-w64-mingw32-gcc".to_string());
1111

1212
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address

compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkerFlavor, StackProbeType, Target};
1+
use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::linux_musl_base::opts();
@@ -21,7 +21,7 @@ pub fn target() -> Target {
2121
//
2222
// This may or may not be related to this bug:
2323
// https://llvm.org/bugs/show_bug.cgi?id=30879
24-
base.eliminate_frame_pointer = false;
24+
base.frame_pointer = FramePointer::Always;
2525

2626
Target {
2727
llvm_target: "i686-unknown-linux-musl".to_string(),

compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use crate::spec::{LinkerFlavor, LldFlavor, Target};
1+
use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
22

33
pub fn target() -> Target {
44
let mut base = super::windows_uwp_gnu_base::opts();
55
base.cpu = "pentium4".to_string();
66
base.pre_link_args
77
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
88
base.max_atomic_width = Some(64);
9-
base.eliminate_frame_pointer = false; // Required for backtraces
9+
base.frame_pointer = FramePointer::Always; // Required for backtraces
1010

1111
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
1212
// space available to x86 Windows binaries on x86_64.

compiler/rustc_target/src/spec/illumos_base.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
1+
use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
22
use std::default::Default;
33

44
pub fn opts() -> TargetOptions {
@@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions {
3535
is_like_solaris: true,
3636
linker_is_gnu: false,
3737
limit_rdylib_exports: false, // Linker doesn't support this
38-
eliminate_frame_pointer: false,
38+
frame_pointer: FramePointer::Always,
3939
eh_frame_header: false,
4040
late_link_args,
4141

compiler/rustc_target/src/spec/linux_kernel_base.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions};
1+
use crate::spec::TargetOptions;
2+
use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
23

34
pub fn opts() -> TargetOptions {
45
TargetOptions {
@@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions {
78
panic_strategy: PanicStrategy::Abort,
89
// don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
910
stack_probes: StackProbeType::Call,
10-
eliminate_frame_pointer: false,
11+
frame_pointer: FramePointer::Always,
1112
position_independent_executables: true,
1213
needs_plt: true,
1314
relro_level: RelroLevel::Full,

0 commit comments

Comments
 (0)