| 
1 | 1 | #[cfg(feature = "master")]  | 
2 | 2 | use gccjit::Context;  | 
3 |  | -use rustc_codegen_ssa::codegen_attrs::check_tied_features;  | 
4 |  | -use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;  | 
5 |  | -use rustc_data_structures::fx::FxHashMap;  | 
6 |  | -use rustc_data_structures::unord::UnordSet;  | 
 | 3 | +use rustc_middle::target_features;  | 
7 | 4 | use rustc_session::Session;  | 
8 |  | -use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;  | 
9 | 5 | use smallvec::{SmallVec, smallvec};  | 
10 | 6 | 
 
  | 
11 |  | -use crate::errors::{  | 
12 |  | -    ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,  | 
13 |  | -    UnstableCTargetFeature,  | 
14 |  | -};  | 
15 |  | - | 
16 | 7 | /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,  | 
17 | 8 | /// `--target` and similar).  | 
18 | 9 | pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<String> {  | 
@@ -40,109 +31,27 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri  | 
40 | 31 |     features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));  | 
41 | 32 | 
 
  | 
42 | 33 |     // -Ctarget-features  | 
43 |  | -    let known_features = sess.target.rust_target_features();  | 
44 |  | -    let mut featsmap = FxHashMap::default();  | 
45 |  | - | 
46 |  | -    // Compute implied features  | 
47 |  | -    let mut all_rust_features = vec![];  | 
48 |  | -    for feature in sess.opts.cg.target_feature.split(',') {  | 
49 |  | -        if let Some(feature) = feature.strip_prefix('+') {  | 
50 |  | -            all_rust_features.extend(  | 
51 |  | -                UnordSet::from(sess.target.implied_target_features(feature))  | 
52 |  | -                    .to_sorted_stable_ord()  | 
53 |  | -                    .iter()  | 
54 |  | -                    .map(|&&s| (true, s)),  | 
55 |  | -            )  | 
56 |  | -        } else if let Some(feature) = feature.strip_prefix('-') {  | 
57 |  | -            // FIXME: Why do we not remove implied features on "-" here?  | 
58 |  | -            // We do the equivalent above in `target_config`.  | 
59 |  | -            // See <https://github.com/rust-lang/rust/issues/134792>.  | 
60 |  | -            all_rust_features.push((false, feature));  | 
61 |  | -        } else if !feature.is_empty() && diagnostics {  | 
62 |  | -            sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });  | 
63 |  | -        }  | 
64 |  | -    }  | 
65 |  | -    // Remove features that are meant for rustc, not codegen.  | 
66 |  | -    all_rust_features.retain(|&(_, feature)| {  | 
67 |  | -        // Retain if it is not a rustc feature  | 
68 |  | -        !RUSTC_SPECIFIC_FEATURES.contains(&feature)  | 
69 |  | -    });  | 
70 |  | - | 
71 |  | -    // Check feature validity.  | 
72 |  | -    if diagnostics {  | 
73 |  | -        for &(enable, feature) in &all_rust_features {  | 
74 |  | -            let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);  | 
75 |  | -            match feature_state {  | 
76 |  | -                None => {  | 
77 |  | -                    let rust_feature = known_features.iter().find_map(|&(rust_feature, _, _)| {  | 
78 |  | -                        let gcc_features = to_gcc_features(sess, rust_feature);  | 
79 |  | -                        if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature)  | 
80 |  | -                        {  | 
81 |  | -                            Some(rust_feature)  | 
82 |  | -                        } else {  | 
83 |  | -                            None  | 
84 |  | -                        }  | 
85 |  | -                    });  | 
86 |  | -                    let unknown_feature = if let Some(rust_feature) = rust_feature {  | 
87 |  | -                        UnknownCTargetFeature {  | 
88 |  | -                            feature,  | 
89 |  | -                            rust_feature: PossibleFeature::Some { rust_feature },  | 
90 |  | -                        }  | 
91 |  | -                    } else {  | 
92 |  | -                        UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }  | 
93 |  | -                    };  | 
94 |  | -                    sess.dcx().emit_warn(unknown_feature);  | 
95 |  | -                }  | 
96 |  | -                Some(&(_, stability, _)) => {  | 
97 |  | -                    if let Err(reason) = stability.toggle_allowed() {  | 
98 |  | -                        sess.dcx().emit_warn(ForbiddenCTargetFeature {  | 
99 |  | -                            feature,  | 
100 |  | -                            enabled: if enable { "enabled" } else { "disabled" },  | 
101 |  | -                            reason,  | 
102 |  | -                        });  | 
103 |  | -                    } else if stability.requires_nightly().is_some() {  | 
104 |  | -                        // An unstable feature. Warn about using it. (It makes little sense  | 
105 |  | -                        // to hard-error here since we just warn about fully unknown  | 
106 |  | -                        // features above).  | 
107 |  | -                        sess.dcx().emit_warn(UnstableCTargetFeature { feature });  | 
108 |  | -                    }  | 
109 |  | -                }  | 
110 |  | -            }  | 
111 |  | - | 
112 |  | -            // FIXME(nagisa): figure out how to not allocate a full hashset here.  | 
113 |  | -            featsmap.insert(feature, enable);  | 
114 |  | -        }  | 
115 |  | -    }  | 
116 |  | - | 
117 |  | -    // Translate this into GCC features.  | 
118 |  | -    let feats =  | 
119 |  | -        all_rust_features.iter().flat_map(|&(enable, feature)| {  | 
120 |  | -            let enable_disable = if enable { '+' } else { '-' };  | 
 | 34 | +    target_features::flag_to_backend_features(  | 
 | 35 | +        sess,  | 
 | 36 | +        diagnostics,  | 
 | 37 | +        |feature| to_gcc_features(sess, feature),  | 
 | 38 | +        |feature, enable| {  | 
121 | 39 |             // We run through `to_gcc_features` when  | 
122 | 40 |             // passing requests down to GCC. This means that all in-language  | 
123 | 41 |             // features also work on the command line instead of having two  | 
124 | 42 |             // different names when the GCC name and the Rust name differ.  | 
125 |  | -            to_gcc_features(sess, feature)  | 
126 |  | -                .iter()  | 
127 |  | -                .flat_map(|feat| to_gcc_features(sess, feat).into_iter())  | 
128 |  | -                .map(|feature| {  | 
129 |  | -                    if enable_disable == '-' {  | 
130 |  | -                        format!("-{}", feature)  | 
131 |  | -                    } else {  | 
132 |  | -                        feature.to_string()  | 
133 |  | -                    }  | 
134 |  | -                })  | 
135 |  | -                .collect::<Vec<_>>()  | 
136 |  | -        });  | 
137 |  | -    features.extend(feats);  | 
138 |  | - | 
139 |  | -    if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {  | 
140 |  | -        sess.dcx().emit_err(TargetFeatureDisableOrEnable {  | 
141 |  | -            features: f,  | 
142 |  | -            span: None,  | 
143 |  | -            missing_features: None,  | 
144 |  | -        });  | 
145 |  | -    }  | 
 | 43 | +            features.extend(  | 
 | 44 | +                to_gcc_features(sess, feature)  | 
 | 45 | +                    .iter()  | 
 | 46 | +                    .flat_map(|feat| to_gcc_features(sess, feat).into_iter())  | 
 | 47 | +                    .map(  | 
 | 48 | +                        |feature| {  | 
 | 49 | +                            if !enable { format!("-{}", feature) } else { feature.to_string() }  | 
 | 50 | +                        },  | 
 | 51 | +                    ),  | 
 | 52 | +            );  | 
 | 53 | +        },  | 
 | 54 | +    );  | 
146 | 55 | 
 
  | 
147 | 56 |     features  | 
148 | 57 | }  | 
 | 
0 commit comments