Skip to content

Commit b6ecdc1

Browse files
committed
-Zretpoline and -Zretpoline-external-thunk flags (target modifiers) to enable retpoline-related target features
1 parent b105556 commit b6ecdc1

16 files changed

+193
-15
lines changed

compiler/rustc_codegen_gcc/src/gcc_util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_data_structures::unord::UnordSet;
77
use rustc_session::Session;
8+
use rustc_session::features::StabilityExt;
89
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
910
use smallvec::{SmallVec, smallvec};
1011

@@ -94,7 +95,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
9495
sess.dcx().emit_warn(unknown_feature);
9596
}
9697
Some(&(_, stability, _)) => {
97-
if let Err(reason) = stability.toggle_allowed() {
98+
if let Err(reason) = stability.is_toggle_permitted(sess) {
9899
sess.dcx().emit_warn(ForbiddenCTargetFeature {
99100
feature,
100101
enabled: if enable { "enabled" } else { "disabled" },

compiler/rustc_codegen_llvm/src/llvm_util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_fs_util::path_to_c_string;
1616
use rustc_middle::bug;
1717
use rustc_session::Session;
1818
use rustc_session::config::{PrintKind, PrintRequest};
19+
use rustc_session::features::StabilityExt;
1920
use rustc_span::Symbol;
2021
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
2122
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
@@ -832,7 +833,7 @@ pub(crate) fn global_llvm_features(
832833
sess.dcx().emit_warn(unknown_feature);
833834
}
834835
Some((_, stability, _)) => {
835-
if let Err(reason) = stability.toggle_allowed() {
836+
if let Err(reason) = stability.is_toggle_permitted(sess) {
836837
sess.dcx().emit_warn(ForbiddenCTargetFeature {
837838
feature,
838839
enabled: if enable { "enabled" } else { "disabled" },

compiler/rustc_codegen_ssa/src/target_features.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
88
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
99
use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
11+
use rustc_session::features::StabilityExt;
1112
use rustc_session::parse::feature_err;
1213
use rustc_span::{Span, Symbol, sym};
1314
use rustc_target::target_features::{self, Stability};
@@ -64,7 +65,7 @@ pub(crate) fn from_target_feature_attr(
6465

6566
// Only allow target features whose feature gates have been enabled
6667
// and which are permitted to be toggled.
67-
if let Err(reason) = stability.toggle_allowed() {
68+
if let Err(reason) = stability.is_toggle_permitted(tcx.sess) {
6869
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
6970
span: item.span(),
7071
feature,

compiler/rustc_session/src/config.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2649,6 +2649,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26492649

26502650
let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
26512651

2652+
// -Zretpoline-external-thunk also requires -Zretpoline
2653+
if unstable_opts.retpoline_external_thunk {
2654+
unstable_opts.retpoline = true;
2655+
target_modifiers.insert(
2656+
OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::retpoline),
2657+
"true".to_string(),
2658+
);
2659+
}
2660+
Options::fill_target_features_by_flags(&unstable_opts, &mut cg);
2661+
26522662
let cg = cg;
26532663

26542664
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use rustc_target::target_features::Stability;
2+
3+
use crate::Session;
4+
5+
pub trait StabilityExt {
6+
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
7+
/// Otherwise, some features also may only be enabled by flag (target modifier).
8+
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
9+
/// `requires_nightly`.)
10+
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str>;
11+
}
12+
13+
impl StabilityExt for Stability {
14+
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str> {
15+
match self {
16+
Stability::Forbidden { reason } => Err(reason),
17+
Stability::TargetModifierOnly { reason, flag } => {
18+
if !sess.opts.target_feature_flag_enabled(*flag) { Err(reason) } else { Ok(()) }
19+
}
20+
_ => Ok(()),
21+
}
22+
}
23+
}

compiler/rustc_session/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use session::*;
3030
pub mod output;
3131

3232
pub use getopts;
33+
pub mod features;
3334

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

compiler/rustc_session/src/options.rs

+42
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,43 @@ macro_rules! top_level_options {
290290
mods.sort_by(|a, b| a.opt.cmp(&b.opt));
291291
mods
292292
}
293+
294+
pub fn target_feature_flag_enabled(&self, flag: &str) -> bool {
295+
match flag {
296+
"retpoline" => self.unstable_opts.retpoline,
297+
"retpoline-external-thunk" => self.unstable_opts.retpoline_external_thunk,
298+
_ => false,
299+
}
300+
}
301+
302+
pub fn fill_target_features_by_flags(
303+
unstable_opts: &UnstableOptions, cg: &mut CodegenOptions
304+
) {
305+
// -Zretpoline without -Zretpoline-external-thunk enables
306+
// retpoline-indirect-branches and retpoline-indirect-calls target features
307+
if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk {
308+
if !cg.target_feature.is_empty() {
309+
cg.target_feature.push(',');
310+
}
311+
cg.target_feature.push_str(
312+
"+retpoline-indirect-branches,\
313+
+retpoline-indirect-calls"
314+
);
315+
}
316+
// -Zretpoline-external-thunk (maybe, with -Zretpoline too) enables
317+
// retpoline-external-thunk, retpoline-indirect-branches and
318+
// retpoline-indirect-calls target features
319+
if unstable_opts.retpoline_external_thunk {
320+
if !cg.target_feature.is_empty() {
321+
cg.target_feature.push(',');
322+
}
323+
cg.target_feature.push_str(
324+
"+retpoline-external-thunk,\
325+
+retpoline-indirect-branches,\
326+
+retpoline-indirect-calls"
327+
);
328+
}
329+
}
293330
}
294331
);
295332
}
@@ -2446,6 +2483,11 @@ options! {
24462483
remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
24472484
"directory into which to write optimization remarks (if not specified, they will be \
24482485
written to standard error output)"),
2486+
retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2487+
"enables retpoline-indirect-branches and retpoline-indirect-calls target features (default: no)"),
2488+
retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
2489+
"enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \
2490+
target features (default: no)"),
24492491
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
24502492
"use a sanitizer"),
24512493
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],

compiler/rustc_target/src/target_features.rs

+29-10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub enum Stability {
3434
/// particular for features are actually ABI configuration flags (not all targets are as nice as
3535
/// RISC-V and have an explicit way to set the ABI separate from target features).
3636
Forbidden { reason: &'static str },
37+
/// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set
38+
/// by target modifier flag. Target modifier flags are tracked to be consistent in linked modules.
39+
TargetModifierOnly { reason: &'static str, flag: &'static str },
3740
}
3841
use Stability::*;
3942

@@ -49,6 +52,7 @@ impl<CTX> HashStable<CTX> for Stability {
4952
Stability::Forbidden { reason } => {
5053
reason.hash_stable(hcx, hasher);
5154
}
55+
Stability::TargetModifierOnly { .. } => {}
5256
}
5357
}
5458
}
@@ -74,16 +78,7 @@ impl Stability {
7478
Stability::Unstable(nightly_feature) => Some(nightly_feature),
7579
Stability::Stable { .. } => None,
7680
Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
77-
}
78-
}
79-
80-
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
81-
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
82-
/// `requires_nightly`.)
83-
pub fn toggle_allowed(&self) -> Result<(), &'static str> {
84-
match self {
85-
Stability::Forbidden { reason } => Err(reason),
86-
_ => Ok(()),
81+
Stability::TargetModifierOnly { .. } => None,
8782
}
8883
}
8984
}
@@ -453,6 +448,30 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
453448
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
454449
("rdrand", Stable, &[]),
455450
("rdseed", Stable, &[]),
451+
(
452+
"retpoline-external-thunk",
453+
Stability::TargetModifierOnly {
454+
reason: "use `retpoline-external-thunk` target modifier flag instead",
455+
flag: "retpoline-external-thunk",
456+
},
457+
&[],
458+
),
459+
(
460+
"retpoline-indirect-branches",
461+
Stability::TargetModifierOnly {
462+
reason: "use `retpoline` target modifier flag instead",
463+
flag: "retpoline",
464+
},
465+
&[],
466+
),
467+
(
468+
"retpoline-indirect-calls",
469+
Stability::TargetModifierOnly {
470+
reason: "use `retpoline` target modifier flag instead",
471+
flag: "retpoline",
472+
},
473+
&[],
474+
),
456475
("rtm", Unstable(sym::rtm_target_feature), &[]),
457476
("sha", Stable, &["sse2"]),
458477
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),

src/librustdoc/json/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_data_structures::fx::FxHashSet;
1818
use rustc_hir::def_id::{DefId, DefIdSet};
1919
use rustc_middle::ty::TyCtxt;
2020
use rustc_session::Session;
21+
use rustc_session::features::StabilityExt;
2122
use rustc_span::def_id::LOCAL_CRATE;
2223
use rustdoc_json_types as types;
2324
// It's important to use the FxHashMap from rustdoc_json_types here, instead of
@@ -148,7 +149,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
148149
.copied()
149150
.filter(|(_, stability, _)| {
150151
// Describe only target features which the user can toggle
151-
stability.toggle_allowed().is_ok()
152+
stability.is_toggle_permitted(sess).is_ok()
152153
})
153154
.map(|(name, stability, implied_features)| {
154155
types::TargetFeature {
@@ -164,7 +165,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
164165
// Imply only target features which the user can toggle
165166
feature_stability
166167
.get(name)
167-
.map(|stability| stability.toggle_allowed().is_ok())
168+
.map(|stability| stability.is_toggle_permitted(sess).is_ok())
168169
.unwrap_or(false)
169170
})
170171
.map(String::from)

tests/codegen/retpoline.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// ignore-tidy-linelength
2+
// Test that the
3+
// `retpoline-external-thunk`, `retpoline-indirect-branches`, `retpoline-indirect-calls`
4+
// target features are (not) emitted when the `retpoline/retpoline-external-thunk` flag is (not) set.
5+
6+
//@ revisions: disabled enabled_retpoline enabled_retpoline_external_thunk
7+
//@ needs-llvm-components: x86
8+
//@ compile-flags: --target x86_64-unknown-linux-gnu
9+
//@ [enabled_retpoline] compile-flags: -Zretpoline
10+
//@ [enabled_retpoline_external_thunk] compile-flags: -Zretpoline-external-thunk
11+
12+
#![crate_type = "lib"]
13+
#![feature(no_core, lang_items)]
14+
#![no_core]
15+
16+
#[lang = "sized"]
17+
trait Sized {}
18+
19+
#[no_mangle]
20+
pub fn foo() {
21+
// CHECK: @foo() unnamed_addr #0
22+
23+
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk{{.*}} }
24+
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches{{.*}} }
25+
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-calls{{.*}} }
26+
27+
// enabled_retpoline: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} }
28+
// enabled_retpoline_external_thunk: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk,+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} }
29+
}

tests/ui/check-cfg/target_feature.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
202202
`relax`
203203
`relaxed-simd`
204204
`reserve-x18`
205+
`retpoline-external-thunk`
206+
`retpoline-indirect-branches`
207+
`retpoline-indirect-calls`
205208
`rtm`
206209
`sb`
207210
`scq`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `x86-retpoline` target modifier flag instead
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: 1 warning emitted
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` target modifier flag instead
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: 1 warning emitted
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
warning: target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: 1 warning emitted
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
warning: target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: 1 warning emitted
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ revisions: by_flag by_feature1 by_feature2 by_feature3
2+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
3+
//@ needs-llvm-components: x86
4+
//@ [by_flag]compile-flags: -Zretpoline
5+
6+
//@ [by_feature1]compile-flags: -Ctarget-feature=+retpoline-external-thunk
7+
//@ [by_feature2]compile-flags: -Ctarget-feature=+retpoline-indirect-branches
8+
//@ [by_feature3]compile-flags: -Ctarget-feature=+retpoline-indirect-calls
9+
//@ [by_flag]build-pass
10+
// For now this is just a warning.
11+
//@ [by_feature1]build-pass
12+
//@ [by_feature2]build-pass
13+
//@ [by_feature3]build-pass
14+
#![feature(no_core, lang_items)]
15+
#![no_std]
16+
#![no_core]
17+
18+
#[lang = "sized"]
19+
pub trait Sized {}

0 commit comments

Comments
 (0)