mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Don't use LLVM to compute -Ctarget-feature
This commit is contained in:
parent
484aca8857
commit
a25da077cf
@ -97,13 +97,12 @@ pub fn write_output_file<'ll>(
|
|||||||
|
|
||||||
pub fn create_informational_target_machine(
|
pub fn create_informational_target_machine(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
extra_features: bool,
|
only_base_features: bool,
|
||||||
) -> OwnedTargetMachine {
|
) -> OwnedTargetMachine {
|
||||||
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
|
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
|
||||||
// Can't use query system here quite yet because this function is invoked before the query
|
// Can't use query system here quite yet because this function is invoked before the query
|
||||||
// system/tcx is set up.
|
// system/tcx is set up.
|
||||||
let features =
|
let features = llvm_util::global_llvm_features(sess, false, only_base_features);
|
||||||
if extra_features { llvm_util::global_llvm_features(sess, false) } else { Vec::new() };
|
|
||||||
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
target_machine_factory(sess, config::OptLevel::No, &features)(config)
|
||||||
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ pub unsafe fn create_module<'ll>(
|
|||||||
|
|
||||||
// Ensure the data-layout values hardcoded remain the defaults.
|
// Ensure the data-layout values hardcoded remain the defaults.
|
||||||
{
|
{
|
||||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess, true);
|
let tm = crate::back::write::create_informational_target_machine(tcx.sess, false);
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||||||
|
|
||||||
fn provide(&self, providers: &mut Providers) {
|
fn provide(&self, providers: &mut Providers) {
|
||||||
providers.global_backend_features =
|
providers.global_backend_features =
|
||||||
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
|
|tcx, ()| llvm_util::global_llvm_features(tcx.sess, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
|
||||||
@ -434,7 +434,7 @@ impl ModuleLlvm {
|
|||||||
ModuleLlvm {
|
ModuleLlvm {
|
||||||
llmod_raw,
|
llmod_raw,
|
||||||
llcx,
|
llcx,
|
||||||
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, true)),
|
tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,19 +308,10 @@ pub fn check_tied_features(
|
|||||||
/// Used to generate cfg variables and apply features
|
/// Used to generate cfg variables and apply features
|
||||||
/// Must express features in the way Rust understands them
|
/// Must express features in the way Rust understands them
|
||||||
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||||
let rust_features = sess
|
|
||||||
.target
|
|
||||||
.supported_target_features()
|
|
||||||
.iter()
|
|
||||||
.map(|(feature, _, _)| {
|
|
||||||
(to_llvm_features(sess, feature).llvm_feature_name, Symbol::intern(feature))
|
|
||||||
})
|
|
||||||
.collect::<FxHashMap<_, _>>();
|
|
||||||
|
|
||||||
let mut features = FxHashSet::default();
|
let mut features = FxHashSet::default();
|
||||||
|
|
||||||
// Add base features for the target
|
// Add base features for the target
|
||||||
let target_machine = create_informational_target_machine(sess, false);
|
let target_machine = create_informational_target_machine(sess, true);
|
||||||
features.extend(
|
features.extend(
|
||||||
sess.target
|
sess.target
|
||||||
.supported_target_features()
|
.supported_target_features()
|
||||||
@ -343,13 +334,16 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add enabled features
|
// Add enabled features
|
||||||
for llvm_feature in global_llvm_features(sess, false) {
|
for (enabled, feature) in
|
||||||
let (add, llvm_feature) = llvm_feature.split_at(1);
|
sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() {
|
||||||
let feature =
|
Some('+') => Some((true, Symbol::intern(&s[1..]))),
|
||||||
rust_features.get(llvm_feature).cloned().unwrap_or(Symbol::intern(llvm_feature));
|
Some('-') => Some((false, Symbol::intern(&s[1..]))),
|
||||||
if add == "+" {
|
_ => None,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if enabled {
|
||||||
features.extend(sess.target.implied_target_features(std::iter::once(feature)));
|
features.extend(sess.target.implied_target_features(std::iter::once(feature)));
|
||||||
} else if add == "-" {
|
} else {
|
||||||
features.remove(&feature);
|
features.remove(&feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,7 +469,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
|
|||||||
|
|
||||||
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||||
require_inited();
|
require_inited();
|
||||||
let tm = create_informational_target_machine(sess, true);
|
let tm = create_informational_target_machine(sess, false);
|
||||||
match req.kind {
|
match req.kind {
|
||||||
PrintKind::TargetCPUs => {
|
PrintKind::TargetCPUs => {
|
||||||
// SAFETY generate a C compatible string from a byte slice to pass
|
// SAFETY generate a C compatible string from a byte slice to pass
|
||||||
@ -523,7 +517,11 @@ pub fn target_cpu(sess: &Session) -> &str {
|
|||||||
|
|
||||||
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
||||||
/// `--target` and similar).
|
/// `--target` and similar).
|
||||||
pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<String> {
|
pub(crate) fn global_llvm_features(
|
||||||
|
sess: &Session,
|
||||||
|
diagnostics: bool,
|
||||||
|
only_base_features: bool,
|
||||||
|
) -> Vec<String> {
|
||||||
// Features that come earlier are overridden by conflicting features later in the string.
|
// Features that come earlier are overridden by conflicting features later in the string.
|
||||||
// Typically we'll want more explicit settings to override the implicit ones, so:
|
// Typically we'll want more explicit settings to override the implicit ones, so:
|
||||||
//
|
//
|
||||||
@ -583,96 +581,109 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -Ctarget-features
|
// -Ctarget-features
|
||||||
let supported_features = sess.target.supported_target_features();
|
if !only_base_features {
|
||||||
let (llvm_major, _, _) = get_version();
|
let supported_features = sess.target.supported_target_features();
|
||||||
let mut featsmap = FxHashMap::default();
|
let (llvm_major, _, _) = get_version();
|
||||||
let feats = sess
|
let mut featsmap = FxHashMap::default();
|
||||||
.opts
|
let feats = sess
|
||||||
.cg
|
.opts
|
||||||
.target_feature
|
.cg
|
||||||
.split(',')
|
.target_feature
|
||||||
.filter_map(|s| {
|
.split(',')
|
||||||
let enable_disable = match s.chars().next() {
|
.filter_map(|s| {
|
||||||
None => return None,
|
let enable_disable = match s.chars().next() {
|
||||||
Some(c @ ('+' | '-')) => c,
|
None => return None,
|
||||||
Some(_) => {
|
Some(c @ ('+' | '-')) => c,
|
||||||
if diagnostics {
|
Some(_) => {
|
||||||
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s });
|
if diagnostics {
|
||||||
|
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s });
|
||||||
|
}
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let feature = backend_feature_name(sess, s)?;
|
||||||
|
// Warn against use of LLVM specific feature names and unstable features on the CLI.
|
||||||
|
if diagnostics {
|
||||||
|
let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
|
||||||
|
if feature_state.is_none() {
|
||||||
|
let rust_feature =
|
||||||
|
supported_features.iter().find_map(|&(rust_feature, _, _)| {
|
||||||
|
let llvm_features = to_llvm_features(sess, rust_feature);
|
||||||
|
if llvm_features.contains(feature)
|
||||||
|
&& !llvm_features.contains(rust_feature)
|
||||||
|
{
|
||||||
|
Some(rust_feature)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let unknown_feature = if let Some(rust_feature) = rust_feature {
|
||||||
|
UnknownCTargetFeature {
|
||||||
|
feature,
|
||||||
|
rust_feature: PossibleFeature::Some { rust_feature },
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
|
||||||
|
};
|
||||||
|
sess.dcx().emit_warn(unknown_feature);
|
||||||
|
} else if feature_state
|
||||||
|
.is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
|
||||||
|
{
|
||||||
|
// An unstable feature. Warn about using it.
|
||||||
|
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if diagnostics {
|
||||||
|
// FIXME(nagisa): figure out how to not allocate a full hashset here.
|
||||||
|
featsmap.insert(feature, enable_disable == '+');
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustc-specific features do not get passed down to LLVM…
|
||||||
|
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let feature = backend_feature_name(sess, s)?;
|
// if the target-feature is "backchain" and LLVM version is greater than 18
|
||||||
// Warn against use of LLVM specific feature names and unstable features on the CLI.
|
// then we also need to add "+backchain" to the target-features attribute.
|
||||||
if diagnostics {
|
// otherwise, we will only add the naked `backchain` attribute to the attribute-group.
|
||||||
let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
|
if feature == "backchain" && llvm_major < 18 {
|
||||||
if feature_state.is_none() {
|
return None;
|
||||||
let rust_feature =
|
|
||||||
supported_features.iter().find_map(|&(rust_feature, _, _)| {
|
|
||||||
let llvm_features = to_llvm_features(sess, rust_feature);
|
|
||||||
if llvm_features.contains(feature)
|
|
||||||
&& !llvm_features.contains(rust_feature)
|
|
||||||
{
|
|
||||||
Some(rust_feature)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let unknown_feature = if let Some(rust_feature) = rust_feature {
|
|
||||||
UnknownCTargetFeature {
|
|
||||||
feature,
|
|
||||||
rust_feature: PossibleFeature::Some { rust_feature },
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
|
|
||||||
};
|
|
||||||
sess.dcx().emit_warn(unknown_feature);
|
|
||||||
} else if feature_state
|
|
||||||
.is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
|
|
||||||
{
|
|
||||||
// An unstable feature. Warn about using it.
|
|
||||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
|
||||||
}
|
}
|
||||||
}
|
// ... otherwise though we run through `to_llvm_features` when
|
||||||
|
// passing requests down to LLVM. This means that all in-language
|
||||||
|
// features also work on the command line instead of having two
|
||||||
|
// different names when the LLVM name and the Rust name differ.
|
||||||
|
let llvm_feature = to_llvm_features(sess, feature);
|
||||||
|
|
||||||
if diagnostics {
|
Some(
|
||||||
// FIXME(nagisa): figure out how to not allocate a full hashset here.
|
std::iter::once(format!(
|
||||||
featsmap.insert(feature, enable_disable == '+');
|
"{}{}",
|
||||||
}
|
enable_disable, llvm_feature.llvm_feature_name
|
||||||
|
))
|
||||||
// rustc-specific features do not get passed down to LLVM…
|
.chain(llvm_feature.dependency.into_iter().filter_map(
|
||||||
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
|
move |feat| match (enable_disable, feat) {
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the target-feature is "backchain" and LLVM version is greater than 18
|
|
||||||
// then we also need to add "+backchain" to the target-features attribute.
|
|
||||||
// otherwise, we will only add the naked `backchain` attribute to the attribute-group.
|
|
||||||
if feature == "backchain" && llvm_major < 18 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// ... otherwise though we run through `to_llvm_features` when
|
|
||||||
// passing requests down to LLVM. This means that all in-language
|
|
||||||
// features also work on the command line instead of having two
|
|
||||||
// different names when the LLVM name and the Rust name differ.
|
|
||||||
let llvm_feature = to_llvm_features(sess, feature);
|
|
||||||
|
|
||||||
Some(
|
|
||||||
std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
|
|
||||||
.chain(llvm_feature.dependency.into_iter().filter_map(move |feat| {
|
|
||||||
match (enable_disable, feat) {
|
|
||||||
('-' | '+', TargetFeatureFoldStrength::Both(f))
|
('-' | '+', TargetFeatureFoldStrength::Both(f))
|
||||||
| ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
|
| ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
|
||||||
Some(format!("{enable_disable}{f}"))
|
Some(format!("{enable_disable}{f}"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
},
|
||||||
})),
|
)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
features.extend(feats);
|
features.extend(feats);
|
||||||
|
|
||||||
|
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
||||||
|
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
||||||
|
features: f,
|
||||||
|
span: None,
|
||||||
|
missing_features: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -Zfixed-x18
|
// -Zfixed-x18
|
||||||
if sess.opts.unstable_opts.fixed_x18 {
|
if sess.opts.unstable_opts.fixed_x18 {
|
||||||
@ -683,14 +694,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
|
||||||
sess.dcx().emit_err(TargetFeatureDisableOrEnable {
|
|
||||||
features: f,
|
|
||||||
span: None,
|
|
||||||
missing_features: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,13 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
|||||||
// FEAT_SSBS & FEAT_SSBS2
|
// FEAT_SSBS & FEAT_SSBS2
|
||||||
("ssbs", Stable, &[]),
|
("ssbs", Stable, &[]),
|
||||||
// FEAT_SVE
|
// FEAT_SVE
|
||||||
("sve", Stable, &[]),
|
// It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
|
||||||
|
//
|
||||||
|
// LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always
|
||||||
|
// exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
|
||||||
|
//
|
||||||
|
// "For backwards compatibility, Neon and VFP are required in the latest architectures."
|
||||||
|
("sve", Stable, &["neon"]),
|
||||||
// FEAT_SVE2
|
// FEAT_SVE2
|
||||||
("sve2", Stable, &["sve"]),
|
("sve2", Stable, &["sve"]),
|
||||||
// FEAT_SVE2_AES
|
// FEAT_SVE2_AES
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//@ revisions: COMPAT INCOMPAT
|
//@ revisions: COMPAT INCOMPAT
|
||||||
//@ needs-llvm-components: x86
|
//@ needs-llvm-components: x86
|
||||||
//@ compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
|
//@ compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
|
||||||
//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2,+avx,+sse4.2,+sse4.1,+ssse3,+sse3
|
//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2,+avx
|
||||||
//@ [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
|
//@ [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
|
||||||
|
|
||||||
// See also tests/assembly/target-feature-multiple.rs
|
// See also tests/assembly/target-feature-multiple.rs
|
||||||
|
Loading…
Reference in New Issue
Block a user