about summary refs log tree commit diff
path: root/compiler/rustc_session/src/features.rs
blob: 70a088a236f7e873f1c1bccbc1f494c9e9afbd42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use rustc_target::target_features::Stability;

use crate::Session;
use crate::errors::{ForbiddenCTargetFeature, UnstableCTargetFeature};

pub trait StabilityExt {
    /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
    /// Otherwise, some features also may only be enabled by flag (target modifier).
    /// (It might still be nightly-only even if this returns `true`, so make sure to also check
    /// `requires_nightly`.)
    fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str>;

    /// Check that feature is correctly enabled/disabled by command line flag (emits warnings)
    fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str);
}

impl StabilityExt for Stability {
    fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str> {
        match self {
            Stability::Forbidden { reason } => Err(reason),
            Stability::TargetModifierOnly { reason, flag } => {
                if !sess.opts.target_feature_flag_enabled(*flag) { Err(reason) } else { Ok(()) }
            }
            _ => Ok(()),
        }
    }
    fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str) {
        if let Err(reason) = self.is_toggle_permitted(sess) {
            sess.dcx().emit_warn(ForbiddenCTargetFeature {
                feature,
                enabled: if enable { "enabled" } else { "disabled" },
                reason,
            });
        } else if self.requires_nightly().is_some() {
            // An unstable feature. Warn about using it. It makes little sense
            // to hard-error here since we just warn about fully unknown
            // features above.
            sess.dcx().emit_warn(UnstableCTargetFeature { feature });
        }
    }
}

pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec<&str>) {
    // -Zretpoline without -Zretpoline-external-thunk enables
    // retpoline-indirect-branches and retpoline-indirect-calls target features
    let unstable_opts = &sess.opts.unstable_opts;
    if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk {
        features.push("+retpoline-indirect-branches");
        features.push("+retpoline-indirect-calls");
    }
    // -Zretpoline-external-thunk (maybe, with -Zretpoline too) enables
    // retpoline-external-thunk, retpoline-indirect-branches and
    // retpoline-indirect-calls target features
    if unstable_opts.retpoline_external_thunk {
        features.push("+retpoline-external-thunk");
        features.push("+retpoline-indirect-branches");
        features.push("+retpoline-indirect-calls");
    }
}