Skip to content

Commit 207bc77

Browse files
committed
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.
1 parent 6edd86d commit 207bc77

13 files changed

Lines changed: 100 additions & 163 deletions

File tree

‎compiler/rustc_codegen_gcc/messages.ftl‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ 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_tied_target_features = the target features {$features} must all be either enabled or disabled together
12-
.help = add the missing features in a `target_feature` attribute
13-
1411
codegen_gcc_unwinding_inline_asm =
1512
GCC backend does not support unwinding from inline asm
1613

‎compiler/rustc_codegen_gcc/src/attributes.rs‎

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ use rustc_attr::InstructionSetAttr;
77
#[cfg(feature = "master")]
88
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
99
use rustc_middle::ty;
10-
use rustc_span::symbol::sym;
1110

1211
usecrate::context::CodegenCx;
13-
usecrate::errors::TiedTargetFeatures;
14-
usecrate::gcc_util::{check_tied_features, to_gcc_features};
12+
usecrate::gcc_util::to_gcc_features;
1513

1614
/// Get GCC attribute for the provided inline heuristic.
1715
#[cfg(feature = "master")]
@@ -72,26 +70,10 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
7270
}
7371
}
7472

75-
let function_features = codegen_fn_attrs
73+
letmutfunction_features = codegen_fn_attrs
7674
.target_features
7775
.iter()
7876
.map(|features| features.name.as_str())
79-
.collect::<Vec<&str>>();
80-
81-
ifletSome(features) = check_tied_features(
82-
cx.tcx.sess,
83-
&function_features.iter().map(|features| (*features,true)).collect(),
84-
){
85-
let span = cx
86-
.tcx
87-
.get_attr(instance.def_id(), sym::target_feature)
88-
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
89-
cx.tcx.dcx().create_err(TiedTargetFeatures{features: features.join(", "), span }).emit();
90-
return;
91-
}
92-
93-
letmut function_features = function_features
94-
.iter()
9577
.flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter())
9678
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match*x {
9779
InstructionSetAttr::ArmA32 => "-thumb-mode",// TODO(antoyo): support removing feature.

‎compiler/rustc_codegen_gcc/src/errors.rs‎

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
use rustc_errors::{Diag,DiagCtxtHandle,Diagnostic,EmissionGuarantee,Level};
21
use rustc_macros::{Diagnostic,Subdiagnostic};
32
use rustc_span::Span;
43

5-
usecrate::fluent_generated as fluent;
6-
74
#[derive(Diagnostic)]
85
#[diag(codegen_gcc_unknown_ctarget_feature_prefix)]
96
#[note]
@@ -45,15 +42,6 @@ pub(crate) struct InvalidMinimumAlignment {
4542
puberr:String,
4643
}
4744

48-
#[derive(Diagnostic)]
49-
#[diag(codegen_gcc_tied_target_features)]
50-
#[help]
51-
pub(crate)structTiedTargetFeatures{
52-
#[primary_span]
53-
pubspan:Span,
54-
pubfeatures:String,
55-
}
56-
5745
#[derive(Diagnostic)]
5846
#[diag(codegen_gcc_copy_bitcode)]
5947
pub(crate)structCopyBitcode{
@@ -78,27 +66,3 @@ pub(crate) struct LtoDylib;
7866
pub(crate)structLtoBitcodeFromRlib{
7967
pubgcc_err:String,
8068
}
81-
82-
pub(crate)structTargetFeatureDisableOrEnable<'a>{
83-
pubfeatures:&'a[&'astr],
84-
pubspan:Option<Span>,
85-
pubmissing_features:Option<MissingFeatures>,
86-
}
87-
88-
#[derive(Subdiagnostic)]
89-
#[help(codegen_gcc_missing_features)]
90-
pub(crate)structMissingFeatures;
91-
92-
impl<G:EmissionGuarantee>Diagnostic<'_,G>forTargetFeatureDisableOrEnable<'_>{
93-
fninto_diag(self,dcx:DiagCtxtHandle<'_>,level:Level) -> Diag<'_,G>{
94-
letmut diag = Diag::new(dcx, level, fluent::codegen_gcc_target_feature_disable_or_enable);
95-
ifletSome(span) = self.span{
96-
diag.span(span);
97-
};
98-
ifletSome(missing_features) = self.missing_features{
99-
diag.subdiagnostic(missing_features);
100-
}
101-
diag.arg("features",self.features.join(", "));
102-
diag
103-
}
104-
}

‎compiler/rustc_codegen_gcc/src/gcc_util.rs‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
#[cfg(feature = "master")]
22
use gccjit::Context;
3+
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
4+
use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
35
use rustc_data_structures::fx::FxHashMap;
46
use rustc_middle::bug;
57
use rustc_session::Session;
68
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
79
use smallvec::{SmallVec, smallvec};
810

9-
usecrate::errors::{
10-
PossibleFeature,TargetFeatureDisableOrEnable,UnknownCTargetFeature,
11-
UnknownCTargetFeaturePrefix,
12-
};
11+
usecrate::errors::{PossibleFeature,UnknownCTargetFeature,UnknownCTargetFeaturePrefix};
1312

1413
/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
1514
/// `--target` and similar).
@@ -185,23 +184,6 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
185184
}
186185
}
187186

188-
// Given a map from target_features to whether they are enabled or disabled,
189-
// ensure only valid combinations are allowed.
190-
pubfncheck_tied_features(
191-
sess:&Session,
192-
features:&FxHashMap<&str,bool>,
193-
) -> Option<&'static[&'staticstr]>{
194-
for tied in sess.target.tied_target_features(){
195-
// Tied features must be set to the same value, or not set at all
196-
letmut tied_iter = tied.iter();
197-
let enabled = features.get(tied_iter.next().unwrap());
198-
if tied_iter.any(|feature| enabled != features.get(feature)){
199-
returnSome(tied);
200-
}
201-
}
202-
None
203-
}
204-
205187
fnarch_to_gcc(name:&str) -> &str{
206188
match name {
207189
"M68020" => "68020",

‎compiler/rustc_codegen_llvm/messages.ftl‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit
3333
codegen_llvm_mismatch_data_layout =
3434
data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
3535
36-
codegen_llvm_missing_features =
37-
add the missing features in a `target_feature` attribute
38-
3936
codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
4037
codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
4138
@@ -63,9 +60,6 @@ codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}
6360
codegen_llvm_symbol_already_defined =
6461
symbol `{$symbol_name}` is already defined
6562
66-
codegen_llvm_target_feature_disable_or_enable =
67-
the target features {$features} must all be either enabled or disabled together
68-
6963
codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
7064
codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
7165

‎compiler/rustc_codegen_llvm/src/attributes.rs‎

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ use rustc_hir::def_id::DefId;
66
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags,PatchableFunctionEntry};
77
use rustc_middle::ty::{self,TyCtxt};
88
use rustc_session::config::{BranchProtection,FunctionReturn,OptLevel,PAuthKey,PacRet};
9-
use rustc_span::symbol::sym;
109
use rustc_target::spec::{FramePointer,SanitizerSet,StackProbeType,StackProtector};
1110
use smallvec::SmallVec;
1211

1312
usecrate::context::CodegenCx;
14-
usecrate::errors::{MissingFeatures,SanitizerMemtagRequiresMte,TargetFeatureDisableOrEnable};
13+
usecrate::errors::SanitizerMemtagRequiresMte;
1514
usecrate::llvm::AttributePlace::Function;
1615
usecrate::llvm::{self,AllocKindFlags,Attribute,AttributeKind,AttributePlace,MemoryEffects};
1716
usecrate::value::Value;
@@ -502,26 +501,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
502501
let function_features =
503502
codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::<Vec<&str>>();
504503

505-
ifletSome(f) = llvm_util::check_tied_features(
506-
cx.tcx.sess,
507-
&function_features.iter().map(|f| (*f,true)).collect(),
508-
){
509-
let span = cx
510-
.tcx
511-
.get_attrs(instance.def_id(), sym::target_feature)
512-
.next()
513-
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
514-
cx.tcx
515-
.dcx()
516-
.create_err(TargetFeatureDisableOrEnable{
517-
features: f,
518-
span:Some(span),
519-
missing_features:Some(MissingFeatures),
520-
})
521-
.emit();
522-
return;
523-
}
524-
525504
let function_features = function_features
526505
.iter()
527506
// Convert to LLVMFeatures and filter out unavailable ones

‎compiler/rustc_codegen_llvm/src/errors.rs‎

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -80,30 +80,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
8080
}
8181
}
8282

83-
pub(crate)structTargetFeatureDisableOrEnable<'a>{
84-
pubfeatures:&'a[&'astr],
85-
pubspan:Option<Span>,
86-
pubmissing_features:Option<MissingFeatures>,
87-
}
88-
89-
#[derive(Subdiagnostic)]
90-
#[help(codegen_llvm_missing_features)]
91-
pub(crate)structMissingFeatures;
92-
93-
impl<G:EmissionGuarantee>Diagnostic<'_,G>forTargetFeatureDisableOrEnable<'_>{
94-
fninto_diag(self,dcx:DiagCtxtHandle<'_>,level:Level) -> Diag<'_,G>{
95-
letmut diag = Diag::new(dcx, level, fluent::codegen_llvm_target_feature_disable_or_enable);
96-
ifletSome(span) = self.span{
97-
diag.span(span);
98-
};
99-
ifletSome(missing_features) = self.missing_features{
100-
diag.subdiagnostic(missing_features);
101-
}
102-
diag.arg("features",self.features.join(", "));
103-
diag
104-
}
105-
}
106-
10783
#[derive(Diagnostic)]
10884
#[diag(codegen_llvm_lto_disallowed)]
10985
pub(crate)structLtoDisallowed;

‎compiler/rustc_codegen_llvm/src/llvm_util.rs‎

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{ptr, slice, str};
66

77
use libc::c_int;
88
use rustc_codegen_ssa::base::wants_wasm_eh;
9+
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
910
use rustc_data_structures::fx::{FxHashMap,FxHashSet};
1011
use rustc_data_structures::small_c_str::SmallCStr;
1112
use rustc_data_structures::unord::UnordSet;
@@ -19,8 +20,8 @@ use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATU
1920

2021
usecrate::back::write::create_informational_target_machine;
2122
usecrate::errors::{
22-
FixedX18InvalidArch,InvalidTargetFeaturePrefix,PossibleFeature,TargetFeatureDisableOrEnable,
23-
UnknownCTargetFeature,UnknownCTargetFeaturePrefix,UnstableCTargetFeature,
23+
FixedX18InvalidArch,InvalidTargetFeaturePrefix,PossibleFeature,UnknownCTargetFeature,
24+
UnknownCTargetFeaturePrefix,UnstableCTargetFeature,
2425
};
2526
usecrate::llvm;
2627

@@ -272,25 +273,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
272273
}
273274
}
274275

275-
/// Given a map from target_features to whether they are enabled or disabled,
276-
/// ensure only valid combinations are allowed.
277-
pub(crate)fncheck_tied_features(
278-
sess:&Session,
279-
features:&FxHashMap<&str,bool>,
280-
) -> Option<&'static[&'staticstr]>{
281-
if !features.is_empty(){
282-
for tied in sess.target.tied_target_features(){
283-
// Tied features must be set to the same value, or not set at all
284-
letmut tied_iter = tied.iter();
285-
let enabled = features.get(tied_iter.next().unwrap());
286-
if tied_iter.any(|f| enabled != features.get(f)){
287-
returnSome(tied);
288-
}
289-
}
290-
}
291-
None
292-
}
293-
294276
/// Used to generate cfg variables and apply features
295277
/// Must express features in the way Rust understands them
296278
pubfntarget_features(sess:&Session,allow_unstable:bool) -> Vec<Symbol>{
@@ -676,7 +658,7 @@ pub(crate) fn global_llvm_features(
676658
features.extend(feats);
677659

678660
if diagnostics && letSome(f) = check_tied_features(sess,&featsmap){
679-
sess.dcx().emit_err(TargetFeatureDisableOrEnable{
661+
sess.dcx().emit_err(rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable{
680662
features: f,
681663
span:None,
682664
missing_features:None,

‎compiler/rustc_codegen_ssa/messages.ftl‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ codegen_ssa_metadata_object_file_write = error writing metadata object file: {$e
183183
184184
codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
185185
186+
codegen_ssa_missing_features = add the missing features in a `target_feature` attribute
187+
186188
codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
187189
188190
codegen_ssa_missing_query_depgraph =
@@ -238,6 +240,9 @@ codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` fa
238240
239241
codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
240242
243+
codegen_ssa_target_feature_disable_or_enable =
244+
the target features {$features} must all be either enabled or disabled together
245+
241246
codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
242247
.label = cannot be applied to safe trait method
243248
.label_def = not an `unsafe` function

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs‎

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{MetaItemKind,NestedMetaItem, ast, attr};
22
use rustc_attr::{InlineAttr,InstructionSetAttr,OptimizeAttr, list_contains_name};
3+
use rustc_data_structures::fx::FxHashMap;
34
use rustc_errors::codes::*;
45
use rustc_errors::{DiagMessage,SubdiagMessage, struct_span_code_err};
56
use rustc_hir as hir;
@@ -13,13 +14,13 @@ use rustc_middle::middle::codegen_fn_attrs::{
1314
use rustc_middle::mir::mono::Linkage;
1415
use rustc_middle::query::Providers;
1516
use rustc_middle::ty::{selfas ty,TyCtxt};
16-
use rustc_session::lint;
1717
use rustc_session::parse::feature_err;
18+
use rustc_session::{Session, lint};
1819
use rustc_span::symbol::Ident;
1920
use rustc_span::{Span, sym};
2021
use rustc_target::spec::{SanitizerSet, abi};
2122

22-
usecrate::errors;
23+
usecrate::errors::{self,MissingFeatures,TargetFeatureDisableOrEnable};
2324
usecrate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
2425

2526
fnlinkage_by_name(tcx:TyCtxt<'_>,def_id:LocalDefId,name:&str) -> Linkage{
@@ -662,9 +663,49 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
662663
}
663664
}
664665

666+
ifletSome(features) = check_tied_features(
667+
tcx.sess,
668+
&codegen_fn_attrs
669+
.target_features
670+
.iter()
671+
.map(|features| (features.name.as_str(),true))
672+
.collect(),
673+
){
674+
let span = tcx
675+
.get_attrs(did, sym::target_feature)
676+
.next()
677+
.map_or_else(|| tcx.def_span(did), |a| a.span);
678+
tcx.dcx()
679+
.create_err(TargetFeatureDisableOrEnable{
680+
features,
681+
span:Some(span),
682+
missing_features:Some(MissingFeatures),
683+
})
684+
.emit();
685+
}
686+
665687
codegen_fn_attrs
666688
}
667689

690+
/// Given a map from target_features to whether they are enabled or disabled, ensure only valid
691+
/// combinations are allowed.
692+
pubfncheck_tied_features(
693+
sess:&Session,
694+
features:&FxHashMap<&str,bool>,
695+
) -> Option<&'static[&'staticstr]>{
696+
if !features.is_empty(){
697+
for tied in sess.target.tied_target_features(){
698+
// Tied features must be set to the same value, or not set at all
699+
letmut tied_iter = tied.iter();
700+
let enabled = features.get(tied_iter.next().unwrap());
701+
if tied_iter.any(|f| enabled != features.get(f)){
702+
returnSome(tied);
703+
}
704+
}
705+
}
706+
None
707+
}
708+
668709
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
669710
/// applied to the method prototype.
670711
fnshould_inherit_track_caller(tcx:TyCtxt<'_>,def_id:DefId) -> bool{

0 commit comments

Comments
 (0)