1
Fork 0

codegen_ssa: consolidate tied feature checking

`rustc_codegen_llvm` and `rustc_codegen_gcc` duplicated logic for
checking if tied target features were partially enabled. This commit
consolidates these checks into `rustc_codegen_ssa` in the
`codegen_fn_attrs` query, which also is run pre-monomorphisation for
each function, which ensures that this check is run for unused functions,
as would be expected.
This commit is contained in:
David Wood 2024-09-11 13:57:12 +01:00
parent 6edd86d58e
commit 207bc77e15
No known key found for this signature in database
13 changed files with 100 additions and 163 deletions

View file

@ -183,6 +183,8 @@ codegen_ssa_metadata_object_file_write = error writing metadata object file: {$e
codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
codegen_ssa_missing_features = add the missing features in a `target_feature` attribute
codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
codegen_ssa_missing_query_depgraph =
@ -238,6 +240,9 @@ codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` fa
codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
codegen_ssa_target_feature_disable_or_enable =
the target features {$features} must all be either enabled or disabled together
codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
.label = cannot be applied to safe trait method
.label_def = not an `unsafe` function

View file

@ -1,5 +1,6 @@
use rustc_ast::{MetaItemKind, NestedMetaItem, ast, attr};
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::codes::*;
use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
use rustc_hir as hir;
@ -13,13 +14,13 @@ use rustc_middle::middle::codegen_fn_attrs::{
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::{Session, lint};
use rustc_span::symbol::Ident;
use rustc_span::{Span, sym};
use rustc_target::spec::{SanitizerSet, abi};
use crate::errors;
use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable};
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
@ -662,9 +663,49 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
}
if let Some(features) = check_tied_features(
tcx.sess,
&codegen_fn_attrs
.target_features
.iter()
.map(|features| (features.name.as_str(), true))
.collect(),
) {
let span = tcx
.get_attrs(did, sym::target_feature)
.next()
.map_or_else(|| tcx.def_span(did), |a| a.span);
tcx.dcx()
.create_err(TargetFeatureDisableOrEnable {
features,
span: Some(span),
missing_features: Some(MissingFeatures),
})
.emit();
}
codegen_fn_attrs
}
/// Given a map from target_features to whether they are enabled or disabled, ensure only valid
/// combinations are allowed.
pub fn check_tied_features(
sess: &Session,
features: &FxHashMap<&str, bool>,
) -> Option<&'static [&'static str]> {
if !features.is_empty() {
for tied in sess.target.tied_target_features() {
// Tied features must be set to the same value, or not set at all
let mut tied_iter = tied.iter();
let enabled = features.get(tied_iter.next().unwrap());
if tied_iter.any(|f| enabled != features.get(f)) {
return Some(tied);
}
}
}
None
}
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {

View file

@ -9,7 +9,7 @@ use rustc_errors::codes::*;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
};
use rustc_macros::Diagnostic;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutError;
use rustc_span::{Span, Symbol};
@ -1068,3 +1068,27 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> {
pub lib_name: &'a str,
pub error: String,
}
pub struct TargetFeatureDisableOrEnable<'a> {
pub features: &'a [&'a str],
pub span: Option<Span>,
pub missing_features: Option<MissingFeatures>,
}
#[derive(Subdiagnostic)]
#[help(codegen_ssa_missing_features)]
pub struct MissingFeatures;
impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable);
if let Some(span) = self.span {
diag.span(span);
};
if let Some(missing_features) = self.missing_features {
diag.subdiagnostic(missing_features);
}
diag.arg("features", self.features.join(", "));
diag
}
}