Skip to content

Commit 43786cf

Browse files
committed
Auto merge of rust-lang#117616 - RalfJung:unstable-target-features, r=compiler-errors
warn when using an unstable feature with -Ctarget-feature Setting or unsetting the wrong target features can cause ABI incompatibility (rust-lang#116344, rust-lang#116558). We need to carefully audit features for their ABI impact before stabilization. I just learned that we currently accept arbitrary unstable features on stable and if they are in the list of Rust target features, even unstable, then we don't even warn about that!1 That doesn't seem great, so I propose we introduce a warning here. This has an obvious loophole via `-Ctarget-cpu`. I'm not sure how to best deal with that, but it seems better to fix what we can and think about the other cases later, maybe once we have a better idea for how to resolve the general mess that are ABI-affecting target features.
2 parents 61a3eea + b85c683 commit 43786cf

File tree

7 files changed

+64
-23
lines changed

7 files changed

+64
-23
lines changed

compiler/rustc_codegen_llvm/messages.ftl

+6-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$
7676
codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
7777
7878
codegen_llvm_unknown_ctarget_feature =
79-
unknown feature specified for `-Ctarget-feature`: `{$feature}`
80-
.note = it is still passed through to the codegen backend
79+
unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`
80+
.note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
8181
.possible_feature = you might have meant: `{$rust_feature}`
8282
.consider_filing_feature_request = consider filing a feature request
8383
@@ -87,6 +87,10 @@ codegen_llvm_unknown_ctarget_feature_prefix =
8787
8888
codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo
8989
90+
codegen_llvm_unstable_ctarget_feature =
91+
unstable feature specified for `-Ctarget-feature`: `{$feature}`
92+
.note = this feature is not stably supported; its behavior can change in the future
93+
9094
codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
9195
9296
codegen_llvm_write_ir = failed to write LLVM IR to {$path}

compiler/rustc_codegen_llvm/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ pub(crate) struct UnknownCTargetFeature<'a> {
2626
pub rust_feature: PossibleFeature<'a>,
2727
}
2828

29+
#[derive(Diagnostic)]
30+
#[diag(codegen_llvm_unstable_ctarget_feature)]
31+
#[note]
32+
pub(crate) struct UnstableCTargetFeature<'a> {
33+
pub feature: &'a str,
34+
}
35+
2936
#[derive(Subdiagnostic)]
3037
pub(crate) enum PossibleFeature<'a> {
3138
#[help(codegen_llvm_possible_feature)]

compiler/rustc_codegen_llvm/src/llvm_util.rs

+28-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::back::write::create_informational_target_machine;
22
use crate::errors::{
33
PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
4-
UnknownCTargetFeaturePrefix,
4+
UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
55
};
66
use crate::llvm;
77
use libc::c_int;
@@ -531,25 +531,34 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
531531
};
532532

533533
let feature = backend_feature_name(s)?;
534-
// Warn against use of LLVM specific feature names on the CLI.
535-
if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) {
536-
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
537-
let llvm_features = to_llvm_features(sess, rust_feature);
538-
if llvm_features.contains(&feature) && !llvm_features.contains(&rust_feature) {
539-
Some(rust_feature)
534+
// Warn against use of LLVM specific feature names and unstable features on the CLI.
535+
if diagnostics {
536+
let feature_state = supported_features.iter().find(|&&(v, _)| v == feature);
537+
if feature_state.is_none() {
538+
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
539+
let llvm_features = to_llvm_features(sess, rust_feature);
540+
if llvm_features.contains(&feature)
541+
&& !llvm_features.contains(&rust_feature)
542+
{
543+
Some(rust_feature)
544+
} else {
545+
None
546+
}
547+
});
548+
let unknown_feature = if let Some(rust_feature) = rust_feature {
549+
UnknownCTargetFeature {
550+
feature,
551+
rust_feature: PossibleFeature::Some { rust_feature },
552+
}
540553
} else {
541-
None
542-
}
543-
});
544-
let unknown_feature = if let Some(rust_feature) = rust_feature {
545-
UnknownCTargetFeature {
546-
feature,
547-
rust_feature: PossibleFeature::Some { rust_feature },
548-
}
549-
} else {
550-
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
551-
};
552-
sess.emit_warning(unknown_feature);
554+
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
555+
};
556+
sess.emit_warning(unknown_feature);
557+
} else if feature_state.is_some_and(|(_name, feature_gate)| feature_gate.is_some())
558+
{
559+
// An unstable feature. Warn about using it.
560+
sess.emit_warning(UnstableCTargetFeature { feature });
561+
}
553562
}
554563

555564
if diagnostics {

compiler/rustc_codegen_ssa/src/target_features.rs

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
2323
// check whether they're named already elsewhere in rust
2424
// e.g. in stdarch and whether the given name matches LLVM's
2525
// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted
26+
//
27+
// When adding a new feature, be particularly mindful of features that affect function ABIs. Those
28+
// need to be treated very carefully to avoid introducing unsoundness! This often affects features
29+
// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an
30+
// example of this going wrong), but features enabling new SIMD registers are also a concern (see
31+
// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong).
32+
//
33+
// Stabilizing a target feature (setting the 2nd component of the pair to `None`) requires t-lang
34+
// approval.
2635

2736
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
2837
// tidy-alphabetical-start

tests/ui/target-feature/similar-feature-suggestion.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
warning: unknown feature specified for `-Ctarget-feature`: `rdrnd`
1+
warning: unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd`
22
|
3-
= note: it is still passed through to the codegen backend
3+
= note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
44
= help: you might have meant: `rdrand`
55

66
warning: 1 warning emitted
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// compile-flags: -Ctarget-feature=+vaes --crate-type=rlib --target=x86_64-unknown-linux-gnu
2+
// build-pass
3+
// needs-llvm-components: x86
4+
5+
#![feature(no_core)]
6+
#![no_core]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
warning: unstable feature specified for `-Ctarget-feature`: `vaes`
2+
|
3+
= note: this feature is not stably supported; its behavior can change in the future
4+
5+
warning: 1 warning emitted
6+

0 commit comments

Comments
 (0)