From 7c0b5cf99fc8c0f575d6e6304d4b3fc247beb298 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 4 May 2024 15:41:52 -0700 Subject: [PATCH 1/8] compiler: Add FramePointer::ratchet --- compiler/rustc_target/src/spec/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 62ccc57f421..81ada30a594 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1413,6 +1413,20 @@ pub enum FramePointer { MayOmit, } +impl FramePointer { + /// It is intended that the "force frame pointer" transition is "one way" + /// so this convenience assures such if used + #[inline] + pub fn ratchet(&mut self, rhs: FramePointer) -> FramePointer { + *self = match (*self, rhs) { + (FramePointer::Always, _) | (_, FramePointer::Always) => FramePointer::Always, + (FramePointer::NonLeaf, _) | (_, FramePointer::NonLeaf) => FramePointer::NonLeaf, + _ => FramePointer::MayOmit, + }; + *self + } +} + impl FromStr for FramePointer { type Err = (); fn from_str(s: &str) -> Result { From b3a1975cdc82753ef51a784c91b3b5f9a6997054 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 4 May 2024 16:19:42 -0700 Subject: [PATCH 2/8] compiler(nfc): -Cforce-frame-pointers is a FramePointer --- compiler/rustc_codegen_llvm/src/attributes.rs | 5 +++-- compiler/rustc_interface/src/tests.rs | 6 ++--- compiler/rustc_session/src/config.rs | 7 +++--- compiler/rustc_session/src/options.rs | 22 ++++++++++++++----- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 870e5ab3296..48693895da1 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -108,9 +108,10 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr let opts = &cx.sess().opts; // "mcount" function relies on stack pointer. // See . - if opts.unstable_opts.instrument_mcount || matches!(opts.cg.force_frame_pointers, Some(true)) { - fp = FramePointer::Always; + if opts.unstable_opts.instrument_mcount { + fp.ratchet(FramePointer::Always); } + fp.ratchet(opts.cg.force_frame_pointers); let attr_value = match fp { FramePointer::Always => "all", FramePointer::NonLeaf => "non-leaf", diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2909f8adfb0..6ffc518097e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -20,9 +20,9 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, + CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi, }; -use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZero; use std::path::{Path, PathBuf}; @@ -605,7 +605,7 @@ fn test_codegen_options_tracking_hash() { tracked!(debug_assertions, Some(true)); tracked!(debuginfo, DebugInfo::Limited); tracked!(embed_bitcode, false); - tracked!(force_frame_pointers, Some(false)); + tracked!(force_frame_pointers, FramePointer::Always); tracked!(force_unwind_tables, Some(true)); tracked!(inline_threshold, Some(0xf007ba11)); tracked!(instrument_coverage, InstrumentCoverage::Yes); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 24143808ef4..34eaa74cc38 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2966,10 +2966,8 @@ pub(crate) mod dep_tracking { use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_target::spec::{ - CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, - }; - use rustc_target::spec::{ - RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, + RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, WasmCAbi, }; use std::collections::BTreeMap; use std::hash::{DefaultHasher, Hash}; @@ -3023,6 +3021,7 @@ pub(crate) mod dep_tracking { lint::Level, WasiExecModel, u32, + FramePointer, RelocModel, CodeModel, TlsModel, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 145af50117c..ce64e9113f4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -12,10 +12,9 @@ use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi, -}; -use rustc_target::spec::{ - RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, + WasmCAbi, }; use std::collections::BTreeMap; use std::hash::{DefaultHasher, Hasher}; @@ -374,6 +373,7 @@ mod desc { pub const parse_opt_comma_list: &str = parse_comma_list; pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; + pub const parse_frame_pointer: &str = parse_bool; pub const parse_threads: &str = parse_number; pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; @@ -672,6 +672,18 @@ mod parse { } } + pub(crate) fn parse_frame_pointer(slot: &mut FramePointer, v: Option<&str>) -> bool { + let mut boolish = false; + let mut is_parsed = parse_bool(&mut boolish, v); + if boolish & is_parsed { + *slot = FramePointer::Always; + } else if false { + /* TODO: add NonLeaf as an unstable opt */ + is_parsed = true; + }; + is_parsed + } + pub(crate) fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool { match v { Some("all") => { @@ -1479,7 +1491,7 @@ options! { "emit bitcode in rlibs (default: yes)"), extra_filename: String = (String::new(), parse_string, [UNTRACKED], "extra data to put in each output filename"), - force_frame_pointers: Option = (None, parse_opt_bool, [TRACKED], + force_frame_pointers: FramePointer = (FramePointer::MayOmit, parse_frame_pointer, [TRACKED], "force use of the frame pointers"), #[rustc_lint_opt_deny_field_access("use `Session::must_emit_unwind_tables` instead of this field")] force_unwind_tables: Option = (None, parse_opt_bool, [TRACKED], From 79416c411802ab6870ae6da8fdb8f7febfaa872e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 4 May 2024 16:47:18 -0700 Subject: [PATCH 3/8] cg_clif: Define build opts from FramePointer --- compiler/rustc_codegen_cranelift/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 2edb34e7c20..06ca52b3903 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -271,9 +271,9 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc Date: Sat, 4 May 2024 18:05:44 -0700 Subject: [PATCH 4/8] test: for frame-pointer=non-leaf codegen opts --- tests/codegen/force-frame-pointers.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs index 84e0bcb39ad..dece633f831 100644 --- a/tests/codegen/force-frame-pointers.rs +++ b/tests/codegen/force-frame-pointers.rs @@ -1,6 +1,11 @@ -//@ compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y -Copt-level=0 +//@ revisions: Always NonLeaf +//@ [Always] compile-flags: -Cforce-frame-pointers=yes +//@ [NonLeaf] compile-flags: -Cforce-frame-pointers=non-leaf +//@ compile-flags: -Zunstable-options +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 #![crate_type = "lib"] -// CHECK: attributes #{{.*}} "frame-pointer"="all" +// Always: attributes #{{.*}} "frame-pointer"="all" +// NonLeaf: attributes #{{.*}} "frame-pointer"="non-leaf" pub fn foo() {} From 7d160ae61a778da53256d1a02c711c4bfa693c34 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 4 May 2024 17:52:47 -0700 Subject: [PATCH 5/8] compiler: Support nightly -Cforce-frame-pointers=non-leaf Requires -Zunstable-options as this is a -C flag already. --- compiler/rustc_session/src/config.rs | 11 ++++++++++- compiler/rustc_session/src/options.rs | 7 ++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 34eaa74cc38..f4e24cd4606 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -19,7 +19,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm}; -use rustc_target::spec::{LinkSelfContainedComponents, LinkerFeatures}; +use rustc_target::spec::{FramePointer, LinkSelfContainedComponents, LinkerFeatures}; use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple}; use std::collections::btree_map::{ Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, @@ -2524,6 +2524,15 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M } } + if !nightly_options::is_unstable_enabled(matches) + && cg.force_frame_pointers == FramePointer::NonLeaf + { + early_dcx.early_fatal( + "`-Cforce-frame-pointers=non-leaf` also requires `-Zunstable-options` \ + and a nightly compiler", + ) + } + // For testing purposes, until we have more feedback about these options: ensure `-Z // unstable-options` is required when using the unstable `-C link-self-contained` and `-C // linker-flavor` options. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ce64e9113f4..75f0e9a616c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -373,7 +373,8 @@ mod desc { pub const parse_opt_comma_list: &str = parse_comma_list; pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; - pub const parse_frame_pointer: &str = parse_bool; + pub const parse_frame_pointer: &str = + "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf`"; pub const parse_threads: &str = parse_number; pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; @@ -677,9 +678,9 @@ mod parse { let mut is_parsed = parse_bool(&mut boolish, v); if boolish & is_parsed { *slot = FramePointer::Always; - } else if false { - /* TODO: add NonLeaf as an unstable opt */ + } else if v == Some("non-leaf") { is_parsed = true; + *slot = FramePointer::NonLeaf; }; is_parsed } From 598e265d43db1ef980679d94702173b61de71c3f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 14 May 2024 12:26:01 -0700 Subject: [PATCH 6/8] compiler: Accept -Cforce-frame-pointers=always Also lands behind -Zunstable-options, for now. Take the opportunity to do some mild cleanup. --- compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_session/src/options.rs | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f4e24cd4606..839cc51efce 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2528,7 +2528,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M && cg.force_frame_pointers == FramePointer::NonLeaf { early_dcx.early_fatal( - "`-Cforce-frame-pointers=non-leaf` also requires `-Zunstable-options` \ + "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \ and a nightly compiler", ) } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 75f0e9a616c..933bae793f8 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -373,8 +373,7 @@ mod desc { pub const parse_opt_comma_list: &str = parse_comma_list; pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; - pub const parse_frame_pointer: &str = - "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf`"; + pub const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`"; pub const parse_threads: &str = parse_number; pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; @@ -674,15 +673,15 @@ mod parse { } pub(crate) fn parse_frame_pointer(slot: &mut FramePointer, v: Option<&str>) -> bool { - let mut boolish = false; - let mut is_parsed = parse_bool(&mut boolish, v); - if boolish & is_parsed { - *slot = FramePointer::Always; - } else if v == Some("non-leaf") { - is_parsed = true; - *slot = FramePointer::NonLeaf; + let mut yes = false; + match v { + Some(_) if parse_bool(&mut yes, v) && yes => slot.ratchet(FramePointer::Always), + Some(_) if parse_bool(&mut yes, v) => slot.ratchet(FramePointer::MayOmit), + Some("always") => slot.ratchet(FramePointer::Always), + Some("non-leaf") => slot.ratchet(FramePointer::NonLeaf), + _ => return false, }; - is_parsed + true } pub(crate) fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool { From c72a6ad8f2653d8da38a28520b6c5a2d64aa7aa5 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 22 Jun 2024 21:36:11 -0700 Subject: [PATCH 7/8] test: ignore force-frame-pointers test on some targets all of these currently force stronger frame pointers, and currently the CLI does not override the target --- src/tools/compiletest/src/header.rs | 2 ++ tests/codegen/force-frame-pointers.rs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5469b9f1a0a..82d80fcc19c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -779,6 +779,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-haiku", "ignore-horizon", "ignore-i686-pc-windows-msvc", + "ignore-illumos", "ignore-ios", "ignore-linux", "ignore-lldb", @@ -843,6 +844,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-x32", "ignore-x86", "ignore-x86_64", + "ignore-x86_64-apple-darwin", "ignore-x86_64-unknown-linux-gnu", "incremental", "known-bug", diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs index dece633f831..88c918945d6 100644 --- a/tests/codegen/force-frame-pointers.rs +++ b/tests/codegen/force-frame-pointers.rs @@ -3,6 +3,13 @@ //@ [NonLeaf] compile-flags: -Cforce-frame-pointers=non-leaf //@ compile-flags: -Zunstable-options //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ [NonLeaf] ignore-illumos +//@ [NonLeaf] ignore-openbsd +//@ [NonLeaf] ignore-x86 +//@ [NonLeaf] ignore-x86_64-apple-darwin +//@ [NonLeaf] ignore-windows-gnu +//@ [NonLeaf] ignore-thumb +// result is platform-dependent based on platform's frame pointer settings #![crate_type = "lib"] From 761ba5bb073578c6a510482be8338075f0b71493 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 23 Jun 2024 02:22:55 -0700 Subject: [PATCH 8/8] compiler: parse the empty frame-pointer --- compiler/rustc_session/src/options.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 933bae793f8..f068d093889 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -675,8 +675,8 @@ mod parse { pub(crate) fn parse_frame_pointer(slot: &mut FramePointer, v: Option<&str>) -> bool { let mut yes = false; match v { - Some(_) if parse_bool(&mut yes, v) && yes => slot.ratchet(FramePointer::Always), - Some(_) if parse_bool(&mut yes, v) => slot.ratchet(FramePointer::MayOmit), + _ if parse_bool(&mut yes, v) && yes => slot.ratchet(FramePointer::Always), + _ if parse_bool(&mut yes, v) => slot.ratchet(FramePointer::MayOmit), Some("always") => slot.ratchet(FramePointer::Always), Some("non-leaf") => slot.ratchet(FramePointer::NonLeaf), _ => return false,