Skip to content

Commit 4876043

Browse files
committed
move cfg(target_feature) computation into shared place
1 parent 38081f2 commit 4876043

File tree

3 files changed

+124
-117
lines changed

3 files changed

+124
-117
lines changed

compiler/rustc_codegen_gcc/src/lib.rs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ use rustc_codegen_ssa::back::write::{
102102
};
103103
use rustc_codegen_ssa::base::codegen_crate;
104104
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
105-
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
105+
use rustc_codegen_ssa::{
106+
CodegenResults, CompiledModule, ModuleCodegen, TargetConfig, target_features,
107+
};
106108
use rustc_data_structures::fx::FxIndexMap;
107109
use rustc_data_structures::sync::IntoDynSyncSend;
108110
use rustc_errors::DiagCtxtHandle;
@@ -486,40 +488,23 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
486488

487489
/// Returns the features that should be set in `cfg(target_feature)`.
488490
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
489-
// TODO(antoyo): use global_gcc_features.
490-
let f = |allow_unstable| {
491-
sess.target
492-
.rust_target_features()
493-
.iter()
494-
.filter_map(|&(feature, gate, _)| {
495-
if allow_unstable
496-
|| (gate.in_cfg()
497-
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
498-
{
499-
Some(feature)
500-
} else {
501-
None
502-
}
503-
})
504-
.filter(|feature| {
505-
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
506-
if *feature == "neon" {
507-
return false;
508-
}
509-
target_info.cpu_supports(feature)
510-
/*
511-
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
512-
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
513-
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
514-
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
515-
*/
516-
})
517-
.map(Symbol::intern)
518-
.collect()
519-
};
520-
521-
let target_features = f(false);
522-
let unstable_target_features = f(true);
491+
let (unstable_target_features, target_features) = target_features::cfg_target_feature(
492+
sess,
493+
/* FIXME: we ignore `-Ctarget-feature` */ "",
494+
|feature| {
495+
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
496+
if feature == "neon" {
497+
return false;
498+
}
499+
target_info.cpu_supports(feature)
500+
/*
501+
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
502+
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
503+
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
504+
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
505+
*/
506+
},
507+
);
523508

524509
TargetConfig {
525510
target_features,

compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 7 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@ use std::sync::Once;
66
use std::{ptr, slice, str};
77

88
use libc::c_int;
9-
use rustc_codegen_ssa::TargetConfig;
109
use rustc_codegen_ssa::base::wants_wasm_eh;
1110
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
11+
use rustc_codegen_ssa::{TargetConfig, target_features};
1212
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1313
use rustc_data_structures::small_c_str::SmallCStr;
1414
use rustc_data_structures::unord::UnordSet;
1515
use rustc_fs_util::path_to_c_string;
1616
use rustc_middle::bug;
1717
use rustc_session::Session;
1818
use rustc_session::config::{PrintKind, PrintRequest};
19-
use rustc_span::Symbol;
2019
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
21-
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
20+
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
2221
use smallvec::{SmallVec, smallvec};
2322

2423
use crate::back::write::create_informational_target_machine;
@@ -335,18 +334,11 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig {
335334
// the target CPU, that is still expanded to target features (with all their implied features)
336335
// by LLVM.
337336
let target_machine = create_informational_target_machine(sess, true);
338-
// Compute which of the known target features are enabled in the 'base' target machine. We only
339-
// consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
340-
let mut features: FxHashSet<Symbol> = sess
341-
.target
342-
.rust_target_features()
343-
.iter()
344-
.filter(|(feature, _, _)| {
345-
// skip checking special features, as LLVM may not understand them
346-
if RUSTC_SPECIAL_FEATURES.contains(feature) {
347-
return true;
348-
}
337+
338+
let (unstable_target_features, target_features) =
339+
target_features::cfg_target_feature(sess, &sess.opts.cg.target_feature, |feature| {
349340
if let Some(feat) = to_llvm_features(sess, feature) {
341+
// All the LLVM features this expands to must be enabled.
350342
for llvm_feature in feat {
351343
let cstr = SmallCStr::new(llvm_feature);
352344
// `LLVMRustHasFeature` is moderately expensive. On targets with many
@@ -360,73 +352,8 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig {
360352
} else {
361353
false
362354
}
363-
})
364-
.map(|(feature, _, _)| Symbol::intern(feature))
365-
.collect();
366-
367-
// Add enabled and remove disabled features.
368-
for (enabled, feature) in
369-
sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() {
370-
Some('+') => Some((true, Symbol::intern(&s[1..]))),
371-
Some('-') => Some((false, Symbol::intern(&s[1..]))),
372-
_ => None,
373-
})
374-
{
375-
if enabled {
376-
// Also add all transitively implied features.
377-
378-
// We don't care about the order in `features` since the only thing we use it for is the
379-
// `features.contains` below.
380-
#[allow(rustc::potential_query_instability)]
381-
features.extend(
382-
sess.target
383-
.implied_target_features(feature.as_str())
384-
.iter()
385-
.map(|s| Symbol::intern(s)),
386-
);
387-
} else {
388-
// Remove transitively reverse-implied features.
389-
390-
// We don't care about the order in `features` since the only thing we use it for is the
391-
// `features.contains` below.
392-
#[allow(rustc::potential_query_instability)]
393-
features.retain(|f| {
394-
if sess.target.implied_target_features(f.as_str()).contains(&feature.as_str()) {
395-
// If `f` if implies `feature`, then `!feature` implies `!f`, so we have to
396-
// remove `f`. (This is the standard logical contraposition principle.)
397-
false
398-
} else {
399-
// We can keep `f`.
400-
true
401-
}
402-
});
403-
}
404-
}
405-
406-
// Filter enabled features based on feature gates.
407-
let f = |allow_unstable| {
408-
sess.target
409-
.rust_target_features()
410-
.iter()
411-
.filter_map(|(feature, gate, _)| {
412-
// The `allow_unstable` set is used by rustc internally to determined which target
413-
// features are truly available, so we want to return even perma-unstable
414-
// "forbidden" features.
415-
if allow_unstable
416-
|| (gate.in_cfg()
417-
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
418-
{
419-
Some(Symbol::intern(feature))
420-
} else {
421-
None
422-
}
423-
})
424-
.filter(|feature| features.contains(&feature))
425-
.collect()
426-
};
355+
});
427356

428-
let target_features = f(false);
429-
let unstable_target_features = f(true);
430357
let mut cfg = TargetConfig {
431358
target_features,
432359
unstable_target_features,

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_attr_data_structures::InstructionSetAttr;
2-
use rustc_data_structures::fx::FxIndexSet;
2+
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
33
use rustc_data_structures::unord::{UnordMap, UnordSet};
44
use rustc_errors::Applicability;
55
use rustc_hir as hir;
@@ -8,10 +8,11 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
88
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
99
use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
11+
use rustc_session::Session;
1112
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
1213
use rustc_session::parse::feature_err;
1314
use rustc_span::{Span, Symbol, sym};
14-
use rustc_target::target_features::{self, Stability};
15+
use rustc_target::target_features::{self, RUSTC_SPECIAL_FEATURES, Stability};
1516

1617
use crate::errors;
1718

@@ -155,6 +156,100 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
155156
}
156157
}
157158

159+
/// Utility function for a codegen backend to compute `cfg(target_feature)`, or more specifically,
160+
/// to populate `sess.unstable_target_features` and `sess.target_features` (these are the first and
161+
/// 2nd component of the return value, respectively).
162+
///
163+
/// `target_feature_flag` is the value of `-Ctarget-feature` (giving the caller a chance to override it).
164+
/// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is enabled
165+
/// in the "base" target machine, i.e., without applying `-Ctarget-feature`.
166+
///
167+
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere.
168+
pub fn cfg_target_feature(
169+
sess: &Session,
170+
target_feature_flag: &str,
171+
mut is_feature_enabled: impl FnMut(&str) -> bool,
172+
) -> (Vec<Symbol>, Vec<Symbol>) {
173+
// Compute which of the known target features are enabled in the 'base' target machine. We only
174+
// consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
175+
let mut features: FxHashSet<Symbol> = sess
176+
.target
177+
.rust_target_features()
178+
.iter()
179+
.filter(|(feature, _, _)| {
180+
// Skip checking special features, those are not known to the backend.
181+
if RUSTC_SPECIAL_FEATURES.contains(feature) {
182+
return true;
183+
}
184+
is_feature_enabled(feature)
185+
})
186+
.map(|(feature, _, _)| Symbol::intern(feature))
187+
.collect();
188+
189+
// Add enabled and remove disabled features.
190+
for (enabled, feature) in
191+
target_feature_flag.split(',').filter_map(|s| match s.chars().next() {
192+
Some('+') => Some((true, Symbol::intern(&s[1..]))),
193+
Some('-') => Some((false, Symbol::intern(&s[1..]))),
194+
_ => None,
195+
})
196+
{
197+
if enabled {
198+
// Also add all transitively implied features.
199+
200+
// We don't care about the order in `features` since the only thing we use it for is the
201+
// `features.contains` below.
202+
#[allow(rustc::potential_query_instability)]
203+
features.extend(
204+
sess.target
205+
.implied_target_features(feature.as_str())
206+
.iter()
207+
.map(|s| Symbol::intern(s)),
208+
);
209+
} else {
210+
// Remove transitively reverse-implied features.
211+
212+
// We don't care about the order in `features` since the only thing we use it for is the
213+
// `features.contains` below.
214+
#[allow(rustc::potential_query_instability)]
215+
features.retain(|f| {
216+
if sess.target.implied_target_features(f.as_str()).contains(&feature.as_str()) {
217+
// If `f` if implies `feature`, then `!feature` implies `!f`, so we have to
218+
// remove `f`. (This is the standard logical contraposition principle.)
219+
false
220+
} else {
221+
// We can keep `f`.
222+
true
223+
}
224+
});
225+
}
226+
}
227+
228+
// Filter enabled features based on feature gates.
229+
let f = |allow_unstable| {
230+
sess.target
231+
.rust_target_features()
232+
.iter()
233+
.filter_map(|(feature, gate, _)| {
234+
// The `allow_unstable` set is used by rustc internally to determine which target
235+
// features are truly available, so we want to return even perma-unstable
236+
// "forbidden" features.
237+
if allow_unstable
238+
|| (gate.in_cfg()
239+
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
240+
{
241+
Some(Symbol::intern(feature))
242+
} else {
243+
None
244+
}
245+
})
246+
.filter(|feature| features.contains(&feature))
247+
.collect()
248+
};
249+
250+
(f(true), f(false))
251+
}
252+
158253
pub(crate) fn provide(providers: &mut Providers) {
159254
*providers = Providers {
160255
rust_target_features: |tcx, cnum| {

0 commit comments

Comments
 (0)