From 597eb26e521428a3980e62cfdef2019c068dfc54 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Wed, 15 Jan 2025 20:43:02 +0700 Subject: [PATCH] -Zretpoline and -Zretpoline-external-thunk flags (target modifiers) 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 | 10 +++++ compiler/rustc_session/src/options.rs | 42 +++++++++++++++++++ compiler/rustc_target/src/target_features.rs | 38 ++++++++++++++++- tests/codegen/retpoline.rs | 29 +++++++++++++ tests/ui/check-cfg/target_feature.stderr | 3 ++ ...line-target-feature-flag.by_feature.stderr | 7 ++++ ...ine-target-feature-flag.by_feature1.stderr | 7 ++++ ...ine-target-feature-flag.by_feature2.stderr | 7 ++++ ...ine-target-feature-flag.by_feature3.stderr | 7 ++++ .../retpoline-target-feature-flag.rs | 19 +++++++++ 13 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 tests/codegen/retpoline.rs 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.by_feature1.stderr create mode 100644 tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr create mode 100644 tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.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 6eae0c24f48ad..b1904e31b7bd8 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -94,7 +94,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 4a166b0872dfd..d2b8f25f24008 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -733,7 +733,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 8058cd1b1783a..5f0464e7b81a1 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 ed336cc559612..33ced94a64bb8 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2531,6 +2531,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches); + // -Zretpoline-external-thunk also requires -Zretpoline + if unstable_opts.retpoline_external_thunk { + unstable_opts.retpoline = true; + target_modifiers.insert( + OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::retpoline), + "true".to_string(), + ); + } + 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 b3be4b611f03f..d3934a14e8493 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -286,6 +286,43 @@ 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 { + "retpoline" => self.unstable_opts.retpoline, + "retpoline-external-thunk" => self.unstable_opts.retpoline_external_thunk, + _ => false, + } + } + + pub fn fill_target_features_by_flags( + unstable_opts: &UnstableOptions, cg: &mut CodegenOptions + ) { + // -Zretpoline without -Zretpoline-external-thunk enables + // retpoline-indirect-branches and retpoline-indirect-calls target features + if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk { + if !cg.target_feature.is_empty() { + cg.target_feature.push(','); + } + cg.target_feature.push_str( + "+retpoline-indirect-branches,\ + +retpoline-indirect-calls" + ); + } + // -Zretpoline-external-thunk (maybe, with -Zretpoline too) enables + // retpoline-external-thunk, retpoline-indirect-branches and + // retpoline-indirect-calls target features + if unstable_opts.retpoline_external_thunk { + if !cg.target_feature.is_empty() { + cg.target_feature.push(','); + } + cg.target_feature.push_str( + "+retpoline-external-thunk,\ + +retpoline-indirect-branches,\ + +retpoline-indirect-calls" + ); + } + } } ); } @@ -2423,6 +2460,11 @@ options! { remark_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "directory into which to write optimization remarks (if not specified, they will be \ written to standard error output)"), + retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], + "enables retpoline-indirect-branches and retpoline-indirect-calls target features (default: no)"), + retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], + "enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \ + target features (default: no)"), sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED], "use a sanitizer"), sanitizer_cfi_canonical_jump_tables: Option = (Some(true), parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index a96caf227f747..f76eb60b0dec1 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(()), } } @@ -423,6 +435,30 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("prfchw", Unstable(sym::prfchw_target_feature), &[]), ("rdrand", Stable, &[]), ("rdseed", Stable, &[]), + ( + "retpoline-external-thunk", + Stability::EnabledByTargetModifierFlag { + reason: "use `retpoline-external-thunk` target modifier flag instead", + flag: "retpoline-external-thunk", + }, + &[], + ), + ( + "retpoline-indirect-branches", + Stability::EnabledByTargetModifierFlag { + reason: "use `retpoline` target modifier flag instead", + flag: "retpoline", + }, + &[], + ), + ( + "retpoline-indirect-calls", + Stability::EnabledByTargetModifierFlag { + reason: "use `retpoline` target modifier flag instead", + flag: "retpoline", + }, + &[], + ), ("rtm", Unstable(sym::rtm_target_feature), &[]), ("sha", Stable, &["sse2"]), ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]), diff --git a/tests/codegen/retpoline.rs b/tests/codegen/retpoline.rs new file mode 100644 index 0000000000000..30fdd9c2db2c0 --- /dev/null +++ b/tests/codegen/retpoline.rs @@ -0,0 +1,29 @@ +// ignore-tidy-linelength +// Test that the +// `retpoline-external-thunk`, `retpoline-indirect-branches`, `retpoline-indirect-calls` +// target features are (not) emitted when the `retpoline/retpoline-external-thunk` flag is (not) set. + +//@ revisions: disabled enabled_retpoline enabled_retpoline_external_thunk +//@ needs-llvm-components: x86 +//@ compile-flags: --target x86_64-unknown-linux-gnu +//@ [enabled_retpoline] compile-flags: -Zretpoline +//@ [enabled_retpoline_external_thunk] compile-flags: -Zretpoline-external-thunk + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk{{.*}} } + // disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches{{.*}} } + // disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-calls{{.*}} } + + // enabled_retpoline: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} } + // enabled_retpoline_external_thunk: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk,+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} } +} diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index a9d67481ba15b..597c4882651b4 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -192,6 +192,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `relax` `relaxed-simd` `reserve-x18` +`retpoline-external-thunk` +`retpoline-indirect-branches` +`retpoline-indirect-calls` `rtm` `sb` `scq` 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.by_feature1.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr new file mode 100644 index 0000000000000..2a0f5f01aef6f --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature1.stderr @@ -0,0 +1,7 @@ +warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` 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.by_feature2.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr new file mode 100644 index 0000000000000..f7b6cb1644778 --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature2.stderr @@ -0,0 +1,7 @@ +warning: target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `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.by_feature3.stderr b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr new file mode 100644 index 0000000000000..4f2cd1d1a522f --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.by_feature3.stderr @@ -0,0 +1,7 @@ +warning: target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `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..d3b0ce67944be --- /dev/null +++ b/tests/ui/target-feature/retpoline-target-feature-flag.rs @@ -0,0 +1,19 @@ +//@ revisions: by_flag by_feature1 by_feature2 by_feature3 +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ [by_flag]compile-flags: -Zretpoline + +//@ [by_feature1]compile-flags: -Ctarget-feature=+retpoline-external-thunk +//@ [by_feature2]compile-flags: -Ctarget-feature=+retpoline-indirect-branches +//@ [by_feature3]compile-flags: -Ctarget-feature=+retpoline-indirect-calls +//@ [by_flag]build-pass +// For now this is just a warning. +//@ [by_feature1]build-pass +//@ [by_feature2]build-pass +//@ [by_feature3]build-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {}