mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #152941 - RalfJung:abi-control, r=mati865
prefer actual ABI-controling fields over target.abi when making ABI decisions We don't actually check that `abi` is consistent with the fields that control the ABI, e.g. one could set `llvm_abiname` to "ilp32e" on a riscv target without setting a matching `abi`. So, if we need to make actual decisions, better to use the source of truth we forward to LLVM than the informational string we forward to the user. This is a breaking change for aarch64 JSON target specs: setting `abi` to "softfloat" is no longer enough; one has to also set `rustc_abi` to "softfloat". That is consistent with riscv and arm32, but it's still surprising. Cc @Darksonn in case this affects the Linux kernel. Also see https://github.com/rust-lang/rust/pull/153035 which does something similar for PowerPC, and [Zulip](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/De-spaghettifying.20ABI.20controls/with/575095372). Happy to delay this PR if someone has a better idea. Cc @folkertdev @workingjubilee
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_target::spec::{Abi, Arch, Env};
|
||||
use rustc_target::spec::{Arch, Env, RustcAbi};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::llvm::{Type, Value};
|
||||
@@ -272,7 +272,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
|
||||
|
||||
// Rust does not currently support any powerpc softfloat targets.
|
||||
let target = &bx.cx.tcx.sess.target;
|
||||
let is_soft_float_abi = target.abi == Abi::SoftFloat;
|
||||
let is_soft_float_abi = target.rustc_abi == Some(RustcAbi::Softfloat);
|
||||
assert!(!is_soft_float_abi);
|
||||
|
||||
// All instances of VaArgSafe are passed directly.
|
||||
@@ -1077,7 +1077,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
|
||||
AllowHigherAlign::Yes,
|
||||
ForceRightAdjust::Yes,
|
||||
),
|
||||
Arch::RiscV32 if target.abi == Abi::Ilp32e => {
|
||||
Arch::RiscV32 if target.llvm_abiname == "ilp32e" => {
|
||||
// FIXME: clang manually adjusts the alignment for this ABI. It notes:
|
||||
//
|
||||
// > To be compatible with GCC's behaviors, we force arguments with
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use rustc_abi::{BackendRepr, HasDataLayout, Primitive, TyAbiInterface};
|
||||
|
||||
use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
||||
use crate::spec::{Abi, HasTargetSpec, Target};
|
||||
use crate::spec::{HasTargetSpec, RustcAbi, Target};
|
||||
|
||||
/// Indicates the variant of the AArch64 ABI we are compiling for.
|
||||
/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI.
|
||||
@@ -34,7 +34,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
|
||||
RegKind::Integer => false,
|
||||
// The softfloat ABI treats floats like integers, so they
|
||||
// do not get homogeneous aggregate treatment.
|
||||
RegKind::Float => cx.target_spec().abi != Abi::SoftFloat,
|
||||
RegKind::Float => cx.target_spec().rustc_abi != Some(RustcAbi::Softfloat),
|
||||
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
|
||||
}
|
||||
|
||||
fn softfloat_float_abi<Ty>(target: &Target, arg: &mut ArgAbi<'_, Ty>) {
|
||||
if target.abi != Abi::SoftFloat {
|
||||
if target.rustc_abi != Some(RustcAbi::Softfloat) {
|
||||
return;
|
||||
}
|
||||
// Do *not* use the float registers for passing arguments, as that would make LLVM pick the ABI
|
||||
|
||||
@@ -2210,8 +2210,10 @@ pub struct TargetOptions {
|
||||
pub env: Env,
|
||||
/// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
|
||||
/// or `"eabihf"`. Defaults to [`Abi::Unspecified`].
|
||||
/// This field is *not* forwarded directly to LLVM; its primary purpose is `cfg(target_abi)`.
|
||||
/// However, parts of the backend do check this field for specific values to enable special behavior.
|
||||
/// This field is *not* forwarded directly to LLVM and therefore does not control which ABI (in
|
||||
/// the sense of function calling convention) is actually used; its primary purpose is
|
||||
/// `cfg(target_abi)`. The actual calling convention is controlled by `llvm_abiname`,
|
||||
/// `llvm_floatabi`, and `rustc_abi`.
|
||||
pub abi: Abi,
|
||||
/// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
|
||||
#[rustc_lint_opt_deny_field_access(
|
||||
@@ -3228,8 +3230,8 @@ macro_rules! check_matches {
|
||||
),
|
||||
RustcAbi::Softfloat => check_matches!(
|
||||
self.arch,
|
||||
Arch::X86 | Arch::X86_64 | Arch::S390x,
|
||||
"`softfloat` ABI is only valid for x86 and s390x targets"
|
||||
Arch::X86 | Arch::X86_64 | Arch::S390x | Arch::AArch64,
|
||||
"`softfloat` ABI is only valid for x86, s390x, and aarch64 targets"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
use rustc_abi::Endian;
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType,
|
||||
Target, TargetMetadata, TargetOptions,
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
|
||||
StackProbeType, Target, TargetMetadata, TargetOptions,
|
||||
};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: Abi::SoftFloat,
|
||||
rustc_abi: Some(RustcAbi::Softfloat),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
features: "+v8a,+strict-align,-neon".into(),
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
// For example, `-C target-cpu=cortex-a53`.
|
||||
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType,
|
||||
Target, TargetMetadata, TargetOptions,
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
|
||||
StackProbeType, Target, TargetMetadata, TargetOptions,
|
||||
};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: Abi::SoftFloat,
|
||||
rustc_abi: Some(RustcAbi::Softfloat),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
features: "+v8a,+strict-align,-neon".into(),
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::spec::{
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType,
|
||||
Target, TargetMetadata, TargetOptions,
|
||||
Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
|
||||
StackProbeType, Target, TargetMetadata, TargetOptions,
|
||||
};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: Abi::SoftFloat,
|
||||
rustc_abi: Some(RustcAbi::Softfloat),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
relocation_model: RelocModel::Static,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::spec::{Abi, Arch, FloatAbi, RustcAbi, Target};
|
||||
use crate::spec::{Arch, FloatAbi, RustcAbi, Target};
|
||||
|
||||
/// Features that control behaviour of rustc, rather than the codegen.
|
||||
/// These exist globally and are not in the target-specific lists below.
|
||||
@@ -1154,17 +1154,21 @@ pub fn abi_required_features(&self) -> FeatureConstraints {
|
||||
Arch::AArch64 | Arch::Arm64EC => {
|
||||
// Aarch64 has no sane ABI specifier, and LLVM doesn't even have a way to force
|
||||
// the use of soft-float, so all we can do here is some crude hacks.
|
||||
if self.abi == Abi::SoftFloat {
|
||||
// LLVM will use float registers when `fp-armv8` is available, e.g. for
|
||||
// calls to built-ins. The only way to ensure a consistent softfloat ABI
|
||||
// on aarch64 is to never enable `fp-armv8`, so we enforce that.
|
||||
// In Rust we tie `neon` and `fp-armv8` together, therefore `neon` is the
|
||||
// feature we have to mark as incompatible.
|
||||
FeatureConstraints { required: &[], incompatible: &["neon"] }
|
||||
} else {
|
||||
// Everything else is assumed to use a hardfloat ABI. neon and fp-armv8 must be enabled.
|
||||
// `FeatureConstraints` uses Rust feature names, hence only "neon" shows up.
|
||||
FeatureConstraints { required: &["neon"], incompatible: &[] }
|
||||
match self.rustc_abi {
|
||||
Some(RustcAbi::Softfloat) => {
|
||||
// LLVM will use float registers when `fp-armv8` is available, e.g. for
|
||||
// calls to built-ins. The only way to ensure a consistent softfloat ABI
|
||||
// on aarch64 is to never enable `fp-armv8`, so we enforce that.
|
||||
// In Rust we tie `neon` and `fp-armv8` together, therefore `neon` is the
|
||||
// feature we have to mark as incompatible.
|
||||
FeatureConstraints { required: &[], incompatible: &["neon"] }
|
||||
}
|
||||
None => {
|
||||
// Everything else is assumed to use a hardfloat ABI. neon and fp-armv8 must be enabled.
|
||||
// `FeatureConstraints` uses Rust feature names, hence only "neon" shows up.
|
||||
FeatureConstraints { required: &["neon"], incompatible: &[] }
|
||||
}
|
||||
Some(r) => panic!("invalid Rust ABI for aarch64: {r:?}"),
|
||||
}
|
||||
}
|
||||
Arch::RiscV32 | Arch::RiscV64 => {
|
||||
|
||||
Reference in New Issue
Block a user