Skip to content

Commit 7fce460

Browse files
committed
target specs: tighten checks for llvm_abiname and llvm_floatabi, and tie them to cfg(target_abi)
1 parent ab7e9a5 commit 7fce460

2 files changed

Lines changed: 214 additions & 40 deletions

File tree

compiler/rustc_target/src/spec/base/apple/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,12 @@ pub(crate) fn base(
127127
let link_env_remove = link_env_remove(&os);
128128
let unversioned_llvm_target = unversioned_llvm_target(&os, arch, env);
129129
let mut opts = TargetOptions {
130-
llvm_floatabi: Some(FloatAbi::Hard),
130+
llvm_floatabi: if arch.target_arch() == crate::spec::Arch::Arm {
131+
Some(FloatAbi::Hard)
132+
} else {
133+
// `llvm_floatabi` makes no sense on x86 and aarch64.
134+
None
135+
},
131136
os,
132137
env: env.target_env(),
133138
cfg_abi: env.target_abi(),

compiler/rustc_target/src/spec/mod.rs

Lines changed: 208 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ crate::target_spec_enum! {
10051005
pub enum RustcAbi {
10061006
/// On x86-32 only: make use of SSE and SSE2 for ABI purposes.
10071007
X86Sse2 = "x86-sse2",
1008-
/// On x86-32/64 and S390x: do not use any FPU or SIMD registers for the ABI.
1008+
/// On x86-32/64, aarch64, and S390x: do not use any FPU or SIMD registers for the ABI.
10091009
Softfloat = "softfloat", "x86-softfloat",
10101010
}
10111011

@@ -3184,69 +3184,237 @@ impl Target {
31843184
);
31853185
}
31863186

3187-
// Check that RISC-V targets always specify which ABI they use,
3188-
// and that ARM targets specify their float ABI.
3187+
// Check ABI flag consistency, for the architectures where we have proper ABI treatment.
3188+
// To ensure targets are trated consistently, please consult with the team before allowing
3189+
// new cases.
31893190
match self.arch {
3191+
Arch::X86 => {
3192+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-32");
3193+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-32");
3194+
check_matches!(
3195+
(&self.rustc_abi, &self.cfg_abi),
3196+
// FIXME: we do not currently set a cfg_abi for softfloat targets here,
3197+
// but we probably should, so we already allow it.
3198+
(Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
3199+
| (
3200+
Some(RustcAbi::X86Sse2) | None,
3201+
Abi::Uwp | Abi::Llvm | Abi::Sim | Abi::Unspecified | Abi::Other(_)
3202+
),
3203+
"invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\n\
3204+
Rust-specific ABI: {:?}\n\
3205+
cfg(target_abi): {}",
3206+
self.rustc_abi,
3207+
self.cfg_abi,
3208+
);
3209+
}
3210+
Arch::X86_64 => {
3211+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-64");
3212+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-64");
3213+
check_matches!(
3214+
(&self.rustc_abi, &self.cfg_abi),
3215+
// FIXME: we do not currently set a cfg_abi for softfloat targets here,
3216+
// but we probably should, so we already allow it.
3217+
(Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
3218+
| (
3219+
None,
3220+
Abi::X32
3221+
| Abi::Llvm
3222+
| Abi::Fortanix
3223+
| Abi::Uwp
3224+
| Abi::MacAbi
3225+
| Abi::Sim
3226+
| Abi::Unspecified
3227+
| Abi::Other(_)
3228+
),
3229+
"invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
3230+
Rust-specific ABI: {:?}\n\
3231+
cfg(target_abi): {}",
3232+
self.rustc_abi,
3233+
self.cfg_abi,
3234+
);
3235+
}
31903236
Arch::RiscV32 => {
3237+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
3238+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
31913239
check_matches!(
3192-
&*self.llvm_abiname,
3193-
"ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
3194-
"invalid RISC-V ABI name: {}",
3240+
(&*self.llvm_abiname, &self.cfg_abi),
3241+
("ilp32", Abi::Unspecified | Abi::Other(_))
3242+
| ("ilp32f", Abi::Unspecified | Abi::Other(_))
3243+
| ("ilp32d", Abi::Unspecified | Abi::Other(_))
3244+
| ("ilp32e", Abi::Ilp32e),
3245+
"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
3246+
ABI name: {}\n\
3247+
cfg(target_abi): {}",
31953248
self.llvm_abiname,
3249+
self.cfg_abi,
31963250
);
31973251
}
31983252
Arch::RiscV64 => {
31993253
// Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
3254+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
3255+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
32003256
check_matches!(
3201-
&*self.llvm_abiname,
3202-
"lp64" | "lp64f" | "lp64d" | "lp64e",
3203-
"invalid RISC-V ABI name: {}",
3257+
(&*self.llvm_abiname, &self.cfg_abi),
3258+
("lp64", Abi::Unspecified | Abi::Other(_))
3259+
| ("lp64f", Abi::Unspecified | Abi::Other(_))
3260+
| ("lp64d", Abi::Unspecified | Abi::Other(_))
3261+
| ("lp64e", Abi::Unspecified | Abi::Other(_)),
3262+
"invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
3263+
ABI name: {}\n\
3264+
cfg(target_abi): {}",
32043265
self.llvm_abiname,
3266+
self.cfg_abi,
32053267
);
32063268
}
32073269
Arch::Arm => {
3208-
check!(
3209-
self.llvm_floatabi.is_some(),
3210-
"ARM targets must set `llvm-floatabi` to `hard` or `soft`",
3270+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on ARM");
3271+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on ARM");
3272+
check_matches!(
3273+
(&self.llvm_floatabi, &self.cfg_abi),
3274+
(
3275+
Some(FloatAbi::Hard),
3276+
Abi::EabiHf | Abi::Uwp | Abi::Unspecified | Abi::Other(_)
3277+
) | (Some(FloatAbi::Soft), Abi::Eabi),
3278+
"Invalid combination of float ABI and `cfg(`target_abi`) for ARM target\n\
3279+
float ABI: {:?}\n\
3280+
cfg(target_abi): {}",
3281+
self.llvm_floatabi,
3282+
self.cfg_abi,
32113283
)
32123284
}
3213-
// PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
3285+
Arch::AArch64 => {
3286+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on aarch64");
3287+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on aarch64");
3288+
check_matches!(
3289+
(&self.rustc_abi, &self.cfg_abi),
3290+
(Some(RustcAbi::Softfloat), Abi::SoftFloat)
3291+
| (
3292+
None,
3293+
Abi::Ilp32
3294+
| Abi::Llvm
3295+
| Abi::MacAbi
3296+
| Abi::Sim
3297+
| Abi::Uwp
3298+
| Abi::Unspecified
3299+
| Abi::Other(_)
3300+
),
3301+
"invalid aarch64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
3302+
Rust-specific ABI: {:?}\n\
3303+
cfg(target_abi): {}",
3304+
self.rustc_abi,
3305+
self.cfg_abi,
3306+
);
3307+
}
32143308
Arch::PowerPC64 => {
3309+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
3310+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
3311+
// PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
32153312
if self.os == Os::Aix {
3216-
check!(
3217-
self.llvm_abiname.is_empty(),
3218-
"AIX targets always use the AIX ABI and `llvm_abiname` should be left empty",
3313+
check_matches!(
3314+
(&*self.llvm_abiname, &self.cfg_abi),
3315+
("", Abi::VecDefault | Abi::VecExtAbi),
3316+
"invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n\
3317+
ABI name: {}\n\
3318+
cfg(target_abi): {}",
3319+
self.llvm_abiname,
3320+
self.cfg_abi,
32193321
);
32203322
} else if self.endian == Endian::Big {
32213323
check_matches!(
3222-
&*self.llvm_abiname,
3223-
"elfv1" | "elfv2",
3224-
"invalid PowerPC64 ABI name: {}",
3324+
(&*self.llvm_abiname, &self.cfg_abi),
3325+
("elfv1", Abi::ElfV1) | ("elfv2", Abi::ElfV2),
3326+
"invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\n\
3327+
ABI name: {}\n\
3328+
cfg(target_abi): {}",
32253329
self.llvm_abiname,
3330+
self.cfg_abi,
32263331
);
32273332
} else {
3228-
check!(
3229-
self.llvm_abiname == "elfv2",
3230-
"little-endian PowerPC64 targets only support the `elfv2` ABI",
3333+
check_matches!(
3334+
(&*self.llvm_abiname, &self.cfg_abi),
3335+
("elfv2", Abi::ElfV2),
3336+
"invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\n\
3337+
ABI name: {}\n\
3338+
cfg(target_abi): {}",
3339+
self.llvm_abiname,
3340+
self.cfg_abi,
32313341
);
32323342
}
32333343
}
3234-
_ => {}
3235-
}
3236-
3237-
// Check consistency of Rust ABI declaration.
3238-
if let Some(rust_abi) = self.rustc_abi {
3239-
match rust_abi {
3240-
RustcAbi::X86Sse2 => check_matches!(
3241-
self.arch,
3242-
Arch::X86,
3243-
"`x86-sse2` ABI is only valid for x86-32 targets"
3244-
),
3245-
RustcAbi::Softfloat => check_matches!(
3246-
self.arch,
3247-
Arch::X86 | Arch::X86_64 | Arch::S390x | Arch::AArch64,
3248-
"`softfloat` ABI is only valid for x86, s390x, and aarch64 targets"
3249-
),
3344+
Arch::S390x => {
3345+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on s390x");
3346+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on s390x");
3347+
check_matches!(
3348+
(&self.rustc_abi, &self.cfg_abi),
3349+
(Some(RustcAbi::Softfloat), Abi::SoftFloat)
3350+
| (None, Abi::Unspecified | Abi::Other(_)),
3351+
"invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\n\
3352+
Rust-specific ABI: {:?}\n\
3353+
cfg(target_abi): {}",
3354+
self.rustc_abi,
3355+
self.cfg_abi,
3356+
);
3357+
}
3358+
Arch::LoongArch32 => {
3359+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
3360+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
3361+
check_matches!(
3362+
(&*self.llvm_abiname, &self.cfg_abi),
3363+
("ilp32s", Abi::SoftFloat) | ("ilp32d", Abi::Unspecified | Abi::Other(_)),
3364+
"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
3365+
ABI name: {}\n\
3366+
cfg(target_abi): {}",
3367+
self.llvm_abiname,
3368+
self.cfg_abi,
3369+
);
3370+
}
3371+
Arch::LoongArch64 => {
3372+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
3373+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
3374+
check_matches!(
3375+
(&*self.llvm_abiname, &self.cfg_abi),
3376+
("lp64s", Abi::SoftFloat) | ("lp64d", Abi::Unspecified | Abi::Other(_)),
3377+
"invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
3378+
ABI name: {}\n\
3379+
cfg(target_abi): {}",
3380+
self.llvm_abiname,
3381+
self.cfg_abi,
3382+
);
3383+
}
3384+
Arch::Mips => {
3385+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
3386+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
3387+
check_matches!(
3388+
(&*self.llvm_abiname, &self.cfg_abi),
3389+
// FIXME: we should force it to always be non-empty.
3390+
("o32", Abi::Unspecified | Abi::Other(_))
3391+
| ("", Abi::Unspecified | Abi::Other(_)),
3392+
"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
3393+
ABI name: {}\n\
3394+
cfg(target_abi): {}",
3395+
self.llvm_abiname,
3396+
self.cfg_abi,
3397+
);
3398+
}
3399+
Arch::Mips64 | Arch::Mips64r6 => {
3400+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
3401+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
3402+
check_matches!(
3403+
(&*self.llvm_abiname, &self.cfg_abi),
3404+
("n64", Abi::Abi64),
3405+
"invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
3406+
ABI name: {}\n\
3407+
cfg(target_abi): {}",
3408+
self.llvm_abiname,
3409+
self.cfg_abi,
3410+
);
3411+
}
3412+
ref arch => {
3413+
check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on {arch}");
3414+
check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on {arch}");
3415+
check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on {arch}");
3416+
// We don't know what's going on with ABIs on these architectures, so we allow
3417+
// arbitrary values for `cfg_abi` here.
32503418
}
32513419
}
32523420

@@ -3306,7 +3474,8 @@ impl Target {
33063474
let recycled_target =
33073475
Target::from_json(&serde_json::to_string(&self.to_json()).unwrap()).map(|(j, _)| j);
33083476
self.update_to_cli();
3309-
self.check_consistency(TargetKind::Builtin).unwrap();
3477+
self.check_consistency(TargetKind::Builtin)
3478+
.unwrap_or_else(|err| panic!("Target consistency check failed:\n{err}"));
33103479
assert_eq!(recycled_target, Ok(self));
33113480
}
33123481

0 commit comments

Comments
 (0)