cg_gcc: properly populate cfg(target_features) with -Ctarget-features
This commit is contained in:
@@ -102,10 +102,9 @@ use rustc_codegen_ssa::back::write::{
|
||||
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
|
||||
};
|
||||
use rustc_codegen_ssa::base::codegen_crate;
|
||||
use rustc_codegen_ssa::target_features::cfg_target_feature;
|
||||
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
|
||||
use rustc_codegen_ssa::{
|
||||
CodegenResults, CompiledModule, ModuleCodegen, TargetConfig, target_features,
|
||||
};
|
||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
@@ -478,25 +477,21 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
|
||||
|
||||
/// Returns the features that should be set in `cfg(target_feature)`.
|
||||
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
|
||||
let (unstable_target_features, target_features) = target_features::cfg_target_feature(
|
||||
sess,
|
||||
/* FIXME: we ignore `-Ctarget-feature` */ "",
|
||||
|feature| {
|
||||
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
|
||||
if feature == "neon" {
|
||||
return false;
|
||||
}
|
||||
target_info.cpu_supports(feature)
|
||||
// cSpell:disable
|
||||
/*
|
||||
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
|
||||
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
||||
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
|
||||
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
|
||||
*/
|
||||
// cSpell:enable
|
||||
},
|
||||
);
|
||||
let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
|
||||
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
|
||||
if feature == "neon" {
|
||||
return false;
|
||||
}
|
||||
target_info.cpu_supports(feature)
|
||||
// cSpell:disable
|
||||
/*
|
||||
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
|
||||
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
||||
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
|
||||
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
|
||||
*/
|
||||
// cSpell:enable
|
||||
});
|
||||
|
||||
let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16);
|
||||
let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128);
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::{ptr, slice, str};
|
||||
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||
use rustc_codegen_ssa::target_features::cfg_target_feature;
|
||||
use rustc_codegen_ssa::{TargetConfig, target_features};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
@@ -331,24 +332,23 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig {
|
||||
// by LLVM.
|
||||
let target_machine = create_informational_target_machine(sess, true);
|
||||
|
||||
let (unstable_target_features, target_features) =
|
||||
target_features::cfg_target_feature(sess, &sess.opts.cg.target_feature, |feature| {
|
||||
if let Some(feat) = to_llvm_features(sess, feature) {
|
||||
// All the LLVM features this expands to must be enabled.
|
||||
for llvm_feature in feat {
|
||||
let cstr = SmallCStr::new(llvm_feature);
|
||||
// `LLVMRustHasFeature` is moderately expensive. On targets with many
|
||||
// features (e.g. x86) these calls take a non-trivial fraction of runtime
|
||||
// when compiling very small programs.
|
||||
if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } {
|
||||
return false;
|
||||
}
|
||||
let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
|
||||
if let Some(feat) = to_llvm_features(sess, feature) {
|
||||
// All the LLVM features this expands to must be enabled.
|
||||
for llvm_feature in feat {
|
||||
let cstr = SmallCStr::new(llvm_feature);
|
||||
// `LLVMRustHasFeature` is moderately expensive. On targets with many
|
||||
// features (e.g. x86) these calls take a non-trivial fraction of runtime
|
||||
// when compiling very small programs.
|
||||
if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
let mut cfg = TargetConfig {
|
||||
target_features,
|
||||
|
||||
@@ -163,8 +163,7 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
|
||||
/// and call the closure for each (expanded) Rust feature. If the list contains
|
||||
/// a syntactically invalid item (not starting with `+`/`-`), the error callback is invoked.
|
||||
fn parse_rust_feature_flag<'a>(
|
||||
sess: &Session,
|
||||
target_feature_flag: &'a str,
|
||||
sess: &'a Session,
|
||||
err_callback: impl Fn(&'a str),
|
||||
mut callback: impl FnMut(
|
||||
/* base_feature */ &'a str,
|
||||
@@ -175,7 +174,7 @@ fn parse_rust_feature_flag<'a>(
|
||||
// A cache for the backwards implication map.
|
||||
let mut inverse_implied_features: Option<FxHashMap<&str, FxHashSet<&str>>> = None;
|
||||
|
||||
for feature in target_feature_flag.split(',') {
|
||||
for feature in sess.opts.cg.target_feature.split(',') {
|
||||
if let Some(base_feature) = feature.strip_prefix('+') {
|
||||
callback(base_feature, sess.target.implied_target_features(base_feature), true)
|
||||
} else if let Some(base_feature) = feature.strip_prefix('-') {
|
||||
@@ -215,15 +214,13 @@ fn parse_rust_feature_flag<'a>(
|
||||
/// to populate `sess.unstable_target_features` and `sess.target_features` (these are the first and
|
||||
/// 2nd component of the return value, respectively).
|
||||
///
|
||||
/// `target_feature_flag` is the value of `-Ctarget-feature` (giving the caller a chance to override it).
|
||||
/// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is enabled
|
||||
/// in the "base" target machine, i.e., without applying `-Ctarget-feature`.
|
||||
///
|
||||
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere.
|
||||
pub fn cfg_target_feature(
|
||||
sess: &Session,
|
||||
target_feature_flag: &str,
|
||||
mut is_feature_enabled: impl FnMut(&str) -> bool,
|
||||
mut target_base_has_feature: impl FnMut(&str) -> bool,
|
||||
) -> (Vec<Symbol>, Vec<Symbol>) {
|
||||
// Compute which of the known target features are enabled in the 'base' target machine. We only
|
||||
// consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
|
||||
@@ -236,7 +233,7 @@ pub fn cfg_target_feature(
|
||||
if RUSTC_SPECIAL_FEATURES.contains(feature) {
|
||||
return true;
|
||||
}
|
||||
is_feature_enabled(feature)
|
||||
target_base_has_feature(feature)
|
||||
})
|
||||
.map(|(feature, _, _)| Symbol::intern(feature))
|
||||
.collect();
|
||||
@@ -244,7 +241,6 @@ pub fn cfg_target_feature(
|
||||
// Add enabled and remove disabled features.
|
||||
parse_rust_feature_flag(
|
||||
sess,
|
||||
target_feature_flag,
|
||||
/* err_callback */ |_| {},
|
||||
|_base_feature, new_features, enabled| {
|
||||
// Iteration order is irrelevant since this only influences an `UnordSet`.
|
||||
@@ -323,7 +319,6 @@ pub fn flag_to_backend_features<'a, const N: usize>(
|
||||
let mut rust_features = vec![];
|
||||
parse_rust_feature_flag(
|
||||
sess,
|
||||
&sess.opts.cg.target_feature,
|
||||
/* err_callback */
|
||||
|feature| {
|
||||
if diagnostics {
|
||||
|
||||
Reference in New Issue
Block a user