Auto merge of #133099 - RalfJung:forbidden-hardfloat-features, r=workingjubilee
forbid toggling x87 and fpregs on hard-float targets Part of https://github.com/rust-lang/rust/issues/116344, follow-up to https://github.com/rust-lang/rust/pull/129884: The `x87` target feature on x86 and the `fpregs` target feature on ARM must not be disabled on a hardfloat target, as that would change the float ABI. However, *enabling* `fpregs` on ARM is [explicitly requested](https://github.com/rust-lang/rust/issues/130988) as it seems to be useful. Therefore, we need to refine the distinction of "forbidden" target features and "allowed" target features: all (un)stable target features can determine on a per-target basis whether they should be allowed to be toggled or not. `fpregs` then checks whether the current target has the `soft-float` feature, and if yes, `fpregs` is permitted -- otherwise, it is not. (Same for `x87` on x86). Also fixes https://github.com/rust-lang/rust/issues/132351. Since `fpregs` and `x87` can be enabled on some builds and disabled on others, it would make sense that one can query it via `cfg`. Therefore, I made them behave in `cfg` like any other unstable target feature. The first commit prepares the infrastructure, but does not change behavior. The second commit then wires up `fpregs` and `x87` with that new infrastructure. r? `@workingjubilee`
This commit is contained in:
commit
327c7ee436
32 changed files with 616 additions and 414 deletions
|
@ -27,7 +27,7 @@ use std::mem::ManuallyDrop;
|
|||
use back::owned_target_machine::OwnedTargetMachine;
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
use errors::ParseTargetMachineConfig;
|
||||
pub use llvm_util::target_features;
|
||||
pub use llvm_util::target_features_cfg;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::write::{
|
||||
|
@ -330,8 +330,8 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
llvm_util::print_version();
|
||||
}
|
||||
|
||||
fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||
target_features(sess, allow_unstable)
|
||||
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||
target_features_cfg(sess, allow_unstable)
|
||||
}
|
||||
|
||||
fn codegen_crate<'tcx>(
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_session::Session;
|
|||
use rustc_session::config::{PrintKind, PrintRequest};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
|
||||
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability};
|
||||
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
|
||||
|
||||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::errors::{
|
||||
|
@ -300,7 +300,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
|
|||
/// Must express features in the way Rust understands them.
|
||||
///
|
||||
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
|
||||
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||
pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||
let mut features: FxHashSet<Symbol> = Default::default();
|
||||
|
||||
// Add base features for the target.
|
||||
|
@ -316,7 +316,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter(|(_, gate, _)| gate.is_supported())
|
||||
.filter(|(_, gate, _)| gate.in_cfg())
|
||||
.filter(|(feature, _, _)| {
|
||||
// skip checking special features, as LLVM may not understand them
|
||||
if RUSTC_SPECIAL_FEATURES.contains(feature) {
|
||||
|
@ -372,9 +372,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter(|(_, gate, _)| gate.is_supported())
|
||||
.filter(|(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|&(feature, gate, _)| {
|
||||
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
|
||||
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
|
||||
Some(feature)
|
||||
} else {
|
||||
None
|
||||
|
@ -493,7 +493,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
|
|||
.rust_target_features()
|
||||
.iter()
|
||||
.filter_map(|(feature, gate, _implied)| {
|
||||
if !gate.is_supported() {
|
||||
if !gate.in_cfg() {
|
||||
// Only list (experimentally) supported features.
|
||||
return None;
|
||||
}
|
||||
|
@ -716,13 +716,17 @@ pub(crate) fn global_llvm_features(
|
|||
};
|
||||
sess.dcx().emit_warn(unknown_feature);
|
||||
}
|
||||
Some((_, Stability::Stable, _)) => {}
|
||||
Some((_, Stability::Unstable(_), _)) => {
|
||||
// An unstable feature. Warn about using it.
|
||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||
}
|
||||
Some((_, Stability::Forbidden { reason }, _)) => {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
|
||||
Some((_, stability, _)) => {
|
||||
if let Err(reason) =
|
||||
stability.compute_toggleability(&sess.target).allow_toggle()
|
||||
{
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
|
||||
} else if stability.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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue