From f331c608564be070701dc59cfbe092fe7174cb34 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Wed, 15 Jan 2025 20:43:02 +0700 Subject: [PATCH] x86-retpoline flag (target modifier) to enable retpoline-related target features --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 4 ++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 ++- .../rustc_codegen_ssa/src/target_features.rs | 4 ++- compiler/rustc_session/src/config.rs | 2 ++ compiler/rustc_session/src/options.rs | 25 ++++++++++++++++++ compiler/rustc_target/src/target_features.rs | 26 ++++++++++++++++++- ...line-target-feature-flag.by_feature.stderr | 7 +++++ .../retpoline-target-feature-flag.rs | 14 ++++++++++ 8 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/ui/target-feature/retpoline-target-feature-flag.by_feature.stderr create mode 100644 tests/ui/target-feature/retpoline-target-feature-flag.rs diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 560aff43d6538..047e0fba0e042 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -102,7 +102,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { - if let Err(reason) = stability.toggle_allowed() { + if let Err(reason) = stability.toggle_allowed( + |flag| sess.opts.target_feature_flag_enabled(flag) + ) { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, enabled: if enable { "enabled" } else { "disabled" }, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c3d7c217861fb..a4bf28558da90 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -731,7 +731,9 @@ pub(crate) fn global_llvm_features( sess.dcx().emit_warn(unknown_feature); } Some((_, stability, _)) => { - if let Err(reason) = stability.toggle_allowed() { + if let Err(reason) = stability.toggle_allowed( + |flag| sess.opts.target_feature_flag_enabled(flag) + ) { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, enabled: if enable { "enabled" } else { "disabled" }, diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index d8b9bdb55da69..5e8a2b7d2a868 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -64,7 +64,9 @@ pub(crate) fn from_target_feature_attr( // Only allow target features whose feature gates have been enabled // and which are permitted to be toggled. - if let Err(reason) = stability.toggle_allowed() { + if let Err(reason) = stability.toggle_allowed( + |flag| tcx.sess.opts.target_feature_flag_enabled(flag) + ) { tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { span: item.span(), feature, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a301a04580181..5932296d968f3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2495,6 +2495,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches); + Options::fill_target_features_by_flags(&unstable_opts, &mut cg); + let cg = cg; let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b804a5881ccd2..d1fc9a4071df3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -286,6 +286,28 @@ macro_rules! top_level_options { mods.sort_by(|a, b| a.opt.cmp(&b.opt)); mods } + + pub fn target_feature_flag_enabled(&self, flag: &str) -> bool { + match flag { + "x86-retpoline" => self.unstable_opts.x86_retpoline, + _ => false, + } + } + + pub fn fill_target_features_by_flags( + unstable_opts: &UnstableOptions, cg: &mut CodegenOptions + ) { + if unstable_opts.x86_retpoline { + if !cg.target_feature.is_empty() { + cg.target_feature.push(','); + } + cg.target_feature.push_str( + "+retpoline-external-thunk,\ + +retpoline-indirect-branches,\ + +retpoline-indirect-calls" + ); + } + } } ); } @@ -2560,6 +2582,9 @@ written to standard error output)"), "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"), write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], "whether long type names should be written to files instead of being printed in errors"), + x86_retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], + "enable retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \ + target features (default: no)"), // tidy-alphabetical-end // If you add a new option, please update: diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 9fd07c8634aa1..ddabedb7a6a55 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -34,6 +34,9 @@ pub enum Stability { /// particular for features are actually ABI configuration flags (not all targets are as nice as /// RISC-V and have an explicit way to set the ABI separate from target features). Forbidden { reason: &'static str }, + /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set + /// by target modifier flag. Target modifier flags are tracked to be consistent in linked modules. + EnabledByTargetModifierFlag { reason: &'static str, flag: &'static str }, } use Stability::*; @@ -49,6 +52,7 @@ impl HashStable for Stability { Stability::Forbidden { reason } => { reason.hash_stable(hcx, hasher); } + Stability::EnabledByTargetModifierFlag { .. } => {} } } } @@ -74,15 +78,23 @@ impl Stability { Stability::Unstable(nightly_feature) => Some(nightly_feature), Stability::Stable { .. } => None, Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"), + Stability::EnabledByTargetModifierFlag { .. } => None, } } /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`. /// (It might still be nightly-only even if this returns `true`, so make sure to also check /// `requires_nightly`.) - pub fn toggle_allowed(&self) -> Result<(), &'static str> { + pub fn toggle_allowed(&self, flag_enabled: impl Fn(&str) -> bool) -> Result<(), &'static str> { match self { Stability::Forbidden { reason } => Err(reason), + Stability::EnabledByTargetModifierFlag { reason, flag } => { + if !flag_enabled(*flag) { + Err(reason) + } else { + Ok(()) + } + } _ => Ok(()), } } @@ -414,6 +426,18 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("prfchw", Unstable(sym::prfchw_target_feature), &[]), ("rdrand", Stable, &[]), ("rdseed", Stable, &[]), + ("retpoline-external-thunk", Stability::EnabledByTargetModifierFlag { + reason: "use `x86-retpoline` target modifier flag instead", + flag: "x86-retpoline", + }, &[]), + ("retpoline-indirect-branches", Stability::EnabledByTargetModifierFlag { + reason: "use `x86-retpoline` target modifier flag instead", + flag: "x86-retpoline", + }, &[]), + ("retpoline-indirect-calls", Stability::EnabledByTargetModifierFlag { + reason: "use `x86-retpoline` target modifier flag instead", + flag: "x86-retpoline", + }, &[]), ("rtm", Unstable(sym::rtm_target_feature), &[]), ("sha", Stable, &["sse2"]), ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]), diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.by_feature.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature.stderr new file mode 100644 index 0000000000000..e2b6078b7a8c9 --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature.stderr @@ -0,0 +1,7 @@ +warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `x86-retpoline` target modifier flag instead + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/retpoline-target-feature-flag.rs b/tests/ui/target-feature/retpoline-target-feature-flag.rs new file mode 100644 index 0000000000000..76a0536f607fd --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.rs @@ -0,0 +1,14 @@ +//@ revisions: by_flag by_feature +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ [by_flag]compile-flags: -Zx86-retpoline +//@ [by_feature]compile-flags: -Ctarget-feature=+retpoline-external-thunk +//@ [by_flag]build-pass +// For now this is just a warning. +//@ [by_feature]build-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {}