@@ -139,11 +139,12 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
139139 }
140140}
141141
142- /// Parse the value of ` -Ctarget-feature`, also expanding implied features,
143- /// and call the closure for each (expanded) Rust feature. If the list contains
142+ /// Parse the value of the target spec `features` field or ` -Ctarget-feature`, also expanding
143+ /// implied features, and call the closure for each (expanded) Rust feature. If the list contains
144144/// a syntactically invalid item (not starting with `+`/`-`), the error callback is invoked.
145- fn parse_rust_feature_flag < ' a > (
145+ fn parse_rust_feature_list < ' a > (
146146 sess : & ' a Session ,
147+ features : & ' a str ,
147148 err_callback : impl Fn ( & ' a str ) ,
148149 mut callback : impl FnMut (
149150 /* base_feature */ & ' a str ,
@@ -154,7 +155,7 @@ fn parse_rust_feature_flag<'a>(
154155 // A cache for the backwards implication map.
155156 let mut inverse_implied_features: Option < FxHashMap < & str , FxHashSet < & str > > > = None ;
156157
157- for feature in sess . opts . cg . target_feature . split ( ',' ) {
158+ for feature in features . split ( ',' ) {
158159 if let Some ( base_feature) = feature. strip_prefix ( '+' ) {
159160 // Skip features that are not target features, but rustc features.
160161 if RUSTC_SPECIFIC_FEATURES . contains ( & base_feature) {
@@ -244,8 +245,9 @@ pub fn cfg_target_feature<'a, const N: usize>(
244245 let mut enabled_disabled_features = FxHashMap :: default ( ) ;
245246
246247 // Add enabled and remove disabled features.
247- parse_rust_feature_flag (
248+ parse_rust_feature_list (
248249 sess,
250+ & sess. opts . cg . target_feature ,
249251 /* err_callback */
250252 |feature| {
251253 sess. dcx ( ) . emit_warn ( errors:: UnknownCTargetFeaturePrefix { feature } ) ;
@@ -366,6 +368,37 @@ pub fn check_tied_features(
366368 None
367369}
368370
371+ /// Translates the target spec `features` field into a backend target feature list.
372+ ///
373+ /// `extend_backend_features` extends the set of backend features (assumed to be in mutable state
374+ /// accessible by that closure) to enable/disable the given Rust feature name.
375+ pub fn target_spec_to_backend_features < ' a > (
376+ sess : & ' a Session ,
377+ mut extend_backend_features : impl FnMut ( & ' a str , /* enable */ bool ) ,
378+ ) {
379+ // Compute implied features
380+ let mut rust_features = vec ! [ ] ;
381+ parse_rust_feature_list (
382+ sess,
383+ & sess. target . features ,
384+ /* err_callback */
385+ |feature| {
386+ panic ! ( "Target spec contains invalid feature {feature}" ) ;
387+ } ,
388+ |_base_feature, new_features, enable| {
389+ // FIXME emit an error for unknown features like cfg_target_feature would for -Ctarget-feature
390+ rust_features. extend (
391+ UnordSet :: from ( new_features) . to_sorted_stable_ord ( ) . iter ( ) . map ( |& & s| ( enable, s) ) ,
392+ ) ;
393+ } ,
394+ ) ;
395+
396+ // Add this to the backend features.
397+ for ( enable, feature) in rust_features {
398+ extend_backend_features ( feature, enable) ;
399+ }
400+ }
401+
369402/// Translates the `-Ctarget-feature` flag into a backend target feature list.
370403///
371404/// `extend_backend_features` extends the set of backend features (assumed to be in mutable state
@@ -376,8 +409,9 @@ pub fn flag_to_backend_features<'a>(
376409) {
377410 // Compute implied features
378411 let mut rust_features = vec ! [ ] ;
379- parse_rust_feature_flag (
412+ parse_rust_feature_list (
380413 sess,
414+ & sess. opts . cg . target_feature ,
381415 /* err_callback */
382416 |_feature| {
383417 // Errors are already emitted in `cfg_target_feature`; avoid duplicates.
0 commit comments