diff options
Diffstat (limited to 'compiler/rustc_session/src/features.rs')
| -rw-r--r-- | compiler/rustc_session/src/features.rs | 59 | 
1 files changed, 59 insertions, 0 deletions
| diff --git a/compiler/rustc_session/src/features.rs b/compiler/rustc_session/src/features.rs new file mode 100644 index 00000000000..70a088a236f --- /dev/null +++ b/compiler/rustc_session/src/features.rs @@ -0,0 +1,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"); + } +} | 
