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;
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.
}
// 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);
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
llvm::AddFunctionAttrString(llfn, Function, cstr!("cmse_nonsecure_entry"));
}
+ if let Some(align) = codegen_fn_attrs.alignment {
+ llvm::set_alignment(llfn, align as usize);
+ }
sanitize(cx, codegen_fn_attrs.no_sanitize, llfn);
// Always annotate functions with the target-cpu they are compiled for.