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
24 changed files with 149 additions and 60 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue