@@ -308,19 +308,10 @@ pub fn check_tied_features(
308
308
/// Used to generate cfg variables and apply features
309
309
/// Must express features in the way Rust understands them
310
310
pub fn target_features ( sess : & Session , allow_unstable : bool ) -> Vec < Symbol > {
311
- let rust_features = sess
312
- . target
313
- . supported_target_features ( )
314
- . iter ( )
315
- . map ( |( feature, _, _) | {
316
- ( to_llvm_features ( sess, feature) . llvm_feature_name , Symbol :: intern ( feature) )
317
- } )
318
- . collect :: < FxHashMap < _ , _ > > ( ) ;
319
-
320
311
let mut features = FxHashSet :: default ( ) ;
321
312
322
313
// Add base features for the target
323
- let target_machine = create_informational_target_machine ( sess, false ) ;
314
+ let target_machine = create_informational_target_machine ( sess, true ) ;
324
315
features. extend (
325
316
sess. target
326
317
. supported_target_features ( )
@@ -343,13 +334,16 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
343
334
) ;
344
335
345
336
// Add enabled features
346
- for llvm_feature in global_llvm_features ( sess, false ) {
347
- let ( add, llvm_feature) = llvm_feature. split_at ( 1 ) ;
348
- let feature =
349
- rust_features. get ( llvm_feature) . cloned ( ) . unwrap_or ( Symbol :: intern ( llvm_feature) ) ;
350
- if add == "+" {
337
+ for ( enabled, feature) in
338
+ sess. opts . cg . target_feature . split ( ',' ) . filter_map ( |s| match s. chars ( ) . next ( ) {
339
+ Some ( '+' ) => Some ( ( true , Symbol :: intern ( & s[ 1 ..] ) ) ) ,
340
+ Some ( '-' ) => Some ( ( false , Symbol :: intern ( & s[ 1 ..] ) ) ) ,
341
+ _ => None ,
342
+ } )
343
+ {
344
+ if enabled {
351
345
features. extend ( sess. target . implied_target_features ( std:: iter:: once ( feature) ) ) ;
352
- } else if add == "-" {
346
+ } else {
353
347
features. remove ( & feature) ;
354
348
}
355
349
}
@@ -475,7 +469,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
475
469
476
470
pub ( crate ) fn print ( req : & PrintRequest , mut out : & mut String , sess : & Session ) {
477
471
require_inited ( ) ;
478
- let tm = create_informational_target_machine ( sess, true ) ;
472
+ let tm = create_informational_target_machine ( sess, false ) ;
479
473
match req. kind {
480
474
PrintKind :: TargetCPUs => {
481
475
// SAFETY generate a C compatible string from a byte slice to pass
@@ -523,7 +517,11 @@ pub fn target_cpu(sess: &Session) -> &str {
523
517
524
518
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
525
519
/// `--target` and similar).
526
- pub ( crate ) fn global_llvm_features ( sess : & Session , diagnostics : bool ) -> Vec < String > {
520
+ pub ( crate ) fn global_llvm_features (
521
+ sess : & Session ,
522
+ diagnostics : bool ,
523
+ only_base_features : bool ,
524
+ ) -> Vec < String > {
527
525
// Features that come earlier are overridden by conflicting features later in the string.
528
526
// Typically we'll want more explicit settings to override the implicit ones, so:
529
527
//
@@ -583,96 +581,109 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
583
581
}
584
582
585
583
// -Ctarget-features
586
- let supported_features = sess. target . supported_target_features ( ) ;
587
- let ( llvm_major, _, _) = get_version ( ) ;
588
- let mut featsmap = FxHashMap :: default ( ) ;
589
- let feats = sess
590
- . opts
591
- . cg
592
- . target_feature
593
- . split ( ',' )
594
- . filter_map ( |s| {
595
- let enable_disable = match s. chars ( ) . next ( ) {
596
- None => return None ,
597
- Some ( c @ ( '+' | '-' ) ) => c,
598
- Some ( _) => {
599
- if diagnostics {
600
- sess. dcx ( ) . emit_warn ( UnknownCTargetFeaturePrefix { feature : s } ) ;
584
+ if !only_base_features {
585
+ let supported_features = sess. target . supported_target_features ( ) ;
586
+ let ( llvm_major, _, _) = get_version ( ) ;
587
+ let mut featsmap = FxHashMap :: default ( ) ;
588
+ let feats = sess
589
+ . opts
590
+ . cg
591
+ . target_feature
592
+ . split ( ',' )
593
+ . filter_map ( |s| {
594
+ let enable_disable = match s. chars ( ) . next ( ) {
595
+ None => return None ,
596
+ Some ( c @ ( '+' | '-' ) ) => c,
597
+ Some ( _) => {
598
+ if diagnostics {
599
+ sess. dcx ( ) . emit_warn ( UnknownCTargetFeaturePrefix { feature : s } ) ;
600
+ }
601
+ return None ;
601
602
}
602
- return None ;
603
- }
604
- } ;
603
+ } ;
605
604
606
- let feature = backend_feature_name ( sess, s) ?;
607
- // Warn against use of LLVM specific feature names and unstable features on the CLI.
608
- if diagnostics {
609
- let feature_state = supported_features. iter ( ) . find ( |& & ( v, _, _) | v == feature) ;
610
- if feature_state. is_none ( ) {
611
- let rust_feature =
612
- supported_features. iter ( ) . find_map ( |& ( rust_feature, _, _) | {
613
- let llvm_features = to_llvm_features ( sess, rust_feature) ;
614
- if llvm_features. contains ( feature)
615
- && !llvm_features. contains ( rust_feature)
616
- {
617
- Some ( rust_feature)
618
- } else {
619
- None
605
+ let feature = backend_feature_name ( sess, s) ?;
606
+ // Warn against use of LLVM specific feature names and unstable features on the CLI.
607
+ if diagnostics {
608
+ let feature_state = supported_features. iter ( ) . find ( |& & ( v, _, _) | v == feature) ;
609
+ if feature_state. is_none ( ) {
610
+ let rust_feature =
611
+ supported_features. iter ( ) . find_map ( |& ( rust_feature, _, _) | {
612
+ let llvm_features = to_llvm_features ( sess, rust_feature) ;
613
+ if llvm_features. contains ( feature)
614
+ && !llvm_features. contains ( rust_feature)
615
+ {
616
+ Some ( rust_feature)
617
+ } else {
618
+ None
619
+ }
620
+ } ) ;
621
+ let unknown_feature = if let Some ( rust_feature) = rust_feature {
622
+ UnknownCTargetFeature {
623
+ feature,
624
+ rust_feature : PossibleFeature :: Some { rust_feature } ,
620
625
}
621
- } ) ;
622
- let unknown_feature = if let Some ( rust_feature) = rust_feature {
623
- UnknownCTargetFeature {
624
- feature,
625
- rust_feature : PossibleFeature :: Some { rust_feature } ,
626
- }
627
- } else {
628
- UnknownCTargetFeature { feature, rust_feature : PossibleFeature :: None }
629
- } ;
630
- sess. dcx ( ) . emit_warn ( unknown_feature) ;
631
- } else if feature_state
632
- . is_some_and ( |( _name, feature_gate, _implied) | !feature_gate. is_stable ( ) )
633
- {
634
- // An unstable feature. Warn about using it.
635
- sess. dcx ( ) . emit_warn ( UnstableCTargetFeature { feature } ) ;
626
+ } else {
627
+ UnknownCTargetFeature { feature, rust_feature : PossibleFeature :: None }
628
+ } ;
629
+ sess. dcx ( ) . emit_warn ( unknown_feature) ;
630
+ } else if feature_state
631
+ . is_some_and ( |( _name, feature_gate, _implied) | !feature_gate. is_stable ( ) )
632
+ {
633
+ // An unstable feature. Warn about using it.
634
+ sess. dcx ( ) . emit_warn ( UnstableCTargetFeature { feature } ) ;
635
+ }
636
636
}
637
- }
638
637
639
- if diagnostics {
640
- // FIXME(nagisa): figure out how to not allocate a full hashset here.
641
- featsmap. insert ( feature, enable_disable == '+' ) ;
642
- }
638
+ if diagnostics {
639
+ // FIXME(nagisa): figure out how to not allocate a full hashset here.
640
+ featsmap. insert ( feature, enable_disable == '+' ) ;
641
+ }
643
642
644
- // rustc-specific features do not get passed down to LLVM…
645
- if RUSTC_SPECIFIC_FEATURES . contains ( & feature) {
646
- return None ;
647
- }
643
+ // rustc-specific features do not get passed down to LLVM…
644
+ if RUSTC_SPECIFIC_FEATURES . contains ( & feature) {
645
+ return None ;
646
+ }
648
647
649
- // if the target-feature is "backchain" and LLVM version is greater than 18
650
- // then we also need to add "+backchain" to the target-features attribute.
651
- // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
652
- if feature == "backchain" && llvm_major < 18 {
653
- return None ;
654
- }
655
- // ... otherwise though we run through `to_llvm_features` when
656
- // passing requests down to LLVM. This means that all in-language
657
- // features also work on the command line instead of having two
658
- // different names when the LLVM name and the Rust name differ.
659
- let llvm_feature = to_llvm_features ( sess, feature) ;
660
-
661
- Some (
662
- std:: iter:: once ( format ! ( "{}{}" , enable_disable, llvm_feature. llvm_feature_name) )
663
- . chain ( llvm_feature. dependency . into_iter ( ) . filter_map ( move |feat| {
664
- match ( enable_disable, feat) {
648
+ // if the target-feature is "backchain" and LLVM version is greater than 18
649
+ // then we also need to add "+backchain" to the target-features attribute.
650
+ // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
651
+ if feature == "backchain" && llvm_major < 18 {
652
+ return None ;
653
+ }
654
+ // ... otherwise though we run through `to_llvm_features` when
655
+ // passing requests down to LLVM. This means that all in-language
656
+ // features also work on the command line instead of having two
657
+ // different names when the LLVM name and the Rust name differ.
658
+ let llvm_feature = to_llvm_features ( sess, feature) ;
659
+
660
+ Some (
661
+ std:: iter:: once ( format ! (
662
+ "{}{}" ,
663
+ enable_disable, llvm_feature. llvm_feature_name
664
+ ) )
665
+ . chain ( llvm_feature. dependency . into_iter ( ) . filter_map (
666
+ move |feat| match ( enable_disable, feat) {
665
667
( '-' | '+' , TargetFeatureFoldStrength :: Both ( f) )
666
668
| ( '+' , TargetFeatureFoldStrength :: EnableOnly ( f) ) => {
667
669
Some ( format ! ( "{enable_disable}{f}" ) )
668
670
}
669
671
_ => None ,
670
- }
671
- } ) ) ,
672
- )
673
- } )
674
- . flatten ( ) ;
675
- features. extend ( feats) ;
672
+ } ,
673
+ ) ) ,
674
+ )
675
+ } )
676
+ . flatten ( ) ;
677
+ features. extend ( feats) ;
678
+
679
+ if diagnostics && let Some ( f) = check_tied_features ( sess, & featsmap) {
680
+ sess. dcx ( ) . emit_err ( TargetFeatureDisableOrEnable {
681
+ features : f,
682
+ span : None ,
683
+ missing_features : None ,
684
+ } ) ;
685
+ }
686
+ }
676
687
677
688
// -Zfixed-x18
678
689
if sess. opts . unstable_opts . fixed_x18 {
@@ -683,14 +694,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
683
694
}
684
695
}
685
696
686
- if diagnostics && let Some ( f) = check_tied_features ( sess, & featsmap) {
687
- sess. dcx ( ) . emit_err ( TargetFeatureDisableOrEnable {
688
- features : f,
689
- span : None ,
690
- missing_features : None ,
691
- } ) ;
692
- }
693
-
694
697
features
695
698
}
696
699
0 commit comments