@@ -22,7 +22,7 @@ use rustc_target::spec::{
2222use crate :: config:: * ;
2323use crate :: search_paths:: SearchPath ;
2424use crate :: utils:: NativeLib ;
25- use crate :: { EarlyDiagCtxt , lint} ;
25+ use crate :: { EarlyDiagCtxt , Session , lint} ;
2626
2727macro_rules! insert {
2828 ( $opt_name: ident, $opt_expr: expr, $sub_hashes: expr) => {
@@ -85,6 +85,42 @@ pub struct TargetModifier {
8585
8686mod target_modifier_consistency_check {
8787 use super :: * ;
88+ pub ( super ) fn target_feature (
89+ sess : & Session ,
90+ l : & TargetModifier ,
91+ r : Option < & TargetModifier > ,
92+ ) -> bool {
93+ fn parse < ' val > ( session : & Session , val : & ' val TargetModifier ) -> Vec < & ' val str > {
94+ let mut target_features = Vec :: new ( ) ;
95+
96+ for feature in val. value_name . split ( ',' ) {
97+ if let Some ( base_feature) = feature. strip_prefix ( '+' ) {
98+ if session. target . rust_target_features ( ) . iter ( ) . any (
99+ |( name, _, _, target_modifier) | base_feature == * name && * target_modifier,
100+ ) {
101+ target_features. push ( base_feature) ;
102+ }
103+ } else if let Some ( base_feature) = feature. strip_prefix ( '-' ) {
104+ if session. target . rust_target_features ( ) . iter ( ) . any (
105+ |( name, _, _, target_modifier) | base_feature == * name && * target_modifier,
106+ ) {
107+ for ( index, target_feature) in target_features. iter ( ) . enumerate ( ) {
108+ if * target_feature == base_feature {
109+ target_features. remove ( index) ;
110+ break ;
111+ }
112+ }
113+ }
114+ }
115+ }
116+
117+ target_features
118+ }
119+
120+ let l = parse ( sess, l) ;
121+
122+ if let Some ( r) = r { l == parse ( sess, r) } else { l. is_empty ( ) }
123+ }
88124 pub ( super ) fn sanitizer ( l : & TargetModifier , r : Option < & TargetModifier > ) -> bool {
89125 let mut lparsed: SanitizerSet = Default :: default ( ) ;
90126 let lval = if l. value_name . is_empty ( ) { None } else { Some ( l. value_name . as_str ( ) ) } ;
@@ -133,21 +169,25 @@ impl TargetModifier {
133169 }
134170 // Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`)
135171 // When other is None, consistency with default value is checked
136- pub fn consistent ( & self , opts : & Options , other : Option < & TargetModifier > ) -> bool {
172+ pub fn consistent ( & self , sess : & Session , other : Option < & TargetModifier > ) -> bool {
137173 assert ! ( other. is_none( ) || self . opt == other. unwrap( ) . opt) ;
138174 match self . opt {
175+ OptionsTargetModifiers :: CodegenOptions (
176+ CodegenOptionsTargetModifiers :: target_feature,
177+ ) => {
178+ return target_modifier_consistency_check:: target_feature ( sess, self , other) ;
179+ }
139180 OptionsTargetModifiers :: UnstableOptions ( unstable) => match unstable {
140181 UnstableOptionsTargetModifiers :: sanitizer => {
141182 return target_modifier_consistency_check:: sanitizer ( self , other) ;
142183 }
143184 UnstableOptionsTargetModifiers :: sanitizer_cfi_normalize_integers => {
144185 return target_modifier_consistency_check:: sanitizer_cfi_normalize_integers (
145- opts, self , other,
186+ & sess . opts , self , other,
146187 ) ;
147188 }
148189 _ => { }
149190 } ,
150- _ => { }
151191 } ;
152192 match other {
153193 Some ( other) => self . extend ( ) . tech_value == other. extend ( ) . tech_value ,
@@ -2172,7 +2212,7 @@ options! {
21722212 "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')" ) ,
21732213 target_cpu: Option <String > = ( None , parse_opt_string, [ TRACKED ] ,
21742214 "select target processor (`rustc --print target-cpus` for details)" ) ,
2175- target_feature: String = ( String :: new( ) , parse_target_feature, [ TRACKED ] ,
2215+ target_feature: String = ( String :: new( ) , parse_target_feature, [ TRACKED TARGET_MODIFIER ] ,
21762216 "target specific attributes. (`rustc --print target-features` for details). \
21772217 This feature is unsafe.") ,
21782218 unsafe_allow_abi_mismatch: Vec <String > = ( Vec :: new( ) , parse_comma_list, [ UNTRACKED ] ,
0 commit comments