@@ -2,8 +2,8 @@ use crate::back::write::create_informational_target_machine;
22use crate :: { llvm, llvm_util} ;
33use libc:: c_int;
44use libloading:: Library ;
5- use rustc_codegen_ssa:: target_features:: supported_target_features;
6- use rustc_data_structures:: fx:: FxHashSet ;
5+ use rustc_codegen_ssa:: target_features:: { supported_target_features, tied_target_features } ;
6+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
77use rustc_fs_util:: path_to_c_string;
88use rustc_middle:: bug;
99use rustc_session:: config:: PrintRequest ;
@@ -191,10 +191,30 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
191191 ( "aarch64" , "frintts" ) => vec ! [ "fptoint" ] ,
192192 ( "aarch64" , "fcma" ) => vec ! [ "complxnum" ] ,
193193 ( "aarch64" , "pmuv3" ) => vec ! [ "perfmon" ] ,
194+ ( "aarch64" , "paca" ) => vec ! [ "pauth" ] ,
195+ ( "aarch64" , "pacg" ) => vec ! [ "pauth" ] ,
194196 ( _, s) => vec ! [ s] ,
195197 }
196198}
197199
200+ // Given a map from target_features to whether they are enabled or disabled,
201+ // ensure only valid combinations are allowed.
202+ pub fn check_tied_features (
203+ sess : & Session ,
204+ features : & FxHashMap < & str , bool > ,
205+ ) -> Option < & ' static [ & ' static str ] > {
206+ for tied in tied_target_features ( sess) {
207+ // Tied features must be set to the same value, or not set at all
208+ let mut tied_iter = tied. iter ( ) ;
209+ let enabled = features. get ( tied_iter. next ( ) . unwrap ( ) ) ;
210+
211+ if tied_iter. any ( |f| enabled != features. get ( f) ) {
212+ return Some ( tied) ;
213+ }
214+ }
215+ None
216+ }
217+
198218pub fn target_features ( sess : & Session ) -> Vec < Symbol > {
199219 let target_machine = create_informational_target_machine ( sess) ;
200220 supported_target_features ( sess)
@@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
395415 Some ( _) | None => { }
396416 } ;
397417
418+ fn strip ( s : & str ) -> & str {
419+ s. strip_prefix ( & [ '+' , '-' ] ) . unwrap_or ( s)
420+ }
421+
398422 let filter = |s : & str | {
399423 if s. is_empty ( ) {
400424 return vec ! [ ] ;
401425 }
402- let feature = if s. starts_with ( '+' ) || s. starts_with ( '-' ) {
403- & s[ 1 ..]
404- } else {
426+ let feature = strip ( s) ;
427+ if feature == s {
405428 return vec ! [ s. to_string( ) ] ;
406- } ;
429+ }
430+
407431 // Rustc-specific feature requests like `+crt-static` or `-crt-static`
408432 // are not passed down to LLVM.
409433 if RUSTC_SPECIFIC_FEATURES . contains ( & feature) {
@@ -420,8 +444,17 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
420444 features. extend ( sess. target . features . split ( ',' ) . flat_map ( & filter) ) ;
421445
422446 // -Ctarget-features
423- features. extend ( sess. opts . cg . target_feature . split ( ',' ) . flat_map ( & filter) ) ;
424-
447+ let feats: Vec < & str > = sess. opts . cg . target_feature . split ( ',' ) . collect ( ) ;
448+ // LLVM enables based on the last occurence of a feature
449+ if let Some ( f) =
450+ check_tied_features ( sess, & feats. iter ( ) . map ( |f| ( strip ( f) , !f. starts_with ( "-" ) ) ) . collect ( ) )
451+ {
452+ sess. err ( & format ! (
453+ "Target features {} must all be enabled or disabled together" ,
454+ f. join( ", " )
455+ ) ) ;
456+ }
457+ features. extend ( feats. iter ( ) . flat_map ( |& f| filter ( f) ) ) ;
425458 features
426459}
427460
0 commit comments