@@ -2,8 +2,8 @@ use crate::back::write::create_informational_target_machine;
2
2
use crate :: { llvm, llvm_util} ;
3
3
use libc:: c_int;
4
4
use 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 } ;
7
7
use rustc_fs_util:: path_to_c_string;
8
8
use rustc_middle:: bug;
9
9
use rustc_session:: config:: PrintRequest ;
@@ -191,10 +191,30 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
191
191
( "aarch64" , "frintts" ) => vec ! [ "fptoint" ] ,
192
192
( "aarch64" , "fcma" ) => vec ! [ "complxnum" ] ,
193
193
( "aarch64" , "pmuv3" ) => vec ! [ "perfmon" ] ,
194
+ ( "aarch64" , "paca" ) => vec ! [ "pauth" ] ,
195
+ ( "aarch64" , "pacg" ) => vec ! [ "pauth" ] ,
194
196
( _, s) => vec ! [ s] ,
195
197
}
196
198
}
197
199
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
+
198
218
pub fn target_features ( sess : & Session ) -> Vec < Symbol > {
199
219
let target_machine = create_informational_target_machine ( sess) ;
200
220
supported_target_features ( sess)
@@ -395,15 +415,19 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
395
415
Some ( _) | None => { }
396
416
} ;
397
417
418
+ fn strip ( s : & str ) -> & str {
419
+ s. strip_prefix ( & [ '+' , '-' ] ) . unwrap_or ( s)
420
+ }
421
+
398
422
let filter = |s : & str | {
399
423
if s. is_empty ( ) {
400
424
return vec ! [ ] ;
401
425
}
402
- let feature = if s. starts_with ( '+' ) || s. starts_with ( '-' ) {
403
- & s[ 1 ..]
404
- } else {
426
+ let feature = strip ( s) ;
427
+ if feature == s {
405
428
return vec ! [ s. to_string( ) ] ;
406
- } ;
429
+ }
430
+
407
431
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
408
432
// are not passed down to LLVM.
409
433
if RUSTC_SPECIFIC_FEATURES . contains ( & feature) {
@@ -420,8 +444,17 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
420
444
features. extend ( sess. target . features . split ( ',' ) . flat_map ( & filter) ) ;
421
445
422
446
// -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) ) ) ;
425
458
features
426
459
}
427
460
0 commit comments