@@ -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,53 @@ 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 < ' a > ( session : & ' a Session , val : & ' a TargetModifier ) -> Vec < & ' a str > {
94+ let mut target_features = Vec :: new ( ) ;
95+
96+ for feature in session
97+ . target_features
98+ . iter ( )
99+ . map ( |symbol| symbol. as_str ( ) )
100+ . chain ( val. value_name . split ( ',' ) )
101+ {
102+ if let Some ( feature) = feature. strip_prefix ( '+' ) {
103+ if session
104+ . target
105+ . rust_target_features ( )
106+ . iter ( )
107+ . any ( |( name, _, _, target_modifier) | feature == * name && * target_modifier)
108+ {
109+ target_features. push ( feature) ;
110+ }
111+ } else if let Some ( feature) = feature. strip_prefix ( '-' ) {
112+ if session
113+ . target
114+ . rust_target_features ( )
115+ . iter ( )
116+ . any ( |( name, _, _, target_modifier) | feature == * name && * target_modifier)
117+ {
118+ for ( index, target_feature) in target_features. iter ( ) . enumerate ( ) {
119+ if * target_feature == feature {
120+ target_features. remove ( index) ;
121+ break ;
122+ }
123+ }
124+ }
125+ }
126+ }
127+
128+ target_features
129+ }
130+
131+ let l = parse ( sess, l) ;
132+
133+ if let Some ( r) = r { l == parse ( sess, r) } else { l. is_empty ( ) }
134+ }
88135 pub ( super ) fn sanitizer ( l : & TargetModifier , r : Option < & TargetModifier > ) -> bool {
89136 let mut lparsed: SanitizerSet = Default :: default ( ) ;
90137 let lval = if l. value_name . is_empty ( ) { None } else { Some ( l. value_name . as_str ( ) ) } ;
@@ -133,21 +180,25 @@ impl TargetModifier {
133180 }
134181 // Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`)
135182 // When other is None, consistency with default value is checked
136- pub fn consistent ( & self , opts : & Options , other : Option < & TargetModifier > ) -> bool {
183+ pub fn consistent ( & self , sess : & Session , other : Option < & TargetModifier > ) -> bool {
137184 assert ! ( other. is_none( ) || self . opt == other. unwrap( ) . opt) ;
138185 match self . opt {
186+ OptionsTargetModifiers :: CodegenOptions (
187+ CodegenOptionsTargetModifiers :: target_feature,
188+ ) => {
189+ return target_modifier_consistency_check:: target_feature ( sess, self , other) ;
190+ }
139191 OptionsTargetModifiers :: UnstableOptions ( unstable) => match unstable {
140192 UnstableOptionsTargetModifiers :: sanitizer => {
141193 return target_modifier_consistency_check:: sanitizer ( self , other) ;
142194 }
143195 UnstableOptionsTargetModifiers :: sanitizer_cfi_normalize_integers => {
144196 return target_modifier_consistency_check:: sanitizer_cfi_normalize_integers (
145- opts, self , other,
197+ & sess . opts , self , other,
146198 ) ;
147199 }
148200 _ => { }
149201 } ,
150- _ => { }
151202 } ;
152203 match other {
153204 Some ( other) => self . extend ( ) . tech_value == other. extend ( ) . tech_value ,
@@ -2172,7 +2223,7 @@ options! {
21722223 "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')" ) ,
21732224 target_cpu: Option <String > = ( None , parse_opt_string, [ TRACKED ] ,
21742225 "select target processor (`rustc --print target-cpus` for details)" ) ,
2175- target_feature: String = ( String :: new( ) , parse_target_feature, [ TRACKED ] ,
2226+ target_feature: String = ( String :: new( ) , parse_target_feature, [ TRACKED TARGET_MODIFIER ] ,
21762227 "target specific attributes. (`rustc --print target-features` for details). \
21772228 This feature is unsafe.") ,
21782229 unsafe_allow_abi_mismatch: Vec <String > = ( Vec :: new( ) , parse_comma_list, [ UNTRACKED ] ,
0 commit comments