Skip to content

Commit 4843153

Browse files
committed
mark some target features as 'forbidden' so they cannot be (un)set
For now, this is just a warning, but should become a hard error in the future
1 parent 9f20eb7 commit 4843153

File tree

4 files changed

+64
-28
lines changed

4 files changed

+64
-28
lines changed

messages.ftl

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ codegen_gcc_invalid_minimum_alignment =
88
codegen_gcc_lto_not_supported =
99
LTO is not supported. You may get a linker error.
1010
11+
codegen_gcc_forbidden_ctarget_feature =
12+
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
13+
1114
codegen_gcc_unwinding_inline_asm =
1215
GCC backend does not support unwinding from inline asm
1316
@@ -24,11 +27,15 @@ codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdyl
2427
codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})
2528
2629
codegen_gcc_unknown_ctarget_feature =
27-
unknown feature specified for `-Ctarget-feature`: `{$feature}`
28-
.note = it is still passed through to the codegen backend
30+
unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`
31+
.note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
2932
.possible_feature = you might have meant: `{$rust_feature}`
3033
.consider_filing_feature_request = consider filing a feature request
3134
35+
codegen_gcc_unstable_ctarget_feature =
36+
unstable feature specified for `-Ctarget-feature`: `{$feature}`
37+
.note = this feature is not stably supported; its behavior can change in the future
38+
3239
codegen_gcc_missing_features =
3340
add the missing features in a `target_feature` attribute
3441

src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ pub(crate) struct UnknownCTargetFeature<'a> {
1717
pub rust_feature: PossibleFeature<'a>,
1818
}
1919

20+
#[derive(Diagnostic)]
21+
#[diag(codegen_gcc_unstable_ctarget_feature)]
22+
#[note]
23+
pub(crate) struct UnstableCTargetFeature<'a> {
24+
pub feature: &'a str,
25+
}
26+
27+
#[derive(Diagnostic)]
28+
#[diag(codegen_gcc_forbidden_ctarget_feature)]
29+
pub(crate) struct ForbiddenCTargetFeature<'a> {
30+
pub feature: &'a str,
31+
}
32+
2033
#[derive(Subdiagnostic)]
2134
pub(crate) enum PossibleFeature<'a> {
2235
#[help(codegen_gcc_possible_feature)]

src/gcc_util.rs

+40-25
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_middle::bug;
77
use rustc_session::Session;
8-
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
8+
use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
99
use smallvec::{SmallVec, smallvec};
1010

11-
use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
11+
use crate::errors::{
12+
ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
13+
UnstableCTargetFeature,
14+
};
1215

1316
/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
1417
/// `--target` and similar).
@@ -43,7 +46,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
4346
);
4447

4548
// -Ctarget-features
46-
let supported_features = sess.target.supported_target_features();
49+
let known_features = sess.target.rust_target_features();
4750
let mut featsmap = FxHashMap::default();
4851
let feats = sess
4952
.opts
@@ -62,37 +65,49 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
6265
}
6366
};
6467

68+
// Get the backend feature name, if any.
69+
// This excludes rustc-specific features, that do not get passed down to GCC.
6570
let feature = backend_feature_name(s)?;
6671
// Warn against use of GCC specific feature names on the CLI.
67-
if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) {
68-
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| {
69-
let gcc_features = to_gcc_features(sess, rust_feature);
70-
if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
71-
Some(rust_feature)
72-
} else {
73-
None
72+
if diagnostics {
73+
let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
74+
match feature_state {
75+
None => {
76+
let rust_feature =
77+
known_features.iter().find_map(|&(rust_feature, _, _)| {
78+
let gcc_features = to_gcc_features(sess, rust_feature);
79+
if gcc_features.contains(&feature)
80+
&& !gcc_features.contains(&rust_feature)
81+
{
82+
Some(rust_feature)
83+
} else {
84+
None
85+
}
86+
});
87+
let unknown_feature = if let Some(rust_feature) = rust_feature {
88+
UnknownCTargetFeature {
89+
feature,
90+
rust_feature: PossibleFeature::Some { rust_feature },
91+
}
92+
} else {
93+
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
94+
};
95+
sess.dcx().emit_warn(unknown_feature);
7496
}
75-
});
76-
let unknown_feature = if let Some(rust_feature) = rust_feature {
77-
UnknownCTargetFeature {
78-
feature,
79-
rust_feature: PossibleFeature::Some { rust_feature },
97+
Some((_, Stability::Stable, _)) => {}
98+
Some((_, Stability::Unstable(_), _)) => {
99+
// An unstable feature. Warn about using it.
100+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
80101
}
81-
} else {
82-
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
83-
};
84-
sess.dcx().emit_warn(unknown_feature);
85-
}
102+
Some((_, Stability::Forbidden { .. }, _)) => {
103+
sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
104+
}
105+
}
86106

87-
if diagnostics {
88107
// FIXME(nagisa): figure out how to not allocate a full hashset here.
89108
featsmap.insert(feature, enable_disable == '+');
90109
}
91110

92-
// rustc-specific features do not get passed down to GCC…
93-
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
94-
return None;
95-
}
96111
// ... otherwise though we run through `to_gcc_features` when
97112
// passing requests down to GCC. This means that all in-language
98113
// features also work on the command line instead of having two

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,9 @@ pub fn target_features(
491491
) -> Vec<Symbol> {
492492
// TODO(antoyo): use global_gcc_features.
493493
sess.target
494-
.supported_target_features()
494+
.rust_target_features()
495495
.iter()
496+
.filter(|(_, gate, _)| gate.is_supported())
496497
.filter_map(|&(feature, gate, _)| {
497498
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
498499
Some(feature)

0 commit comments

Comments
 (0)