mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
Add support for leaf fn 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
This commit is contained in:
parent
3ddb78a346
commit
9b67cba4f6
@ -12,7 +12,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_session::Session;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_target::spec::{SanitizerSet, StackProbeType};
|
||||
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType};
|
||||
|
||||
use crate::attributes;
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
@ -69,15 +69,25 @@ fn naked(val: &'ll Value, is_naked: bool) {
|
||||
Attribute::Naked.toggle_llfn(Function, val, is_naked);
|
||||
}
|
||||
|
||||
pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
||||
if cx.sess().must_not_eliminate_frame_pointers() {
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
llfn,
|
||||
llvm::AttributePlace::Function,
|
||||
cstr!("frame-pointer"),
|
||||
cstr!("all"),
|
||||
);
|
||||
pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
||||
let mut fp = cx.sess().target.frame_pointer;
|
||||
// "mcount" function relies on stack pointer.
|
||||
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
|
||||
if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true))
|
||||
{
|
||||
fp = FramePointer::Always;
|
||||
}
|
||||
let attr_value = match fp {
|
||||
FramePointer::Always => cstr!("all"),
|
||||
FramePointer::NonLeaf => cstr!("non-leaf"),
|
||||
FramePointer::MayOmit => return,
|
||||
};
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
llfn,
|
||||
llvm::AttributePlace::Function,
|
||||
cstr!("frame-pointer"),
|
||||
attr_value,
|
||||
);
|
||||
}
|
||||
|
||||
/// 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::
|
||||
}
|
||||
|
||||
// FIXME: none of these three functions interact with source level attributes.
|
||||
set_frame_pointer_elimination(cx, llfn);
|
||||
set_frame_pointer_type(cx, llfn);
|
||||
set_instrument_function(cx, llfn);
|
||||
set_probestack(cx, llfn);
|
||||
|
||||
|
@ -410,8 +410,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
&self.used_statics
|
||||
}
|
||||
|
||||
fn set_frame_pointer_elimination(&self, llfn: &'ll Value) {
|
||||
attributes::set_frame_pointer_elimination(self, llfn)
|
||||
fn set_frame_pointer_type(&self, llfn: &'ll Value) {
|
||||
attributes::set_frame_pointer_type(self, llfn)
|
||||
}
|
||||
|
||||
fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
|
||||
|
@ -674,7 +674,7 @@ fn gen_fn<'ll, 'tcx>(
|
||||
) -> &'ll Value {
|
||||
let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
|
||||
let llfn = cx.declare_fn(name, &fn_abi);
|
||||
cx.set_frame_pointer_elimination(llfn);
|
||||
cx.set_frame_pointer_type(llfn);
|
||||
cx.apply_target_cpu_attr(llfn);
|
||||
// FIXME(eddyb) find a nicer way to do this.
|
||||
unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
|
||||
|
@ -406,7 +406,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
};
|
||||
|
||||
// `main` should respect same config for frame pointer elimination as rest of code
|
||||
cx.set_frame_pointer_elimination(llfn);
|
||||
cx.set_frame_pointer_type(llfn);
|
||||
cx.apply_target_cpu_attr(llfn);
|
||||
|
||||
let llbb = Bx::append_block(&cx, llfn, "top");
|
||||
|
@ -16,7 +16,7 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
||||
fn sess(&self) -> &Session;
|
||||
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
|
||||
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
|
||||
fn set_frame_pointer_elimination(&self, llfn: Self::Function);
|
||||
fn set_frame_pointer_type(&self, llfn: Self::Function);
|
||||
fn apply_target_cpu_attr(&self, llfn: Self::Function);
|
||||
fn create_used_variable(&self);
|
||||
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
|
||||
|
@ -792,18 +792,6 @@ impl Session {
|
||||
!self.target.is_like_windows && !self.target.is_like_osx
|
||||
}
|
||||
|
||||
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
|
||||
// "mcount" function relies on stack pointer.
|
||||
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
|
||||
if self.instrument_mcount() {
|
||||
true
|
||||
} else if let Some(x) = self.opts.cg.force_frame_pointers {
|
||||
x
|
||||
} else {
|
||||
!self.target.eliminate_frame_pointer
|
||||
}
|
||||
}
|
||||
|
||||
pub fn must_emit_unwind_tables(&self) -> bool {
|
||||
// This is used to control the emission of the `uwtable` attribute on
|
||||
// LLVM functions.
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::apple_base::opts("macos");
|
||||
@ -20,6 +20,10 @@ pub fn target() -> Target {
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
arch: arch.to_string(),
|
||||
options: TargetOptions { mcount: "\u{1}mcount".to_string(), ..base },
|
||||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".to_string(),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..base
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::Arm64);
|
||||
@ -13,6 +13,7 @@ pub fn target() -> Target {
|
||||
max_atomic_width: Some(128),
|
||||
unsupported_abis: super::arm_base::unsupported_abis(),
|
||||
forces_embed_bitcode: true,
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
// Taken from a clang build on Xcode 11.4.1.
|
||||
// These arguments are not actually invoked - they just have
|
||||
// to look right to pass App Store validation.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::Arm64_macabi);
|
||||
@ -13,6 +13,7 @@ pub fn target() -> Target {
|
||||
max_atomic_width: Some(128),
|
||||
unsupported_abis: super::arm_base::unsupported_abis(),
|
||||
forces_embed_bitcode: true,
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
// Taken from a clang build on Xcode 11.4.1.
|
||||
// These arguments are not actually invoked - they just have
|
||||
// to look right to pass App Store validation.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::Arm64_sim);
|
||||
@ -21,6 +21,7 @@ pub fn target() -> Target {
|
||||
max_atomic_width: Some(128),
|
||||
unsupported_abis: super::arm_base::unsupported_abis(),
|
||||
forces_embed_bitcode: true,
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
// Taken from a clang build on Xcode 11.4.1.
|
||||
// These arguments are not actually invoked - they just have
|
||||
// to look right to pass App Store validation.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("tvos", Arch::Arm64);
|
||||
@ -13,6 +13,7 @@ pub fn target() -> Target {
|
||||
max_atomic_width: Some(128),
|
||||
unsupported_abis: super::arm_base::unsupported_abis(),
|
||||
forces_embed_bitcode: true,
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..base
|
||||
},
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::env;
|
||||
|
||||
use crate::spec::{SplitDebuginfo, TargetOptions};
|
||||
use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions};
|
||||
|
||||
pub fn opts(os: &str) -> TargetOptions {
|
||||
// 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 {
|
||||
families: vec!["unix".to_string()],
|
||||
is_like_osx: true,
|
||||
dwarf_version: Some(2),
|
||||
eliminate_frame_pointer: false,
|
||||
frame_pointer: FramePointer::Always,
|
||||
has_rpath: true,
|
||||
dll_suffix: ".dylib".to_string(),
|
||||
archive_format: "darwin".to_string(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{RelroLevel, TargetOptions};
|
||||
use crate::spec::{FramePointer, RelroLevel, TargetOptions};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
@ -8,7 +8,7 @@ pub fn opts() -> TargetOptions {
|
||||
families: vec!["unix".to_string()],
|
||||
has_rpath: true,
|
||||
position_independent_executables: true,
|
||||
eliminate_frame_pointer: false, // FIXME 43575
|
||||
frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
|
||||
relro_level: RelroLevel::Full,
|
||||
abi_return_struct_as_int: true,
|
||||
dwarf_version: Some(2),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
|
||||
use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::apple_base::opts("macos");
|
||||
@ -8,7 +8,7 @@ pub fn target() -> Target {
|
||||
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
|
||||
// don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
|
||||
base.stack_probes = StackProbeType::Call;
|
||||
base.eliminate_frame_pointer = false;
|
||||
base.frame_pointer = FramePointer::Always;
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, LldFlavor, Target};
|
||||
use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::windows_gnu_base::opts();
|
||||
@ -6,7 +6,7 @@ pub fn target() -> Target {
|
||||
base.pre_link_args
|
||||
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.eliminate_frame_pointer = false; // Required for backtraces
|
||||
base.frame_pointer = FramePointer::Always; // Required for backtraces
|
||||
base.linker = Some("i686-w64-mingw32-gcc".to_string());
|
||||
|
||||
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, StackProbeType, Target};
|
||||
use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::linux_musl_base::opts();
|
||||
@ -21,7 +21,7 @@ pub fn target() -> Target {
|
||||
//
|
||||
// This may or may not be related to this bug:
|
||||
// https://llvm.org/bugs/show_bug.cgi?id=30879
|
||||
base.eliminate_frame_pointer = false;
|
||||
base.frame_pointer = FramePointer::Always;
|
||||
|
||||
Target {
|
||||
llvm_target: "i686-unknown-linux-musl".to_string(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkerFlavor, LldFlavor, Target};
|
||||
use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::windows_uwp_gnu_base::opts();
|
||||
@ -6,7 +6,7 @@ pub fn target() -> Target {
|
||||
base.pre_link_args
|
||||
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.eliminate_frame_pointer = false; // Required for backtraces
|
||||
base.frame_pointer = FramePointer::Always; // Required for backtraces
|
||||
|
||||
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
|
||||
// space available to x86 Windows binaries on x86_64.
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
|
||||
use crate::spec::{FramePointer, LinkArgs, LinkerFlavor, TargetOptions};
|
||||
use std::default::Default;
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions {
|
||||
is_like_solaris: true,
|
||||
linker_is_gnu: false,
|
||||
limit_rdylib_exports: false, // Linker doesn't support this
|
||||
eliminate_frame_pointer: false,
|
||||
frame_pointer: FramePointer::Always,
|
||||
eh_frame_header: false,
|
||||
late_link_args,
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions};
|
||||
use crate::spec::TargetOptions;
|
||||
use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions {
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
// don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
|
||||
stack_probes: StackProbeType::Call,
|
||||
eliminate_frame_pointer: false,
|
||||
frame_pointer: FramePointer::Always,
|
||||
position_independent_executables: true,
|
||||
needs_plt: true,
|
||||
relro_level: RelroLevel::Full,
|
||||
|
@ -671,6 +671,42 @@ impl ToJson for SanitizerSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum FramePointer {
|
||||
/// Forces the machine code generator to always preserve the frame pointers.
|
||||
Always,
|
||||
/// Forces the machine code generator to preserve the frame pointers except for the leaf
|
||||
/// functions (i.e. those that don't call other functions).
|
||||
NonLeaf,
|
||||
/// Allows the machine code generator to omit the frame pointers.
|
||||
///
|
||||
/// This option does not guarantee that the frame pointers will be omitted.
|
||||
MayOmit,
|
||||
}
|
||||
|
||||
impl FromStr for FramePointer {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
Ok(match s {
|
||||
"always" => Self::Always,
|
||||
"non-leaf" => Self::NonLeaf,
|
||||
"may-omit" => Self::MayOmit,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for FramePointer {
|
||||
fn to_json(&self) -> Json {
|
||||
match *self {
|
||||
Self::Always => "always",
|
||||
Self::NonLeaf => "non-leaf",
|
||||
Self::MayOmit => "may-omit",
|
||||
}
|
||||
.to_json()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! supported_targets {
|
||||
( $(($( $triple:literal, )+ $module:ident ),)+ ) => {
|
||||
$(mod $module;)+
|
||||
@ -1068,8 +1104,8 @@ pub struct TargetOptions {
|
||||
pub tls_model: TlsModel,
|
||||
/// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
|
||||
pub disable_redzone: bool,
|
||||
/// Eliminate frame pointers from stack frames if possible. Defaults to true.
|
||||
pub eliminate_frame_pointer: bool,
|
||||
/// Frame pointer mode for this target. Defaults to `MayOmit`.
|
||||
pub frame_pointer: FramePointer,
|
||||
/// Emit each function in its own section. Defaults to true.
|
||||
pub function_sections: bool,
|
||||
/// String to prepend to the name of every dynamic library. Defaults to "lib".
|
||||
@ -1330,7 +1366,7 @@ impl Default for TargetOptions {
|
||||
code_model: None,
|
||||
tls_model: TlsModel::GeneralDynamic,
|
||||
disable_redzone: false,
|
||||
eliminate_frame_pointer: true,
|
||||
frame_pointer: FramePointer::MayOmit,
|
||||
function_sections: true,
|
||||
dll_prefix: "lib".to_string(),
|
||||
dll_suffix: ".so".to_string(),
|
||||
@ -1833,6 +1869,16 @@ impl Target {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(fp) = obj.remove_key("frame-pointer") {
|
||||
if let Some(s) = Json::as_string(&fp) {
|
||||
base.frame_pointer = s
|
||||
.parse()
|
||||
.map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?;
|
||||
} else {
|
||||
incorrect_type.push("frame-pointer".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
key!(is_builtin, bool);
|
||||
key!(c_int_width = "target-c-int-width");
|
||||
key!(os);
|
||||
@ -1864,7 +1910,6 @@ impl Target {
|
||||
key!(code_model, CodeModel)?;
|
||||
key!(tls_model, TlsModel)?;
|
||||
key!(disable_redzone, bool);
|
||||
key!(eliminate_frame_pointer, bool);
|
||||
key!(function_sections, bool);
|
||||
key!(dll_prefix);
|
||||
key!(dll_suffix);
|
||||
@ -2128,7 +2173,7 @@ impl ToJson for Target {
|
||||
target_option_val!(code_model);
|
||||
target_option_val!(tls_model);
|
||||
target_option_val!(disable_redzone);
|
||||
target_option_val!(eliminate_frame_pointer);
|
||||
target_option_val!(frame_pointer);
|
||||
target_option_val!(function_sections);
|
||||
target_option_val!(dll_prefix);
|
||||
target_option_val!(dll_suffix);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::spec::{RelroLevel, TargetOptions};
|
||||
use crate::spec::{FramePointer, RelroLevel, TargetOptions};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions {
|
||||
has_rpath: true,
|
||||
abi_return_struct_as_int: true,
|
||||
position_independent_executables: true,
|
||||
eliminate_frame_pointer: false, // FIXME 43575
|
||||
frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit...
|
||||
relro_level: RelroLevel::Full,
|
||||
dwarf_version: Some(2),
|
||||
..Default::default()
|
||||
|
@ -27,7 +27,8 @@
|
||||
// differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
|
||||
// build scripts / gcc flags.
|
||||
|
||||
use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions};
|
||||
use crate::spec::TargetOptions;
|
||||
use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
// See rust-lang/rfcs#1645 for a discussion about these defaults
|
||||
@ -52,7 +53,7 @@ pub fn opts() -> TargetOptions {
|
||||
emit_debug_gdb_scripts: false,
|
||||
// LLVM is eager to trash the link register when calling `noreturn` functions, which
|
||||
// breaks debugging. Preserve LR by default to prevent that from happening.
|
||||
eliminate_frame_pointer: false,
|
||||
frame_pointer: FramePointer::Always,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
|
||||
use crate::spec::TargetOptions;
|
||||
use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::apple_base::opts("macos");
|
||||
base.cpu = "core2".to_string();
|
||||
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
|
||||
base.eliminate_frame_pointer = false;
|
||||
base.frame_pointer = FramePointer::Always;
|
||||
base.pre_link_args.insert(
|
||||
LinkerFlavor::Gcc,
|
||||
vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
|
||||
|
35
src/test/codegen/frame-pointer.rs
Normal file
35
src/test/codegen/frame-pointer.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// compile-flags: --crate-type=rlib
|
||||
// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux
|
||||
// [aarch64-apple] needs-llvm-components: aarch64
|
||||
// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin
|
||||
// [aarch64-linux] needs-llvm-components: aarch64
|
||||
// [aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu
|
||||
// [force] needs-llvm-components: x86
|
||||
// [force] compile-flags: --target=x86_64-unknown-linux-gnu -Cforce-frame-pointers=yes
|
||||
// [x64-apple] needs-llvm-components: x86
|
||||
// [x64-apple] compile-flags: --target=x86_64-apple-darwin
|
||||
// [x64-linux] needs-llvm-components: x86
|
||||
// [x64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
|
||||
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_core]
|
||||
#[lang="sized"]
|
||||
trait Sized { }
|
||||
#[lang="copy"]
|
||||
trait Copy { }
|
||||
|
||||
|
||||
|
||||
// CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] {
|
||||
#[no_mangle]
|
||||
pub fn peach(x: u32) -> u32 {
|
||||
x
|
||||
}
|
||||
|
||||
// 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"
|
||||
// aarch64-apple-SAME: {{.*}}"frame-pointer"="non-leaf"
|
||||
// CHECK-SAME: }
|
Loading…
Reference in New Issue
Block a user