Skip to content

Commit 323b7a0

Browse files
committed
Ability to make target features target modifiers
1 parent 8483293 commit 323b7a0

File tree

6 files changed

+592
-515
lines changed

6 files changed

+592
-515
lines changed

compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
515515
.target
516516
.rust_target_features()
517517
.iter()
518-
.filter_map(|(feature, gate, _implied)| {
518+
.filter_map(|(feature, gate, _implied, _)| {
519519
if !gate.in_cfg() {
520520
// Only list (experimentally) supported features.
521521
return None;

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ fn parse_rust_feature_flag<'a>(
173173

174174
let inverse_implied_features = inverse_implied_features.get_or_insert_with(|| {
175175
let mut set: FxHashMap<&str, FxHashSet<&str>> = FxHashMap::default();
176-
for (f, _, is) in sess.target.rust_target_features() {
176+
for (f, _, is, _) in sess.target.rust_target_features() {
177177
for i in is.iter() {
178178
set.entry(i).or_default().insert(f);
179179
}
@@ -222,8 +222,8 @@ pub fn cfg_target_feature(
222222
.target
223223
.rust_target_features()
224224
.iter()
225-
.filter(|(feature, _, _)| target_base_has_feature(feature))
226-
.flat_map(|(base_feature, _, _)| {
225+
.filter(|(feature, _, _, _)| target_base_has_feature(feature))
226+
.flat_map(|(base_feature, _, _, _)| {
227227
// Expand the direct base feature into all transitively-implied features. Note that we
228228
// cannot simply use the `implied` field of the tuple since that only contains
229229
// directly-implied features.
@@ -260,7 +260,7 @@ pub fn cfg_target_feature(
260260
sess.target
261261
.rust_target_features()
262262
.iter()
263-
.filter_map(|(feature, gate, _)| {
263+
.filter_map(|(feature, gate, _, _)| {
264264
// The `allow_unstable` set is used by rustc internally to determine which target
265265
// features are truly available, so we want to return even perma-unstable
266266
// "forbidden" features.
@@ -330,13 +330,13 @@ pub fn flag_to_backend_features<'a, const N: usize>(
330330
);
331331
// Check feature validity.
332332
if diagnostics {
333-
let feature_state = known_features.iter().find(|&&(v, _, _)| v == base_feature);
333+
let feature_state = known_features.iter().find(|&&(v, _, _, _)| v == base_feature);
334334
match feature_state {
335335
None => {
336336
// This is definitely not a valid Rust feature name. Maybe it is a backend
337337
// feature name? If so, give a better error message.
338338
let rust_feature =
339-
known_features.iter().find_map(|&(rust_feature, _, _)| {
339+
known_features.iter().find_map(|&(rust_feature, _, _, _)| {
340340
let backend_features = to_backend_features(rust_feature);
341341
if backend_features.contains(&base_feature)
342342
&& !backend_features.contains(&rust_feature)
@@ -359,7 +359,7 @@ pub fn flag_to_backend_features<'a, const N: usize>(
359359
};
360360
sess.dcx().emit_warn(unknown_feature);
361361
}
362-
Some((_, stability, _)) => {
362+
Some((_, stability, _, _)) => {
363363
if let Err(reason) = stability.toggle_allowed() {
364364
sess.dcx().emit_warn(errors::ForbiddenCTargetFeature {
365365
feature: base_feature,
@@ -463,7 +463,7 @@ pub(crate) fn provide(providers: &mut Providers) {
463463
.target
464464
.rust_target_features()
465465
.iter()
466-
.map(|(a, b, _)| (a.to_string(), *b))
466+
.map(|(a, b, _, _)| (a.to_string(), *b))
467467
.collect()
468468
}
469469
},

compiler/rustc_metadata/src/creader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl CStore {
412412
match (&left_name_val, &right_name_val) {
413413
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
414414
cmp::Ordering::Equal => {
415-
if !l.1.consistent(&tcx.sess.opts, Some(&r.1)) {
415+
if !l.1.consistent(&tcx.sess, Some(&r.1)) {
416416
report_diff(
417417
&l.0.prefix,
418418
&l.0.name,
@@ -424,26 +424,26 @@ impl CStore {
424424
right_name_val = None;
425425
}
426426
cmp::Ordering::Greater => {
427-
if !r.1.consistent(&tcx.sess.opts, None) {
427+
if !r.1.consistent(&tcx.sess, None) {
428428
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
429429
}
430430
right_name_val = None;
431431
}
432432
cmp::Ordering::Less => {
433-
if !l.1.consistent(&tcx.sess.opts, None) {
433+
if !l.1.consistent(&tcx.sess, None) {
434434
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
435435
}
436436
left_name_val = None;
437437
}
438438
},
439439
(Some(l), None) => {
440-
if !l.1.consistent(&tcx.sess.opts, None) {
440+
if !l.1.consistent(&tcx.sess, None) {
441441
report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
442442
}
443443
left_name_val = None;
444444
}
445445
(None, Some(r)) => {
446-
if !r.1.consistent(&tcx.sess.opts, None) {
446+
if !r.1.consistent(&tcx.sess, None) {
447447
report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
448448
}
449449
right_name_val = None;

compiler/rustc_session/src/options.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_target::spec::{
2222
use crate::config::*;
2323
use crate::search_paths::SearchPath;
2424
use crate::utils::NativeLib;
25-
use crate::{EarlyDiagCtxt, lint};
25+
use crate::{EarlyDiagCtxt, Session, lint};
2626

2727
macro_rules! insert {
2828
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
@@ -85,6 +85,42 @@ pub struct TargetModifier {
8585

8686
mod target_modifier_consistency_check {
8787
use super::*;
88+
pub(super) fn target_feature(
89+
sess: &Session,
90+
l: &TargetModifier,
91+
r: Option<&TargetModifier>,
92+
) -> bool {
93+
fn parse<'val>(session: &Session, val: &'val TargetModifier) -> Vec<&'val str> {
94+
let mut target_features = Vec::new();
95+
96+
for feature in val.value_name.split(',') {
97+
if let Some(base_feature) = feature.strip_prefix('+') {
98+
if session.target.rust_target_features().iter().any(
99+
|(name, _, _, target_modifier)| base_feature == *name && *target_modifier,
100+
) {
101+
target_features.push(base_feature);
102+
}
103+
} else if let Some(base_feature) = feature.strip_prefix('-') {
104+
if session.target.rust_target_features().iter().any(
105+
|(name, _, _, target_modifier)| base_feature == *name && *target_modifier,
106+
) {
107+
for (index, target_feature) in target_features.iter().enumerate() {
108+
if *target_feature == base_feature {
109+
target_features.remove(index);
110+
break;
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
target_features
118+
}
119+
120+
let l = parse(sess, l);
121+
122+
if let Some(r) = r { l == parse(sess, r) } else { l.is_empty() }
123+
}
88124
pub(super) fn sanitizer(l: &TargetModifier, r: Option<&TargetModifier>) -> bool {
89125
let mut lparsed: SanitizerSet = Default::default();
90126
let lval = if l.value_name.is_empty() { None } else { Some(l.value_name.as_str()) };
@@ -133,21 +169,25 @@ impl TargetModifier {
133169
}
134170
// Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`)
135171
// When other is None, consistency with default value is checked
136-
pub fn consistent(&self, opts: &Options, other: Option<&TargetModifier>) -> bool {
172+
pub fn consistent(&self, sess: &Session, other: Option<&TargetModifier>) -> bool {
137173
assert!(other.is_none() || self.opt == other.unwrap().opt);
138174
match self.opt {
175+
OptionsTargetModifiers::CodegenOptions(
176+
CodegenOptionsTargetModifiers::target_feature,
177+
) => {
178+
return target_modifier_consistency_check::target_feature(sess, self, other);
179+
}
139180
OptionsTargetModifiers::UnstableOptions(unstable) => match unstable {
140181
UnstableOptionsTargetModifiers::sanitizer => {
141182
return target_modifier_consistency_check::sanitizer(self, other);
142183
}
143184
UnstableOptionsTargetModifiers::sanitizer_cfi_normalize_integers => {
144185
return target_modifier_consistency_check::sanitizer_cfi_normalize_integers(
145-
opts, self, other,
186+
&sess.opts, self, other,
146187
);
147188
}
148189
_ => {}
149190
},
150-
_ => {}
151191
};
152192
match other {
153193
Some(other) => self.extend().tech_value == other.extend().tech_value,
@@ -2172,7 +2212,7 @@ options! {
21722212
"which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"),
21732213
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
21742214
"select target processor (`rustc --print target-cpus` for details)"),
2175-
target_feature: String = (String::new(), parse_target_feature, [TRACKED],
2215+
target_feature: String = (String::new(), parse_target_feature, [TRACKED TARGET_MODIFIER],
21762216
"target specific attributes. (`rustc --print target-features` for details). \
21772217
This feature is unsafe."),
21782218
unsafe_allow_abi_mismatch: Vec<String> = (Vec::new(), parse_comma_list, [UNTRACKED],

0 commit comments

Comments
 (0)