@@ -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