cranelift: Add a flag for preserving frame pointers (#4469)

Preserving frame pointers -- even inside leaf functions -- makes it easy to
capture the stack of a running program, without requiring any side tables or
metadata (like `.eh_frame` sections). Many sampling profilers and similar tools
walk frame pointers to capture stacks. Enabling this option will play nice with
those tools.
This commit is contained in:
Nick Fitzgerald
2022-07-20 08:02:21 -07:00
committed by GitHub
parent 6e099720af
commit 22d91a7c84
8 changed files with 96 additions and 7 deletions

View File

@@ -237,6 +237,19 @@ pub(crate) fn define() -> SettingGroup {
true, true,
); );
settings.add_bool(
"preserve_frame_pointers",
"Preserve frame pointers",
r#"
Preserving frame pointers -- even inside leaf functions -- makes it
easy to capture the stack of a running program, without requiring any
side tables or metadata (like `.eh_frame` sections). Many sampling
profilers and similar tools walk frame pointers to capture stacks.
Enabling this option will play nice with those tools.
"#,
false,
);
settings.add_bool( settings.add_bool(
"machine_code_cfg_info", "machine_code_cfg_info",
"Generate CFG metadata for machine code.", "Generate CFG metadata for machine code.",

View File

@@ -1410,7 +1410,8 @@ impl<M: ABIMachineSpec> ABICallee for ABICalleeImpl<M> {
if !self.call_conv.extends_baldrdash() { if !self.call_conv.extends_baldrdash() {
self.fixed_frame_storage_size += total_stacksize; self.fixed_frame_storage_size += total_stacksize;
self.setup_frame = M::is_frame_setup_needed( self.setup_frame = self.flags.preserve_frame_pointers()
|| M::is_frame_setup_needed(
self.is_leaf, self.is_leaf,
self.stack_args_size(), self.stack_args_size(),
clobbered_callee_saves.len(), clobbered_callee_saves.len(),

View File

@@ -541,6 +541,7 @@ enable_atomics = true
enable_safepoints = false enable_safepoints = false
enable_llvm_abi_extensions = false enable_llvm_abi_extensions = false
unwind_info = true unwind_info = true
preserve_frame_pointers = false
machine_code_cfg_info = false machine_code_cfg_info = false
emit_all_ones_funcaddrs = false emit_all_ones_funcaddrs = false
enable_probestack = true enable_probestack = true

View File

@@ -0,0 +1,15 @@
;; Test compilation of leaf functions without preserving frame pointers.
test compile precise-output
set unwind_info=false
set preserve_frame_pointers=false
target aarch64
function %leaf(i64) -> i64 {
block0(v0: i64):
return v0
}
; block0:
; ret

View File

@@ -0,0 +1,18 @@
;; Test compilation of leaf functions while preserving frame pointers.
test compile precise-output
set unwind_info=false
set preserve_frame_pointers=true
target aarch64
function %leaf(i64) -> i64 {
block0(v0: i64):
return v0
}
; stp fp, lr, [sp, #-16]!
; mov fp, sp
; block0:
; ldp fp, lr, [sp], #16
; ret

View File

@@ -0,0 +1,20 @@
;; Test compilation of leaf functions without preserving frame pointers.
test compile precise-output
set unwind_info=false
set preserve_frame_pointers=false
target x86_64
function %leaf(i64) -> i64 {
block0(v0: i64):
return v0
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; movq %rbp, %rsp
; popq %rbp
; ret

View File

@@ -0,0 +1,20 @@
;; Test compilation of leaf functions while preserving frame pointers.
test compile precise-output
set unwind_info=false
set preserve_frame_pointers=true
target x86_64
function %leaf(i64) -> i64 {
block0(v0: i64):
return v0
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; movq %rbp, %rsp
; popq %rbp
; ret

View File

@@ -393,6 +393,7 @@ impl Engine {
| "machine_code_cfg_info" | "machine_code_cfg_info"
| "tls_model" // wasmtime doesn't use tls right now | "tls_model" // wasmtime doesn't use tls right now
| "opt_level" // opt level doesn't change semantics | "opt_level" // opt level doesn't change semantics
| "preserve_frame_pointers" // we don't currently rely on frame pointers
| "enable_alias_analysis" // alias analysis-based opts don't change semantics | "enable_alias_analysis" // alias analysis-based opts don't change semantics
| "probestack_func_adjusts_sp" // probestack above asserted disabled | "probestack_func_adjusts_sp" // probestack above asserted disabled
| "probestack_size_log2" // probestack above asserted disabled | "probestack_size_log2" // probestack above asserted disabled