From 648e5e101255abab7c04554278fb5c0d81e0fa15 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Sep 2024 11:45:59 +0200 Subject: [PATCH] mark some target features as 'forbidden' so they cannot be (un)set --- compiler/rustc_codegen_llvm/messages.ftl | 3 + compiler/rustc_codegen_llvm/src/errors.rs | 6 + compiler/rustc_codegen_llvm/src/llvm_util.rs | 91 ++++++++------ compiler/rustc_codegen_ssa/messages.ftl | 3 + .../rustc_codegen_ssa/src/codegen_attrs.rs | 8 +- compiler/rustc_codegen_ssa/src/errors.rs | 8 ++ .../rustc_codegen_ssa/src/target_features.rs | 115 +++++++++++------ compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_target/src/target_features.rs | 119 +++++++++++------- .../using-target-feature-unstable.rs | 0 .../forbidden-target-feature-attribute.rs | 12 ++ .../forbidden-target-feature-attribute.stderr | 8 ++ .../forbidden-target-feature-flag-disable.rs | 11 ++ ...rbidden-target-feature-flag-disable.stderr | 4 + .../forbidden-target-feature-flag.rs | 11 ++ .../forbidden-target-feature-flag.stderr | 4 + .../using-target-feature-unstable.rs | 0 17 files changed, 279 insertions(+), 128 deletions(-) rename tests/ui/{ => target-feature}/auxiliary/using-target-feature-unstable.rs (100%) create mode 100644 tests/ui/target-feature/forbidden-target-feature-attribute.rs create mode 100644 tests/ui/target-feature/forbidden-target-feature-attribute.stderr create mode 100644 tests/ui/target-feature/forbidden-target-feature-flag-disable.rs create mode 100644 tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr create mode 100644 tests/ui/target-feature/forbidden-target-feature-flag.rs create mode 100644 tests/ui/target-feature/forbidden-target-feature-flag.stderr rename tests/ui/{ => target-feature}/using-target-feature-unstable.rs (100%) diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index df2198df14b6a..aec0f25a35337 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -7,6 +7,9 @@ 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 toggled with `-Ctarget-feature` + codegen_llvm_from_llvm_diag = {$message} codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index bb481d2a30856..5111af1a12f21 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -31,6 +31,12 @@ pub(crate) struct UnstableCTargetFeature<'a> { pub feature: &'a str, } +#[derive(Diagnostic)] +#[diag(codegen_llvm_forbidden_ctarget_feature)] +pub(crate) struct ForbiddenCTargetFeature<'a> { + pub feature: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_llvm_possible_feature)] diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 618602ed70f44..49eaa75be4d30 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -15,12 +15,13 @@ use rustc_session::config::{PrintKind, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; -use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; +use rustc_target::target_features::{Stability, RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; use crate::back::write::create_informational_target_machine; use crate::errors::{ - FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, - UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + FixedX18InvalidArch, ForbiddenCTargetFeature, InvalidTargetFeaturePrefix, PossibleFeature, + TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix, + UnstableCTargetFeature, }; use crate::llvm; @@ -298,11 +299,17 @@ pub(crate) fn check_tied_features( pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { let mut features = vec![]; - // Add base features for the target + // Add base features for the target. + // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below. + // The reaosn is that if LLVM considers a feature implied but we do not, we don't want that to + // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of + // the target CPU, that is still expanded to target features (with all their implied features) by + // LLVM. let target_machine = create_informational_target_machine(sess, true); + // Compute which of the known target features are enables in the 'base' target machine. features.extend( sess.target - .supported_target_features() + .known_target_features() .iter() .filter(|(feature, _, _)| { // skip checking special features, as LLVM may not understands them @@ -344,7 +351,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { // Filter enabled features based on feature gates sess.target - .supported_target_features() + .known_target_features() .iter() .filter_map(|&(feature, gate, _)| { 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 let mut known_llvm_target_features = FxHashSet::<&'static str>::default(); let mut rustc_target_features = sess .target - .supported_target_features() + .known_target_features() .iter() - .filter_map(|(feature, _gate, _implied)| { + .filter_map(|(feature, gate, _implied)| { + if matches!(gate, Stability::Forbidden) { + // Do not list forbidden features. + return None; + } // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; let desc = @@ -576,7 +587,7 @@ pub(crate) fn global_llvm_features( // -Ctarget-features if !only_base_features { - let supported_features = sess.target.supported_target_features(); + let known_features = sess.target.known_target_features(); let (llvm_major, _, _) = get_version(); let mut featsmap = FxHashMap::default(); @@ -614,37 +625,43 @@ pub(crate) fn global_llvm_features( let feature = backend_feature_name(sess, s)?; // Warn against use of LLVM specific feature names and unstable features on the CLI. if diagnostics { - let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature); - if feature_state.is_none() { - let rust_feature = - supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature)?; - if llvm_features.contains(feature) - && !llvm_features.contains(rust_feature) - { - Some(rust_feature) - } else { - None + let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); + match feature_state { + None => { + let rust_feature = + known_features.iter().find_map(|&(rust_feature, _, _)| { + let llvm_features = to_llvm_features(sess, rust_feature)?; + if llvm_features.contains(feature) + && !llvm_features.contains(rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } else if feature_state - .is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable()) - { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } else { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::None, + } + }; + sess.dcx().emit_warn(unknown_feature); + } + Some((_, Stability::Stable, _)) => {} + Some((_, Stability::Unstable(_), _)) => { + // An unstable feature. Warn about using it. + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } + Some((_, Stability::Forbidden, _)) => { + sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + } } - } - if diagnostics { // FIXME(nagisa): figure out how to not allocate a full hashset here. featsmap.insert(feature, enable_disable == '+'); } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 8a6a2acd87d44..77e41d1531ce4 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -58,6 +58,9 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error} codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` +codegen_ssa_forbidden_target_feature = + target feature `{$feature}` cannot be toggled with `#[target_feature]` + codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4ab20c154ccd0..3e19f4604a493 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -20,7 +20,7 @@ use rustc_span::{sym, Span}; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; -use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature}; +use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr}; fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { use rustc_middle::mir::mono::Linkage::*; @@ -72,7 +72,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS; } - let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); + let known_target_features = tcx.known_target_features(LOCAL_CRATE); let mut inline_span = None; let mut link_ordinal_span = None; @@ -298,10 +298,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { check_target_feature_trait_unsafe(tcx, did, attr.span); } } - from_target_feature( + from_target_feature_attr( tcx, attr, - supported_target_features, + known_target_features, &mut codegen_fn_attrs.target_features, ); } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 573a8cf7cbe42..1e8ece57ba52f 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1017,6 +1017,14 @@ pub struct TargetFeatureSafeTrait { pub def: Span, } +#[derive(Diagnostic)] +#[diag(codegen_ssa_forbidden_target_feature)] +pub struct ForbiddenTargetFeature<'a> { + #[primary_span] + pub span: Span, + pub feature: &'a str, +} + #[derive(Diagnostic)] #[diag(codegen_ssa_failed_to_get_layout)] pub struct FailedToGetLayout<'tcx> { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index cf8f7fa25d856..569ca5bfe08a6 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -12,13 +12,16 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use rustc_target::target_features::{self, Stability}; use crate::errors; -pub fn from_target_feature( +/// Compute the enabled target features from the `#[target_feature]` function attribute. +/// Enabled target features are added to `target_features`. +pub fn from_target_feature_attr( tcx: TyCtxt<'_>, attr: &ast::Attribute, - supported_target_features: &UnordMap>, + known_target_features: &UnordMap, target_features: &mut Vec, ) { let Some(list) = attr.meta_item_list() else { return }; @@ -47,12 +50,12 @@ pub fn from_target_feature( // We allow comma separation to enable multiple features. added_target_features.extend(value.as_str().split(',').filter_map(|feature| { - let Some(feature_gate) = supported_target_features.get(feature) else { + let Some(stability) = known_target_features.get(feature) else { let msg = format!("the feature named `{feature}` is not valid for this target"); let mut err = tcx.dcx().struct_span_err(item.span(), msg); err.span_label(item.span(), format!("`{feature}` is not valid for this target")); if let Some(stripped) = feature.strip_prefix('+') { - let valid = supported_target_features.contains_key(stripped); + let valid = known_target_features.contains_key(stripped); if valid { err.help("consider removing the leading `+` in the feature name"); } @@ -62,39 +65,73 @@ pub fn from_target_feature( }; // Only allow features whose feature gates have been enabled. - let allowed = match feature_gate.as_ref().copied() { - Some(sym::arm_target_feature) => rust_features.arm_target_feature, - Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, - Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, - Some(sym::mips_target_feature) => rust_features.mips_target_feature, - Some(sym::riscv_target_feature) => rust_features.riscv_target_feature, - Some(sym::avx512_target_feature) => rust_features.avx512_target_feature, - Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature, - Some(sym::tbm_target_feature) => rust_features.tbm_target_feature, - Some(sym::wasm_target_feature) => rust_features.wasm_target_feature, - Some(sym::rtm_target_feature) => rust_features.rtm_target_feature, - Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, - Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, - Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, - Some(sym::csky_target_feature) => rust_features.csky_target_feature, - Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, - Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature, - Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature, - Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86, - Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, - Some(sym::xop_target_feature) => rust_features.xop_target_feature, - Some(sym::s390x_target_feature) => rust_features.s390x_target_feature, - Some(name) => bug!("unknown target feature gate {}", name), - None => true, + let allowed = match stability { + Stability::Forbidden => false, + Stability::Stable => true, + Stability::Unstable(sym::arm_target_feature) => rust_features.arm_target_feature, + Stability::Unstable(sym::hexagon_target_feature) => { + rust_features.hexagon_target_feature + } + Stability::Unstable(sym::powerpc_target_feature) => { + rust_features.powerpc_target_feature + } + Stability::Unstable(sym::mips_target_feature) => rust_features.mips_target_feature, + Stability::Unstable(sym::riscv_target_feature) => { + rust_features.riscv_target_feature + } + Stability::Unstable(sym::avx512_target_feature) => { + rust_features.avx512_target_feature + } + Stability::Unstable(sym::sse4a_target_feature) => { + rust_features.sse4a_target_feature + } + Stability::Unstable(sym::tbm_target_feature) => rust_features.tbm_target_feature, + Stability::Unstable(sym::wasm_target_feature) => rust_features.wasm_target_feature, + Stability::Unstable(sym::rtm_target_feature) => rust_features.rtm_target_feature, + Stability::Unstable(sym::ermsb_target_feature) => { + rust_features.ermsb_target_feature + } + Stability::Unstable(sym::bpf_target_feature) => rust_features.bpf_target_feature, + Stability::Unstable(sym::aarch64_ver_target_feature) => { + rust_features.aarch64_ver_target_feature + } + Stability::Unstable(sym::csky_target_feature) => rust_features.csky_target_feature, + Stability::Unstable(sym::loongarch_target_feature) => { + rust_features.loongarch_target_feature + } + Stability::Unstable(sym::lahfsahf_target_feature) => { + rust_features.lahfsahf_target_feature + } + Stability::Unstable(sym::prfchw_target_feature) => { + rust_features.prfchw_target_feature + } + Stability::Unstable(sym::sha512_sm_x86) => rust_features.sha512_sm_x86, + Stability::Unstable(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, + Stability::Unstable(sym::xop_target_feature) => rust_features.xop_target_feature, + Stability::Unstable(sym::s390x_target_feature) => { + rust_features.s390x_target_feature + } + Stability::Unstable(name) => bug!("unknown target feature gate {}", name), }; if !allowed { - feature_err( - &tcx.sess, - feature_gate.unwrap(), - item.span(), - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); + match stability { + Stability::Stable => unreachable!(), + &Stability::Unstable(lang_feature_name) => { + feature_err( + &tcx.sess, + lang_feature_name, + item.span(), + format!("the target feature `{feature}` is currently unstable"), + ) + .emit(); + } + Stability::Forbidden => { + tcx.dcx().emit_err(errors::ForbiddenTargetFeature { + span: item.span(), + feature, + }); + } + } } Some(Symbol::intern(feature)) })); @@ -160,20 +197,20 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { - supported_target_features: |tcx, cnum| { + known_target_features: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all rustc_target::target_features::all_known_features() - .map(|(a, b)| (a.to_string(), b.as_feature_name())) + .map(|(a, b)| (a.to_string(), b)) .collect() } else { tcx.sess .target - .supported_target_features() + .known_target_features() .iter() - .map(|&(a, b, _)| (a.to_string(), b.as_feature_name())) + .map(|&(a, b, _)| (a.to_string(), b)) .collect() } }, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d6bdc1af0d2ca..15a5eaa5449d0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2160,10 +2160,10 @@ rustc_queries! { desc { "computing autoderef types for `{}`", goal.value.value } } - query supported_target_features(_: CrateNum) -> &'tcx UnordMap> { + query known_target_features(_: CrateNum) -> &'tcx UnordMap { arena_cache eval_always - desc { "looking up supported target features" } + desc { "looking up known target features" } } query implied_target_features(feature: Symbol) -> &'tcx Vec { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 8319cb880cc79..9f4a620975692 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1,4 +1,5 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::symbol::{sym, Symbol}; /// Features that control behaviour of rustc, rather than the codegen. @@ -16,14 +17,31 @@ pub enum Stability { /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]` /// requires enabling the given nightly feature. Unstable(Symbol), + /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic + /// target definition. Used in particular for features that change the floating-point ABI. + Forbidden, } use Stability::*; +impl HashStable for Stability { + #[inline] + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + std::mem::discriminant(self).hash_stable(hcx, hasher); + match self { + Stable => {} + Unstable(sym) => { + sym.hash_stable(hcx, hasher); + } + Forbidden => {} + } + } +} + impl Stability { pub fn as_feature_name(self) -> Option { match self { - Stable => None, Unstable(s) => Some(s), + _ => None, } } @@ -46,17 +64,26 @@ impl Stability { // per-function level, since we would then allow safe calls from functions with `+soft-float` to // functions without that feature! // -// When adding a new feature, be particularly mindful of features that affect function ABIs. Those -// need to be treated very carefully to avoid introducing unsoundness! This often affects features -// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an -// example of this going wrong), but features enabling new SIMD registers are also a concern (see -// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). +// It is important for soundness that features allowed here do *not* change the function call ABI. +// For example, disabling the `x87` feature on x86 changes how scalar floats are passed as +// arguments, so enabling toggling that feature would be unsound. In fact, we have to explicit list +// features that change the ABI as `Forbidden`. Note that this is only effective if such features +// can never be toggled via `-Ctarget-cpu`! If that is ever a possibiliy, we will need extra checks +// ensuring that the LLVM-computed targte features for a CPU did not (un)set a `Forbidden` feature. +// See https://github.com/rust-lang/rust/issues/116344 for some more context. +// FIXME: add such "forbidden" features for non-x86 targets. +// +// The one exception to features that change the ABI is features that enable larger vector +// registers. Those are permitted to be listed here. This is currently unsound (see +// https://github.com/rust-lang/rust/issues/116558); in the future we will have to ensure that +// functions can only use such vectors as arguments/return types if the corresponding target feature +// is enabled. // // Stabilizing a target feature requires t-lang approval. type ImpliedFeatures = &'static [&'static str]; -const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const ARM_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("aclass", Unstable(sym::arm_target_feature), &[]), ("aes", Unstable(sym::arm_target_feature), &["neon"]), @@ -89,7 +116,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const AARCH64_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start // FEAT_AES & FEAT_PMULL ("aes", Stable, &["neon"]), @@ -277,7 +304,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const X86_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("adx", Stable, &[]), ("aes", Stable, &["sse2"]), @@ -328,6 +355,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]), ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]), ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]), + ("soft-float", Forbidden, &[]), // changes float ABI ("sse", Stable, &[]), ("sse2", Stable, &["sse"]), ("sse3", Stable, &["sse2"]), @@ -338,6 +366,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("tbm", Unstable(sym::tbm_target_feature), &[]), ("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]), ("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]), + ("x87", Forbidden, &[]), // changes float ABI ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]), ("xsave", Stable, &[]), ("xsavec", Stable, &["xsave"]), @@ -346,14 +375,14 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const HEXAGON_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("hvx", Unstable(sym::hexagon_target_feature), &[]), ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), // tidy-alphabetical-end ]; -const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const POWERPC_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("altivec", Unstable(sym::powerpc_target_feature), &[]), ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]), @@ -365,7 +394,7 @@ const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const MIPS_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("fp64", Unstable(sym::mips_target_feature), &[]), ("msa", Unstable(sym::mips_target_feature), &[]), @@ -373,7 +402,7 @@ const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const RISCV_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("a", Stable, &[]), ("c", Stable, &[]), @@ -410,7 +439,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const WASM_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("atomics", Unstable(sym::wasm_target_feature), &[]), ("bulk-memory", Stable, &[]), @@ -426,10 +455,10 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = +const BPF_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[("alu32", Unstable(sym::bpf_target_feature), &[])]; -const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const CSKY_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("10e60", Unstable(sym::csky_target_feature), &["7e10"]), ("2e3", Unstable(sym::csky_target_feature), &["e2"]), @@ -476,7 +505,7 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const LOONGARCH_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("d", Unstable(sym::loongarch_target_feature), &["f"]), ("f", Unstable(sym::loongarch_target_feature), &[]), @@ -490,7 +519,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; -const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ +const IBMZ_KNOWN_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("backchain", Unstable(sym::s390x_target_feature), &[]), ("vector", Unstable(sym::s390x_target_feature), &[]), @@ -503,39 +532,37 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! pub fn all_known_features() -> impl Iterator { std::iter::empty() - .chain(ARM_ALLOWED_FEATURES.iter()) - .chain(AARCH64_ALLOWED_FEATURES.iter()) - .chain(X86_ALLOWED_FEATURES.iter()) - .chain(HEXAGON_ALLOWED_FEATURES.iter()) - .chain(POWERPC_ALLOWED_FEATURES.iter()) - .chain(MIPS_ALLOWED_FEATURES.iter()) - .chain(RISCV_ALLOWED_FEATURES.iter()) - .chain(WASM_ALLOWED_FEATURES.iter()) - .chain(BPF_ALLOWED_FEATURES.iter()) - .chain(CSKY_ALLOWED_FEATURES) - .chain(LOONGARCH_ALLOWED_FEATURES) - .chain(IBMZ_ALLOWED_FEATURES) + .chain(ARM_KNOWN_FEATURES.iter()) + .chain(AARCH64_KNOWN_FEATURES.iter()) + .chain(X86_KNOWN_FEATURES.iter()) + .chain(HEXAGON_KNOWN_FEATURES.iter()) + .chain(POWERPC_KNOWN_FEATURES.iter()) + .chain(MIPS_KNOWN_FEATURES.iter()) + .chain(RISCV_KNOWN_FEATURES.iter()) + .chain(WASM_KNOWN_FEATURES.iter()) + .chain(BPF_KNOWN_FEATURES.iter()) + .chain(CSKY_KNOWN_FEATURES) + .chain(LOONGARCH_KNOWN_FEATURES) + .chain(IBMZ_KNOWN_FEATURES) .cloned() .map(|(f, s, _)| (f, s)) } impl super::spec::Target { - pub fn supported_target_features( - &self, - ) -> &'static [(&'static str, Stability, ImpliedFeatures)] { + pub fn known_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { match &*self.arch { - "arm" => ARM_ALLOWED_FEATURES, - "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES, - "x86" | "x86_64" => X86_ALLOWED_FEATURES, - "hexagon" => HEXAGON_ALLOWED_FEATURES, - "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES, - "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, - "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, - "bpf" => BPF_ALLOWED_FEATURES, - "csky" => CSKY_ALLOWED_FEATURES, - "loongarch64" => LOONGARCH_ALLOWED_FEATURES, - "s390x" => IBMZ_ALLOWED_FEATURES, + "arm" => ARM_KNOWN_FEATURES, + "aarch64" | "arm64ec" => AARCH64_KNOWN_FEATURES, + "x86" | "x86_64" => X86_KNOWN_FEATURES, + "hexagon" => HEXAGON_KNOWN_FEATURES, + "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_KNOWN_FEATURES, + "powerpc" | "powerpc64" => POWERPC_KNOWN_FEATURES, + "riscv32" | "riscv64" => RISCV_KNOWN_FEATURES, + "wasm32" | "wasm64" => WASM_KNOWN_FEATURES, + "bpf" => BPF_KNOWN_FEATURES, + "csky" => CSKY_KNOWN_FEATURES, + "loongarch64" => LOONGARCH_KNOWN_FEATURES, + "s390x" => IBMZ_KNOWN_FEATURES, _ => &[], } } @@ -552,7 +579,7 @@ impl super::spec::Target { base_features: impl Iterator, ) -> FxHashSet { let implied_features = self - .supported_target_features() + .known_target_features() .iter() .map(|(f, _, i)| (Symbol::intern(f), i)) .collect::>(); diff --git a/tests/ui/auxiliary/using-target-feature-unstable.rs b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs similarity index 100% rename from tests/ui/auxiliary/using-target-feature-unstable.rs rename to tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs new file mode 100644 index 0000000000000..91c56b43689e1 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs @@ -0,0 +1,12 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[target_feature(enable = "soft-float")] +//~^ERROR: cannot be toggled with +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr new file mode 100644 index 0000000000000..1178fdee95687 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr @@ -0,0 +1,8 @@ +error: target feature `soft-float` cannot be toggled with `#[target_feature]` + --> $DIR/forbidden-target-feature-attribute.rs:10:18 + | +LL | #[target_feature(enable = "soft-float")] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs new file mode 100644 index 0000000000000..16b18ecfbadd5 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-soft-float +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +fn main() {} diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr new file mode 100644 index 0000000000000..3f5930208cc14 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr @@ -0,0 +1,4 @@ +error: target feature `soft-float` cannot be toggled with `-Ctarget-feature` + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs new file mode 100644 index 0000000000000..5a40615182103 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=+soft-float +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +fn main() {} diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.stderr b/tests/ui/target-feature/forbidden-target-feature-flag.stderr new file mode 100644 index 0000000000000..3f5930208cc14 --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-flag.stderr @@ -0,0 +1,4 @@ +error: target feature `soft-float` cannot be toggled with `-Ctarget-feature` + +error: aborting due to 1 previous error + diff --git a/tests/ui/using-target-feature-unstable.rs b/tests/ui/target-feature/using-target-feature-unstable.rs similarity index 100% rename from tests/ui/using-target-feature-unstable.rs rename to tests/ui/target-feature/using-target-feature-unstable.rs