Skip to content

retpoline and retpoline-external-thunk flags (target modifiers) to enable retpoline-related target features #135927

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions compiler/rustc_codegen_gcc/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ codegen_gcc_unknown_ctarget_feature_prefix =
unknown feature specified for `-Ctarget-feature`: `{$feature}`
.note = features must begin with a `+` to enable or `-` to disable it

codegen_gcc_forbidden_ctarget_feature =
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}

codegen_gcc_unwinding_inline_asm =
GCC backend does not support unwinding from inline asm

Expand All @@ -26,10 +23,6 @@ codegen_gcc_unknown_ctarget_feature =
.possible_feature = you might have meant: `{$rust_feature}`
.consider_filing_feature_request = consider filing a feature request

codegen_gcc_unstable_ctarget_feature =
unstable feature specified for `-Ctarget-feature`: `{$feature}`
.note = this feature is not stably supported; its behavior can change in the future

codegen_gcc_missing_features =
add the missing features in a `target_feature` attribute

Expand Down
15 changes: 0 additions & 15 deletions compiler/rustc_codegen_gcc/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,6 @@ pub(crate) struct UnknownCTargetFeature<'a> {
pub rust_feature: PossibleFeature<'a>,
}

#[derive(Diagnostic)]
#[diag(codegen_gcc_unstable_ctarget_feature)]
#[note]
pub(crate) struct UnstableCTargetFeature<'a> {
pub feature: &'a str,
}

#[derive(Diagnostic)]
#[diag(codegen_gcc_forbidden_ctarget_feature)]
pub(crate) struct ForbiddenCTargetFeature<'a> {
pub feature: &'a str,
pub enabled: &'a str,
pub reason: &'a str,
}

#[derive(Subdiagnostic)]
pub(crate) enum PossibleFeature<'a> {
#[help(codegen_gcc_possible_feature)]
Expand Down
27 changes: 10 additions & 17 deletions compiler/rustc_codegen_gcc/src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_session::Session;
use rustc_session::features::{StabilityExt, retpoline_features_by_flags};
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
use smallvec::{SmallVec, smallvec};

use crate::errors::{
ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
UnstableCTargetFeature,
};
use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};

fn gcc_features_by_flags(sess: &Session) -> Vec<&str> {
let mut features: Vec<&str> = Vec::new();
retpoline_features_by_flags(sess, &mut features);
features
}

/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
Expand Down Expand Up @@ -45,7 +49,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri

// Compute implied features
let mut all_rust_features = vec![];
for feature in sess.opts.cg.target_feature.split(',') {
for feature in sess.opts.cg.target_feature.split(',').chain(gcc_features_by_flags(sess)) {
if let Some(feature) = feature.strip_prefix('+') {
all_rust_features.extend(
UnordSet::from(sess.target.implied_target_features(feature))
Expand Down Expand Up @@ -94,18 +98,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
sess.dcx().emit_warn(unknown_feature);
}
Some(&(_, stability, _)) => {
if let Err(reason) = stability.toggle_allowed() {
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: if enable { "enabled" } else { "disabled" },
reason,
});
} else if stability.requires_nightly().is_some() {
// An unstable feature. Warn about using it. (It makes little sense
// to hard-error here since we just warn about fully unknown
// features above).
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
}
stability.verify_feature_enabled_by_flag(sess, enable, feature);
}
}

Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_codegen_llvm/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ codegen_llvm_dynamic_linking_with_lto =

codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture

codegen_llvm_forbidden_ctarget_feature =
target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
codegen_llvm_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

codegen_llvm_from_llvm_diag = {$message}

codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
Expand Down Expand Up @@ -76,10 +71,6 @@ codegen_llvm_unknown_ctarget_feature_prefix =

codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo

codegen_llvm_unstable_ctarget_feature =
unstable feature specified for `-Ctarget-feature`: `{$feature}`
.note = this feature is not stably supported; its behavior can change in the future

codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}

codegen_llvm_write_ir = failed to write LLVM IR to {$path}
Expand Down
17 changes: 0 additions & 17 deletions compiler/rustc_codegen_llvm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@ pub(crate) struct UnknownCTargetFeature<'a> {
pub rust_feature: PossibleFeature<'a>,
}

#[derive(Diagnostic)]
#[diag(codegen_llvm_unstable_ctarget_feature)]
#[note]
pub(crate) struct UnstableCTargetFeature<'a> {
pub feature: &'a str,
}

#[derive(Diagnostic)]
#[diag(codegen_llvm_forbidden_ctarget_feature)]
#[note]
#[note(codegen_llvm_forbidden_ctarget_feature_issue)]
pub(crate) struct ForbiddenCTargetFeature<'a> {
pub feature: &'a str,
pub enabled: &'a str,
pub reason: &'a str,
}

#[derive(Subdiagnostic)]
pub(crate) enum PossibleFeature<'a> {
#[help(codegen_llvm_possible_feature)]
Expand Down
25 changes: 10 additions & 15 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ use rustc_fs_util::path_to_c_string;
use rustc_middle::bug;
use rustc_session::Session;
use rustc_session::config::{PrintKind, PrintRequest};
use rustc_session::features::{StabilityExt, retpoline_features_by_flags};
use rustc_span::Symbol;
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
use smallvec::{SmallVec, smallvec};

use crate::back::write::create_informational_target_machine;
use crate::errors::{
FixedX18InvalidArch, ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature,
UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
FixedX18InvalidArch, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
};
use crate::llvm;

Expand Down Expand Up @@ -707,6 +707,12 @@ pub(crate) fn target_cpu(sess: &Session) -> &str {
handle_native(cpu_name)
}

fn llvm_features_by_flags(sess: &Session) -> Vec<&str> {
let mut features: Vec<&str> = Vec::new();
retpoline_features_by_flags(sess, &mut features);
features
}

/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
pub(crate) fn global_llvm_features(
Expand Down Expand Up @@ -787,7 +793,7 @@ pub(crate) fn global_llvm_features(

// Compute implied features
let mut all_rust_features = vec![];
for feature in sess.opts.cg.target_feature.split(',') {
for feature in sess.opts.cg.target_feature.split(',').chain(llvm_features_by_flags(sess)) {
if let Some(feature) = feature.strip_prefix('+') {
all_rust_features.extend(
UnordSet::from(sess.target.implied_target_features(feature))
Expand Down Expand Up @@ -840,18 +846,7 @@ pub(crate) fn global_llvm_features(
sess.dcx().emit_warn(unknown_feature);
}
Some((_, stability, _)) => {
if let Err(reason) = stability.toggle_allowed() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bunch of duplication in the code around this between codegen backends and rustc_codegen_ssa, it's pre-existing, you could sort it if you wanted, but someone ought to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into StabilityExt::verify_feature_enabled_by_flag

sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: if enable { "enabled" } else { "disabled" },
reason,
});
} else if stability.requires_nightly().is_some() {
// An unstable feature. Warn about using it. It makes little sense
// to hard-error here since we just warn about fully unknown
// features above.
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
}
stability.verify_feature_enabled_by_flag(sess, enable, feature);
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::features::StabilityExt;
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
Expand Down Expand Up @@ -66,7 +67,7 @@ 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.is_toggle_permitted(tcx.sess) {
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
span: item.span(),
feature,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_session/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ session_file_is_not_writeable = output file {$file} is not writeable -- check it

session_file_write_fail = failed to write `{$path}` due to error `{$err}`

session_forbidden_ctarget_feature =
target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
session_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>

session_function_return_requires_x86_or_x86_64 = `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64

session_function_return_thunk_extern_requires_non_large_code_model = `-Zfunction-return=thunk-extern` is only supported on non-large code models
Expand Down Expand Up @@ -132,6 +137,9 @@ session_target_stack_protector_not_supported = `-Z stack-protector={$stack_prote
session_unleashed_feature_help_named = skipping check for `{$gate}` feature
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate

session_unstable_ctarget_feature =
unstable feature specified for `-Ctarget-feature`: `{$feature}`
.note = this feature is not stably supported; its behavior can change in the future
session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`

session_unsupported_crate_type_for_target =
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,15 @@ 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(),
);
}

let cg = cg;

let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_session/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,20 @@ pub(crate) struct SoftFloatIgnored;
#[note]
#[note(session_soft_float_deprecated_issue)]
pub(crate) struct SoftFloatDeprecated;

#[derive(Diagnostic)]
#[diag(session_forbidden_ctarget_feature)]
#[note]
#[note(session_forbidden_ctarget_feature_issue)]
pub(crate) struct ForbiddenCTargetFeature<'a> {
pub feature: &'a str,
pub enabled: &'a str,
pub reason: &'a str,
}

#[derive(Diagnostic)]
#[diag(session_unstable_ctarget_feature)]
#[note]
pub(crate) struct UnstableCTargetFeature<'a> {
pub feature: &'a str,
}
59 changes: 59 additions & 0 deletions compiler/rustc_session/src/features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use rustc_target::target_features::Stability;

use crate::Session;
use crate::errors::{ForbiddenCTargetFeature, UnstableCTargetFeature};

pub trait StabilityExt {
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
/// Otherwise, some features also may only be enabled by flag (target modifier).
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
/// `requires_nightly`.)
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str>;

/// Check that feature is correctly enabled/disabled by command line flag (emits warnings)
fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str);
}

impl StabilityExt for Stability {
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str> {
match self {
Stability::Forbidden { reason } => Err(reason),
Stability::TargetModifierOnly { reason, flag } => {
if !sess.opts.target_feature_flag_enabled(*flag) { Err(reason) } else { Ok(()) }
}
_ => Ok(()),
}
}
fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str) {
if let Err(reason) = self.is_toggle_permitted(sess) {
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: if enable { "enabled" } else { "disabled" },
reason,
});
} else if self.requires_nightly().is_some() {
// An unstable feature. Warn about using it. It makes little sense
// to hard-error here since we just warn about fully unknown
// features above.
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
}
}
}

pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec<&str>) {
// -Zretpoline without -Zretpoline-external-thunk enables
// retpoline-indirect-branches and retpoline-indirect-calls target features
let unstable_opts = &sess.opts.unstable_opts;
if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk {
features.push("+retpoline-indirect-branches");
features.push("+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 {
features.push("+retpoline-external-thunk");
features.push("+retpoline-indirect-branches");
features.push("+retpoline-indirect-calls");
}
}
1 change: 1 addition & 0 deletions compiler/rustc_session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub use session::*;
pub mod output;

pub use getopts;
pub mod features;

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ 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,
}
}
}
);
}
Expand Down Expand Up @@ -2446,6 +2454,11 @@ options! {
remark_dir: Option<PathBuf> = (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<bool> = (Some(true), parse_opt_bool, [TRACKED],
Expand Down
Loading
Loading