Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 648e5e1

Browse files
committedSep 2, 2024
mark some target features as 'forbidden' so they cannot be (un)set
1 parent 9b82580 commit 648e5e1

17 files changed

+279
-128
lines changed
 

‎compiler/rustc_codegen_llvm/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ codegen_llvm_dynamic_linking_with_lto =
77
88
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
99
10+
codegen_llvm_forbidden_ctarget_feature =
11+
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
12+
1013
codegen_llvm_from_llvm_diag = {$message}
1114
1215
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}

‎compiler/rustc_codegen_llvm/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ pub(crate) struct UnstableCTargetFeature<'a> {
3131
pub feature: &'a str,
3232
}
3333

34+
#[derive(Diagnostic)]
35+
#[diag(codegen_llvm_forbidden_ctarget_feature)]
36+
pub(crate) struct ForbiddenCTargetFeature<'a> {
37+
pub feature: &'a str,
38+
}
39+
3440
#[derive(Subdiagnostic)]
3541
pub(crate) enum PossibleFeature<'a> {
3642
#[help(codegen_llvm_possible_feature)]

‎compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ use rustc_session::config::{PrintKind, PrintRequest};
1515
use rustc_session::Session;
1616
use rustc_span::symbol::Symbol;
1717
use rustc_target::spec::{MergeFunctions, PanicStrategy};
18-
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
18+
use rustc_target::target_features::{Stability, RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
1919

2020
use crate::back::write::create_informational_target_machine;
2121
use crate::errors::{
22-
FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable,
23-
UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
22+
FixedX18InvalidArch, ForbiddenCTargetFeature, InvalidTargetFeaturePrefix, PossibleFeature,
23+
TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
24+
UnstableCTargetFeature,
2425
};
2526
use crate::llvm;
2627

@@ -298,11 +299,17 @@ pub(crate) fn check_tied_features(
298299
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
299300
let mut features = vec![];
300301

301-
// Add base features for the target
302+
// Add base features for the target.
303+
// We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
304+
// The reaosn is that if LLVM considers a feature implied but we do not, we don't want that to
305+
// show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of
306+
// the target CPU, that is still expanded to target features (with all their implied features) by
307+
// LLVM.
302308
let target_machine = create_informational_target_machine(sess, true);
309+
// Compute which of the known target features are enables in the 'base' target machine.
303310
features.extend(
304311
sess.target
305-
.supported_target_features()
312+
.known_target_features()
306313
.iter()
307314
.filter(|(feature, _, _)| {
308315
// skip checking special features, as LLVM may not understands them
@@ -344,7 +351,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
344351

345352
// Filter enabled features based on feature gates
346353
sess.target
347-
.supported_target_features()
354+
.known_target_features()
348355
.iter()
349356
.filter_map(|&(feature, gate, _)| {
350357
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
@@ -407,9 +414,13 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
407414
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
408415
let mut rustc_target_features = sess
409416
.target
410-
.supported_target_features()
417+
.known_target_features()
411418
.iter()
412-
.filter_map(|(feature, _gate, _implied)| {
419+
.filter_map(|(feature, gate, _implied)| {
420+
if matches!(gate, Stability::Forbidden) {
421+
// Do not list forbidden features.
422+
return None;
423+
}
413424
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
414425
let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name;
415426
let desc =
@@ -576,7 +587,7 @@ pub(crate) fn global_llvm_features(
576587

577588
// -Ctarget-features
578589
if !only_base_features {
579-
let supported_features = sess.target.supported_target_features();
590+
let known_features = sess.target.known_target_features();
580591
let (llvm_major, _, _) = get_version();
581592
let mut featsmap = FxHashMap::default();
582593

@@ -614,37 +625,43 @@ pub(crate) fn global_llvm_features(
614625
let feature = backend_feature_name(sess, s)?;
615626
// Warn against use of LLVM specific feature names and unstable features on the CLI.
616627
if diagnostics {
617-
let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
618-
if feature_state.is_none() {
619-
let rust_feature =
620-
supported_features.iter().find_map(|&(rust_feature, _, _)| {
621-
let llvm_features = to_llvm_features(sess, rust_feature)?;
622-
if llvm_features.contains(feature)
623-
&& !llvm_features.contains(rust_feature)
624-
{
625-
Some(rust_feature)
626-
} else {
627-
None
628+
let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
629+
match feature_state {
630+
None => {
631+
let rust_feature =
632+
known_features.iter().find_map(|&(rust_feature, _, _)| {
633+
let llvm_features = to_llvm_features(sess, rust_feature)?;
634+
if llvm_features.contains(feature)
635+
&& !llvm_features.contains(rust_feature)
636+
{
637+
Some(rust_feature)
638+
} else {
639+
None
640+
}
641+
});
642+
let unknown_feature = if let Some(rust_feature) = rust_feature {
643+
UnknownCTargetFeature {
644+
feature,
645+
rust_feature: PossibleFeature::Some { rust_feature },
628646
}
629-
});
630-
let unknown_feature = if let Some(rust_feature) = rust_feature {
631-
UnknownCTargetFeature {
632-
feature,
633-
rust_feature: PossibleFeature::Some { rust_feature },
634-
}
635-
} else {
636-
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
637-
};
638-
sess.dcx().emit_warn(unknown_feature);
639-
} else if feature_state
640-
.is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
641-
{
642-
// An unstable feature. Warn about using it.
643-
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
647+
} else {
648+
UnknownCTargetFeature {
649+
feature,
650+
rust_feature: PossibleFeature::None,
651+
}
652+
};
653+
sess.dcx().emit_warn(unknown_feature);
654+
}
655+
Some((_, Stability::Stable, _)) => {}
656+
Some((_, Stability::Unstable(_), _)) => {
657+
// An unstable feature. Warn about using it.
658+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
659+
}
660+
Some((_, Stability::Forbidden, _)) => {
661+
sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
662+
}
644663
}
645-
}
646664

647-
if diagnostics {
648665
// FIXME(nagisa): figure out how to not allocate a full hashset here.
649666
featsmap.insert(feature, enable_disable == '+');
650667
}

‎compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error}
5858
5959
codegen_ssa_field_associated_value_expected = associated value expected for `{$name}`
6060
61+
codegen_ssa_forbidden_target_feature =
62+
target feature `{$feature}` cannot be toggled with `#[target_feature]`
63+
6164
codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
6265
6366
codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_span::{sym, Span};
2020
use rustc_target::spec::{abi, SanitizerSet};
2121

2222
use crate::errors;
23-
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
23+
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr};
2424

2525
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
2626
use rustc_middle::mir::mono::Linkage::*;
@@ -72,7 +72,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
7272
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
7373
}
7474

75-
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
75+
let known_target_features = tcx.known_target_features(LOCAL_CRATE);
7676

7777
let mut inline_span = None;
7878
let mut link_ordinal_span = None;
@@ -298,10 +298,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
298298
check_target_feature_trait_unsafe(tcx, did, attr.span);
299299
}
300300
}
301-
from_target_feature(
301+
from_target_feature_attr(
302302
tcx,
303303
attr,
304-
supported_target_features,
304+
known_target_features,
305305
&mut codegen_fn_attrs.target_features,
306306
);
307307
}

‎compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,14 @@ pub struct TargetFeatureSafeTrait {
10171017
pub def: Span,
10181018
}
10191019

1020+
#[derive(Diagnostic)]
1021+
#[diag(codegen_ssa_forbidden_target_feature)]
1022+
pub struct ForbiddenTargetFeature<'a> {
1023+
#[primary_span]
1024+
pub span: Span,
1025+
pub feature: &'a str,
1026+
}
1027+
10201028
#[derive(Diagnostic)]
10211029
#[diag(codegen_ssa_failed_to_get_layout)]
10221030
pub struct FailedToGetLayout<'tcx> {

‎compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ use rustc_middle::ty::TyCtxt;
1212
use rustc_session::parse::feature_err;
1313
use rustc_span::symbol::{sym, Symbol};
1414
use rustc_span::Span;
15+
use rustc_target::target_features::{self, Stability};
1516

1617
use crate::errors;
1718

18-
pub fn from_target_feature(
19+
/// Compute the enabled target features from the `#[target_feature]` function attribute.
20+
/// Enabled target features are added to `target_features`.
21+
pub fn from_target_feature_attr(
1922
tcx: TyCtxt<'_>,
2023
attr: &ast::Attribute,
21-
supported_target_features: &UnordMap<String, Option<Symbol>>,
24+
known_target_features: &UnordMap<String, target_features::Stability>,
2225
target_features: &mut Vec<TargetFeature>,
2326
) {
2427
let Some(list) = attr.meta_item_list() else { return };
@@ -47,12 +50,12 @@ pub fn from_target_feature(
4750

4851
// We allow comma separation to enable multiple features.
4952
added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
50-
let Some(feature_gate) = supported_target_features.get(feature) else {
53+
let Some(stability) = known_target_features.get(feature) else {
5154
let msg = format!("the feature named `{feature}` is not valid for this target");
5255
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
5356
err.span_label(item.span(), format!("`{feature}` is not valid for this target"));
5457
if let Some(stripped) = feature.strip_prefix('+') {
55-
let valid = supported_target_features.contains_key(stripped);
58+
let valid = known_target_features.contains_key(stripped);
5659
if valid {
5760
err.help("consider removing the leading `+` in the feature name");
5861
}
@@ -62,39 +65,73 @@ pub fn from_target_feature(
6265
};
6366

6467
// Only allow features whose feature gates have been enabled.
65-
let allowed = match feature_gate.as_ref().copied() {
66-
Some(sym::arm_target_feature) => rust_features.arm_target_feature,
67-
Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
68-
Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
69-
Some(sym::mips_target_feature) => rust_features.mips_target_feature,
70-
Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
71-
Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
72-
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
73-
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
74-
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
75-
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
76-
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
77-
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
78-
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
79-
Some(sym::csky_target_feature) => rust_features.csky_target_feature,
80-
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
81-
Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature,
82-
Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature,
83-
Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86,
84-
Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
85-
Some(sym::xop_target_feature) => rust_features.xop_target_feature,
86-
Some(sym::s390x_target_feature) => rust_features.s390x_target_feature,
87-
Some(name) => bug!("unknown target feature gate {}", name),
88-
None => true,
68+
let allowed = match stability {
69+
Stability::Forbidden => false,
70+
Stability::Stable => true,
71+
Stability::Unstable(sym::arm_target_feature) => rust_features.arm_target_feature,
72+
Stability::Unstable(sym::hexagon_target_feature) => {
73+
rust_features.hexagon_target_feature
74+
}
75+
Stability::Unstable(sym::powerpc_target_feature) => {
76+
rust_features.powerpc_target_feature
77+
}
78+
Stability::Unstable(sym::mips_target_feature) => rust_features.mips_target_feature,
79+
Stability::Unstable(sym::riscv_target_feature) => {
80+
rust_features.riscv_target_feature
81+
}
82+
Stability::Unstable(sym::avx512_target_feature) => {
83+
rust_features.avx512_target_feature
84+
}
85+
Stability::Unstable(sym::sse4a_target_feature) => {
86+
rust_features.sse4a_target_feature
87+
}
88+
Stability::Unstable(sym::tbm_target_feature) => rust_features.tbm_target_feature,
89+
Stability::Unstable(sym::wasm_target_feature) => rust_features.wasm_target_feature,
90+
Stability::Unstable(sym::rtm_target_feature) => rust_features.rtm_target_feature,
91+
Stability::Unstable(sym::ermsb_target_feature) => {
92+
rust_features.ermsb_target_feature
93+
}
94+
Stability::Unstable(sym::bpf_target_feature) => rust_features.bpf_target_feature,
95+
Stability::Unstable(sym::aarch64_ver_target_feature) => {
96+
rust_features.aarch64_ver_target_feature
97+
}
98+
Stability::Unstable(sym::csky_target_feature) => rust_features.csky_target_feature,
99+
Stability::Unstable(sym::loongarch_target_feature) => {
100+
rust_features.loongarch_target_feature
101+
}
102+
Stability::Unstable(sym::lahfsahf_target_feature) => {
103+
rust_features.lahfsahf_target_feature
104+
}
105+
Stability::Unstable(sym::prfchw_target_feature) => {
106+
rust_features.prfchw_target_feature
107+
}
108+
Stability::Unstable(sym::sha512_sm_x86) => rust_features.sha512_sm_x86,
109+
Stability::Unstable(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
110+
Stability::Unstable(sym::xop_target_feature) => rust_features.xop_target_feature,
111+
Stability::Unstable(sym::s390x_target_feature) => {
112+
rust_features.s390x_target_feature
113+
}
114+
Stability::Unstable(name) => bug!("unknown target feature gate {}", name),
89115
};
90116
if !allowed {
91-
feature_err(
92-
&tcx.sess,
93-
feature_gate.unwrap(),
94-
item.span(),
95-
format!("the target feature `{feature}` is currently unstable"),
96-
)
97-
.emit();
117+
match stability {
118+
Stability::Stable => unreachable!(),
119+
&Stability::Unstable(lang_feature_name) => {
120+
feature_err(
121+
&tcx.sess,
122+
lang_feature_name,
123+
item.span(),
124+
format!("the target feature `{feature}` is currently unstable"),
125+
)
126+
.emit();
127+
}
128+
Stability::Forbidden => {
129+
tcx.dcx().emit_err(errors::ForbiddenTargetFeature {
130+
span: item.span(),
131+
feature,
132+
});
133+
}
134+
}
98135
}
99136
Some(Symbol::intern(feature))
100137
}));
@@ -160,20 +197,20 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s
160197

161198
pub(crate) fn provide(providers: &mut Providers) {
162199
*providers = Providers {
163-
supported_target_features: |tcx, cnum| {
200+
known_target_features: |tcx, cnum| {
164201
assert_eq!(cnum, LOCAL_CRATE);
165202
if tcx.sess.opts.actually_rustdoc {
166203
// rustdoc needs to be able to document functions that use all the features, so
167204
// whitelist them all
168205
rustc_target::target_features::all_known_features()
169-
.map(|(a, b)| (a.to_string(), b.as_feature_name()))
206+
.map(|(a, b)| (a.to_string(), b))
170207
.collect()
171208
} else {
172209
tcx.sess
173210
.target
174-
.supported_target_features()
211+
.known_target_features()
175212
.iter()
176-
.map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
213+
.map(|&(a, b, _)| (a.to_string(), b))
177214
.collect()
178215
}
179216
},

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,10 +2160,10 @@ rustc_queries! {
21602160
desc { "computing autoderef types for `{}`", goal.value.value }
21612161
}
21622162

2163-
query supported_target_features(_: CrateNum) -> &'tcx UnordMap<String, Option<Symbol>> {
2163+
query known_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
21642164
arena_cache
21652165
eval_always
2166-
desc { "looking up supported target features" }
2166+
desc { "looking up known target features" }
21672167
}
21682168

21692169
query implied_target_features(feature: Symbol) -> &'tcx Vec<Symbol> {

‎compiler/rustc_target/src/target_features.rs

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
23
use rustc_span::symbol::{sym, Symbol};
34

45
/// Features that control behaviour of rustc, rather than the codegen.
@@ -16,14 +17,31 @@ pub enum Stability {
1617
/// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]`
1718
/// requires enabling the given nightly feature.
1819
Unstable(Symbol),
20+
/// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic
21+
/// target definition. Used in particular for features that change the floating-point ABI.
22+
Forbidden,
1923
}
2024
use Stability::*;
2125

26+
impl<CTX> HashStable<CTX> for Stability {
27+
#[inline]
28+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
29+
std::mem::discriminant(self).hash_stable(hcx, hasher);
30+
match self {
31+
Stable => {}
32+
Unstable(sym) => {
33+
sym.hash_stable(hcx, hasher);
34+
}
35+
Forbidden => {}
36+
}
37+
}
38+
}
39+
2240
impl Stability {
2341
pub fn as_feature_name(self) -> Option<Symbol> {
2442
match self {
25-
Stable => None,
2643
Unstable(s) => Some(s),
44+
_ => None,
2745
}
2846
}
2947

@@ -46,17 +64,26 @@ impl Stability {
4664
// per-function level, since we would then allow safe calls from functions with `+soft-float` to
4765
// functions without that feature!
4866
//
49-
// When adding a new feature, be particularly mindful of features that affect function ABIs. Those
50-
// need to be treated very carefully to avoid introducing unsoundness! This often affects features
51-
// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an
52-
// example of this going wrong), but features enabling new SIMD registers are also a concern (see
53-
// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong).
67+
// It is important for soundness that features allowed here do *not* change the function call ABI.
68+
// For example, disabling the `x87` feature on x86 changes how scalar floats are passed as
69+
// arguments, so enabling toggling that feature would be unsound. In fact, we have to explicit list
70+
// features that change the ABI as `Forbidden`. Note that this is only effective if such features
71+
// can never be toggled via `-Ctarget-cpu`! If that is ever a possibiliy, we will need extra checks
72+
// ensuring that the LLVM-computed targte features for a CPU did not (un)set a `Forbidden` feature.
73+
// See https://github.com/rust-lang/rust/issues/116344 for some more context.
74+
// FIXME: add such "forbidden" features for non-x86 targets.
75+
//
76+
// The one exception to features that change the ABI is features that enable larger vector
77+
// registers. Those are permitted to be listed here. This is currently unsound (see
78+
// https://github.com/rust-lang/rust/issues/116558); in the future we will have to ensure that
79+
// functions can only use such vectors as arguments/return types if the corresponding target feature
80+
// is enabled.
5481
//
5582
// Stabilizing a target feature requires t-lang approval.
5683

5784
type ImpliedFeatures = &'static [&'static str];
5885

59-
const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
86+
const ARM_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
6087
// tidy-alphabetical-start
6188
("aclass", Unstable(sym::arm_target_feature), &[]),
6289
("aes", Unstable(sym::arm_target_feature), &["neon"]),
@@ -89,7 +116,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
89116
// tidy-alphabetical-end
90117
];
91118

92-
const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
119+
const AARCH64_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
93120
// tidy-alphabetical-start
94121
// FEAT_AES & FEAT_PMULL
95122
("aes", Stable, &["neon"]),
@@ -277,7 +304,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
277304
&["paca", "pacg"], // Together these represent `pauth` in LLVM
278305
];
279306

280-
const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
307+
const X86_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
281308
// tidy-alphabetical-start
282309
("adx", Stable, &[]),
283310
("aes", Stable, &["sse2"]),
@@ -328,6 +355,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
328355
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
329356
("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
330357
("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
358+
("soft-float", Forbidden, &[]), // changes float ABI
331359
("sse", Stable, &[]),
332360
("sse2", Stable, &["sse"]),
333361
("sse3", Stable, &["sse2"]),
@@ -338,6 +366,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
338366
("tbm", Unstable(sym::tbm_target_feature), &[]),
339367
("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
340368
("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
369+
("x87", Forbidden, &[]), // changes float ABI
341370
("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
342371
("xsave", Stable, &[]),
343372
("xsavec", Stable, &["xsave"]),
@@ -346,14 +375,14 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
346375
// tidy-alphabetical-end
347376
];
348377

349-
const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
378+
const HEXAGON_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
350379
// tidy-alphabetical-start
351380
("hvx", Unstable(sym::hexagon_target_feature), &[]),
352381
("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
353382
// tidy-alphabetical-end
354383
];
355384

356-
const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
385+
const POWERPC_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
357386
// tidy-alphabetical-start
358387
("altivec", Unstable(sym::powerpc_target_feature), &[]),
359388
("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
@@ -365,15 +394,15 @@ const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
365394
// tidy-alphabetical-end
366395
];
367396

368-
const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
397+
const MIPS_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
369398
// tidy-alphabetical-start
370399
("fp64", Unstable(sym::mips_target_feature), &[]),
371400
("msa", Unstable(sym::mips_target_feature), &[]),
372401
("virt", Unstable(sym::mips_target_feature), &[]),
373402
// tidy-alphabetical-end
374403
];
375404

376-
const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
405+
const RISCV_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
377406
// tidy-alphabetical-start
378407
("a", Stable, &[]),
379408
("c", Stable, &[]),
@@ -410,7 +439,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
410439
// tidy-alphabetical-end
411440
];
412441

413-
const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
442+
const WASM_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
414443
// tidy-alphabetical-start
415444
("atomics", Unstable(sym::wasm_target_feature), &[]),
416445
("bulk-memory", Stable, &[]),
@@ -426,10 +455,10 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
426455
// tidy-alphabetical-end
427456
];
428457

429-
const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
458+
const BPF_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
430459
&[("alu32", Unstable(sym::bpf_target_feature), &[])];
431460

432-
const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
461+
const CSKY_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
433462
// tidy-alphabetical-start
434463
("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
435464
("2e3", Unstable(sym::csky_target_feature), &["e2"]),
@@ -476,7 +505,7 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
476505
// tidy-alphabetical-end
477506
];
478507

479-
const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
508+
const LOONGARCH_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
480509
// tidy-alphabetical-start
481510
("d", Unstable(sym::loongarch_target_feature), &["f"]),
482511
("f", Unstable(sym::loongarch_target_feature), &[]),
@@ -490,7 +519,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
490519
// tidy-alphabetical-end
491520
];
492521

493-
const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
522+
const IBMZ_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
494523
// tidy-alphabetical-start
495524
("backchain", Unstable(sym::s390x_target_feature), &[]),
496525
("vector", Unstable(sym::s390x_target_feature), &[]),
@@ -503,39 +532,37 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
503532
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
504533
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
505534
std::iter::empty()
506-
.chain(ARM_ALLOWED_FEATURES.iter())
507-
.chain(AARCH64_ALLOWED_FEATURES.iter())
508-
.chain(X86_ALLOWED_FEATURES.iter())
509-
.chain(HEXAGON_ALLOWED_FEATURES.iter())
510-
.chain(POWERPC_ALLOWED_FEATURES.iter())
511-
.chain(MIPS_ALLOWED_FEATURES.iter())
512-
.chain(RISCV_ALLOWED_FEATURES.iter())
513-
.chain(WASM_ALLOWED_FEATURES.iter())
514-
.chain(BPF_ALLOWED_FEATURES.iter())
515-
.chain(CSKY_ALLOWED_FEATURES)
516-
.chain(LOONGARCH_ALLOWED_FEATURES)
517-
.chain(IBMZ_ALLOWED_FEATURES)
535+
.chain(ARM_KNOWN_FEATURES.iter())
536+
.chain(AARCH64_KNOWN_FEATURES.iter())
537+
.chain(X86_KNOWN_FEATURES.iter())
538+
.chain(HEXAGON_KNOWN_FEATURES.iter())
539+
.chain(POWERPC_KNOWN_FEATURES.iter())
540+
.chain(MIPS_KNOWN_FEATURES.iter())
541+
.chain(RISCV_KNOWN_FEATURES.iter())
542+
.chain(WASM_KNOWN_FEATURES.iter())
543+
.chain(BPF_KNOWN_FEATURES.iter())
544+
.chain(CSKY_KNOWN_FEATURES)
545+
.chain(LOONGARCH_KNOWN_FEATURES)
546+
.chain(IBMZ_KNOWN_FEATURES)
518547
.cloned()
519548
.map(|(f, s, _)| (f, s))
520549
}
521550

522551
impl super::spec::Target {
523-
pub fn supported_target_features(
524-
&self,
525-
) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
552+
pub fn known_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
526553
match &*self.arch {
527-
"arm" => ARM_ALLOWED_FEATURES,
528-
"aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
529-
"x86" | "x86_64" => X86_ALLOWED_FEATURES,
530-
"hexagon" => HEXAGON_ALLOWED_FEATURES,
531-
"mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES,
532-
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
533-
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
534-
"wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
535-
"bpf" => BPF_ALLOWED_FEATURES,
536-
"csky" => CSKY_ALLOWED_FEATURES,
537-
"loongarch64" => LOONGARCH_ALLOWED_FEATURES,
538-
"s390x" => IBMZ_ALLOWED_FEATURES,
554+
"arm" => ARM_KNOWN_FEATURES,
555+
"aarch64" | "arm64ec" => AARCH64_KNOWN_FEATURES,
556+
"x86" | "x86_64" => X86_KNOWN_FEATURES,
557+
"hexagon" => HEXAGON_KNOWN_FEATURES,
558+
"mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_KNOWN_FEATURES,
559+
"powerpc" | "powerpc64" => POWERPC_KNOWN_FEATURES,
560+
"riscv32" | "riscv64" => RISCV_KNOWN_FEATURES,
561+
"wasm32" | "wasm64" => WASM_KNOWN_FEATURES,
562+
"bpf" => BPF_KNOWN_FEATURES,
563+
"csky" => CSKY_KNOWN_FEATURES,
564+
"loongarch64" => LOONGARCH_KNOWN_FEATURES,
565+
"s390x" => IBMZ_KNOWN_FEATURES,
539566
_ => &[],
540567
}
541568
}
@@ -552,7 +579,7 @@ impl super::spec::Target {
552579
base_features: impl Iterator<Item = Symbol>,
553580
) -> FxHashSet<Symbol> {
554581
let implied_features = self
555-
.supported_target_features()
582+
.known_target_features()
556583
.iter()
557584
.map(|(f, _, i)| (Symbol::intern(f), i))
558585
.collect::<FxHashMap<_, _>>();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
2+
//@ needs-llvm-components: x86
3+
#![feature(no_core, lang_items)]
4+
#![no_std]
5+
#![no_core]
6+
7+
#[lang = "sized"]
8+
pub trait Sized {}
9+
10+
#[target_feature(enable = "soft-float")]
11+
//~^ERROR: cannot be toggled with
12+
pub unsafe fn my_fun() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: target feature `soft-float` cannot be toggled with `#[target_feature]`
2+
--> $DIR/forbidden-target-feature-attribute.rs:10:18
3+
|
4+
LL | #[target_feature(enable = "soft-float")]
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
2+
//@ needs-llvm-components: x86
3+
//@ compile-flags: -Ctarget-feature=-soft-float
4+
#![feature(no_core, lang_items)]
5+
#![no_std]
6+
#![no_core]
7+
8+
#[lang = "sized"]
9+
pub trait Sized {}
10+
11+
fn main() {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: target feature `soft-float` cannot be toggled with `-Ctarget-feature`
2+
3+
error: aborting due to 1 previous error
4+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
2+
//@ needs-llvm-components: x86
3+
//@ compile-flags: -Ctarget-feature=+soft-float
4+
#![feature(no_core, lang_items)]
5+
#![no_std]
6+
#![no_core]
7+
8+
#[lang = "sized"]
9+
pub trait Sized {}
10+
11+
fn main() {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: target feature `soft-float` cannot be toggled with `-Ctarget-feature`
2+
3+
error: aborting due to 1 previous error
4+

0 commit comments

Comments
 (0)
Please sign in to comment.