Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions compiler/rustc_codegen_gcc/src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
// should be taken in cases like these.
let mut features = vec![];

// Features implied by an implicit or explicit `--target`.
features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));

// -Ctarget-features
target_features::flag_to_backend_features(sess, |feature, enable| {
let mut extend_backend_features = |feature: &str, enable: bool| {
// We run through `to_gcc_features` when
// passing requests down to GCC. This means that all in-language
// features also work on the command line instead of having two
Expand All @@ -48,7 +44,13 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec<String> {
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
.map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }),
);
});
};

// Features implied by an implicit or explicit `--target`.
target_features::target_spec_to_backend_features(sess, &mut extend_backend_features);

// -Ctarget-features
target_features::flag_to_backend_features(sess, extend_backend_features);

gcc_features_by_flags(sess, &mut features);

Expand All @@ -66,6 +68,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
(&Arch::X86 | &Arch::X86_64, "rdrand") => smallvec!["rdrnd"],
(&Arch::X86 | &Arch::X86_64, "bmi1") => smallvec!["bmi"],
(&Arch::X86 | &Arch::X86_64, "cmpxchg16b") => smallvec!["cx16"],
(&Arch::X86 | &Arch::X86_64, "lahfsahf") => smallvec!["sahf"],
(&Arch::X86 | &Arch::X86_64, "avx512vaes") => smallvec!["vaes"],
(&Arch::X86 | &Arch::X86_64, "avx512gfni") => smallvec!["gfni"],
(&Arch::X86 | &Arch::X86_64, "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
Expand Down
55 changes: 29 additions & 26 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,10 @@ pub(crate) fn target_cpu(sess: &Session) -> &str {

/// The target features for compiler flags other than `-Ctarget-features`.
fn llvm_features_by_flags(sess: &Session, features: &mut Vec<String>) {
if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
features.push("+exception-handling".into());
}

target_features::retpoline_features_by_flags(sess, features);

// -Zfixed-x18
Expand Down Expand Up @@ -691,36 +695,35 @@ pub(crate) fn global_llvm_features(sess: &Session, only_base_features: bool) ->
Some(_) | None => {}
};

// Features implied by an implicit or explicit `--target`.
features.extend(sess.target.features.split(',').filter(|v| !v.is_empty()).map(String::from));
let mut extend_backend_features = |feature: &str, enable: bool| {
let enable_disable = if enable { '+' } else { '-' };
// 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 Some(llvm_feature) = to_llvm_features(sess, feature) else { return };

features.extend(
std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name)).chain(
llvm_feature.dependencies.into_iter().filter_map(move |feat| {
match (enable, feat) {
(_, TargetFeatureFoldStrength::Both(f))
| (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
Some(format!("{enable_disable}{f}"))
}
_ => None,
}
}),
),
);
};

if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
features.push("+exception-handling".into());
}
// Features implied by an implicit or explicit `--target`.
target_features::target_spec_to_backend_features(sess, &mut extend_backend_features);

// -Ctarget-features
if !only_base_features {
target_features::flag_to_backend_features(sess, |feature, enable| {
let enable_disable = if enable { '+' } else { '-' };
// 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 Some(llvm_feature) = to_llvm_features(sess, feature) else { return };

features.extend(
std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
.chain(llvm_feature.dependencies.into_iter().filter_map(move |feat| {
match (enable, feat) {
(_, TargetFeatureFoldStrength::Both(f))
| (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
Some(format!("{enable_disable}{f}"))
}
_ => None,
}
})),
)
});
target_features::flag_to_backend_features(sess, extend_backend_features);
}

// We add this in the "base target" so that these show up in `sess.unstable_target_features`.
Expand Down
40 changes: 37 additions & 3 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,12 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
}
}

/// Parse the value of `-Ctarget-feature`, also expanding implied features,
/// and call the closure for each (expanded) Rust feature. If the list contains
/// Parse the value of the target spec `features` field or `-Ctarget-feature`, also expanding
/// implied features, 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: &'a Session,
features: &'a str,
err_callback: impl Fn(&'a str),
mut callback: impl FnMut(
/* base_feature */ &'a str,
Expand All @@ -154,7 +155,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 sess.opts.cg.target_feature.split(',') {
for feature in features.split(',') {
if let Some(base_feature) = feature.strip_prefix('+') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
Expand Down Expand Up @@ -246,6 +247,7 @@ pub fn cfg_target_feature<'a, const N: usize>(
// Add enabled and remove disabled features.
parse_rust_feature_flag(
sess,
&sess.opts.cg.target_feature,
/* err_callback */
|feature| {
sess.dcx().emit_warn(errors::UnknownCTargetFeaturePrefix { feature });
Expand Down Expand Up @@ -366,6 +368,37 @@ pub fn check_tied_features(
None
}

/// Translates the target spec `features` field into a backend target feature list.
///
/// `extend_backend_features` extends the set of backend features (assumed to be in mutable state
/// accessible by that closure) to enable/disable the given Rust feature name.
pub fn target_spec_to_backend_features<'a>(
sess: &'a Session,
mut extend_backend_features: impl FnMut(&'a str, /* enable */ bool),
) {
// Compute implied features
let mut rust_features = vec![];
parse_rust_feature_flag(
sess,
&sess.target.features,
/* err_callback */
|feature| {
panic!("Target spec contains invalid feature {feature}");
},
|_base_feature, new_features, enable| {
// FIXME emit an error for unknown features like cfg_target_feature would for -Ctarget-feature
rust_features.extend(
UnordSet::from(new_features).to_sorted_stable_ord().iter().map(|&&s| (enable, s)),
);
},
);

// Add this to the backend features.
for (enable, feature) in rust_features {
extend_backend_features(feature, enable);
}
}

/// Translates the `-Ctarget-feature` flag into a backend target feature list.
///
/// `extend_backend_features` extends the set of backend features (assumed to be in mutable state
Expand All @@ -378,6 +411,7 @@ pub fn flag_to_backend_features<'a>(
let mut rust_features = vec![];
parse_rust_feature_flag(
sess,
&sess.opts.cg.target_feature,
/* err_callback */
|_feature| {
// Errors are already emitted in `cfg_target_feature`; avoid duplicates.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ impl CodegenBackend for DummyCodegenBackend {
|feature| {
// This is a standin for the list of features a backend is expected to enable.
// It would be better to parse target.features instead and handle implied features,
// but target.features is a list of LLVM target features, not Rust target features.
// The dummy backend doesn't know the mapping between LLVM and Rust target features.
// but target.features doesn't contain features that are enabled by default for an
// architecture or target cpu.
sess.target.abi_required_features().required.contains(&feature)
},
);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2248,8 +2248,8 @@ pub struct TargetOptions {
pub need_explicit_cpu: bool,
/// Default target features to pass to LLVM. These features overwrite
/// `-Ctarget-cpu` but can be overwritten with `-Ctarget-features`.
/// Corresponds to `llc -mattr=$features`.
/// Note that these are LLVM feature names, not Rust feature names!
/// Corresponds to `llc -mattr=$llvm_features` where `$llvm_features` is the result of mapping
/// the Rust features in this field to LLVM features.
///
/// Generally it is a bad idea to use negative target features because they often interact very
/// poorly with how `-Ctarget-cpu` works. Instead, try to use a lower "base CPU" and enable the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
features: "+neon,+apple-a7".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::THREAD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12".into(),
features: "+neon,+apple-a12".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
..opts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
features: "+neon,+apple-a7".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::THREAD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
features: "+neon,+apple-a7".into(),
max_atomic_width: Some(128),
..opts
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
features: "+neon,+apple-a7".into(),
max_atomic_width: Some(128),
..opts
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
features: "+neon,+apple-a16".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
features: "+neon,+apple-a16".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
features: "+v8a,+neon,+apple-a7".into(),
max_atomic_width: Some(128),
dynamic_linking: false,
position_independent_executables: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
.into(),
arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
features: "+neon,+apple-a7".into(),
max_atomic_width: Some(128),
..opts
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
arch: Arch::AArch64,
data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
options: TargetOptions {
features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
features: "+v8a,+strict-align,+neon".into(),
max_atomic_width: Some(128),
stack_probes: StackProbeType::Inline,
endian: Endian::Big,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
abi: Abi::SoftFloat,
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+v8a,+strict-align,-neon,-fp-armv8".into(),
features: "+v8a,+strict-align,-neon".into(),
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
arch: Arch::AArch64,
options: TargetOptions {
linker: Some("aarch64-kmc-elf-gcc".into()),
features: "+v8a,+neon,+fp-armv8".into(),
features: "+v8a,+neon".into(),
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(128),
// As documented in https://developer.android.com/ndk/guides/cpu-features.html
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
features: "+v8a,+neon,+fp-armv8".into(),
features: "+v8a,+neon".into(),
// the AAPCS64 expects use of non-leaf frame pointers per
// https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
// and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base};
pub(crate) fn target() -> Target {
let mut base = base::windows_gnullvm::opts();
base.max_atomic_width = Some(128);
base.features = "+v8a,+neon,+fp-armv8".into();
base.features = "+v8a,+neon".into();
base.linker = Some("aarch64-w64-mingw32-clang".into());

// Microsoft recommends enabling frame pointers on Arm64 Windows.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base};
pub(crate) fn target() -> Target {
let mut base = base::windows_msvc::opts();
base.max_atomic_width = Some(128);
base.features = "+v8a,+neon,+fp-armv8".into();
base.features = "+v8a,+neon".into();

// Microsoft recommends enabling frame pointers on Arm64 Windows.
// From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
arch: Arch::AArch64,
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
options: TargetOptions {
features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
features: "+v8a,+strict-align,+neon".into(),
max_atomic_width: Some(128),
stack_probes: StackProbeType::Inline,
..base::hermit::opts()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
LinkerFlavor::Gnu(Cc::No, Lld::No),
&["--fix-cortex-a53-843419"],
),
features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
features: "+v8a,+strict-align,+neon".into(),
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
relocation_model: RelocModel::Static,
disable_redzone: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
abi: Abi::SoftFloat,
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+v8a,+strict-align,-neon,-fp-armv8".into(),
features: "+v8a,+strict-align,-neon".into(),
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
LinkerFlavor::Gnu(Cc::No, Lld::No),
&["--fix-cortex-a53-843419"],
),
features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
features: "+v8a,+strict-align,+neon".into(),
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
relocation_model: RelocModel::Static,
disable_redzone: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::spec::{Arch, StackProbeType, Target, TargetMetadata, base};

pub(crate) fn target() -> Target {
let mut base = base::teeos::opts();
base.features = "+strict-align,+neon,+fp-armv8".into();
base.features = "+strict-align,+neon".into();
base.max_atomic_width = Some(128);
base.stack_probes = StackProbeType::Inline;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
arch: Arch::AArch64,
options: TargetOptions {
features: "+neon,+fp-armv8,+reserve-x18".into(),
features: "+neon,+reserve-x18".into(),
executables: true,
max_atomic_width: Some(128),
panic_strategy: PanicStrategy::Abort,
Expand Down
Loading
Loading