@@ -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
@@ -3183,69 +3183,277 @@ impl Target {
31833183 ) ;
31843184 }
31853185
3186- // Check that RISC-V targets always specify which ABI they use,
3187- // and that ARM targets specify their float ABI.
3186+ // Check ABI flag consistency, for the architectures where we have proper ABI treatment.
3187+ // To ensure targets are trated consistently, please consult with the team before allowing
3188+ // new cases.
31883189 match self . arch {
3190+ Arch :: X86 => {
3191+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on x86-32" ) ;
3192+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on x86-32" ) ;
3193+ check_matches ! (
3194+ ( & self . rustc_abi, & self . abi) ,
3195+ // FIXME: we do not currently set a target_abi for softfloat targets here,
3196+ // but we probably should, so we already allow it.
3197+ ( Some ( RustcAbi :: Softfloat ) , Abi :: SoftFloat | Abi :: Unspecified | Abi :: Other ( _) )
3198+ | (
3199+ Some ( RustcAbi :: X86Sse2 ) | None ,
3200+ Abi :: Uwp | Abi :: Llvm | Abi :: Sim | Abi :: Unspecified | Abi :: Other ( _)
3201+ ) ,
3202+ "invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\n \
3203+ Rust-specific ABI: {:?}\n \
3204+ cfg(target_abi): {}",
3205+ self . rustc_abi,
3206+ self . abi,
3207+ ) ;
3208+ }
3209+ Arch :: X86_64 => {
3210+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on x86-64" ) ;
3211+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on x86-64" ) ;
3212+ // FIXME: we do not currently set a target_abi for softfloat targets here, but we
3213+ // probably should, so we already allow it.
3214+ // FIXME: Ensure that target_abi = "x32" correlates with actually using that ABI.
3215+ // Do any of the others need a similar check?
3216+ check_matches ! (
3217+ ( & self . rustc_abi, & self . abi) ,
3218+ ( Some ( RustcAbi :: Softfloat ) , Abi :: SoftFloat | Abi :: Unspecified | Abi :: Other ( _) )
3219+ | (
3220+ None ,
3221+ Abi :: X32
3222+ | Abi :: Llvm
3223+ | Abi :: Fortanix
3224+ | Abi :: Uwp
3225+ | Abi :: MacAbi
3226+ | Abi :: Sim
3227+ | Abi :: Unspecified
3228+ | Abi :: Other ( _)
3229+ ) ,
3230+ "invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\n \
3231+ Rust-specific ABI: {:?}\n \
3232+ cfg(target_abi): {}",
3233+ self . rustc_abi,
3234+ self . abi,
3235+ ) ;
3236+ }
31893237 Arch :: RiscV32 => {
3238+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on RISC-V" ) ;
3239+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on RISC-V" ) ;
31903240 check_matches ! (
3191- & * self . llvm_abiname,
3192- "ilp32" | "ilp32f" | "ilp32d" | "ilp32e" ,
3193- "invalid RISC-V ABI name: {}" ,
3241+ ( & * self . llvm_abiname, & self . abi) ,
3242+ ( "ilp32" , Abi :: Unspecified | Abi :: Other ( _) )
3243+ | ( "ilp32f" , Abi :: Unspecified | Abi :: Other ( _) )
3244+ | ( "ilp32d" , Abi :: Unspecified | Abi :: Other ( _) )
3245+ | ( "ilp32e" , Abi :: Ilp32e ) ,
3246+ "invalid RISC-V ABI name and `cfg(target_abi)` combination:\n \
3247+ ABI name: {}\n \
3248+ cfg(target_abi): {}",
31943249 self . llvm_abiname,
3250+ self . abi,
31953251 ) ;
31963252 }
31973253 Arch :: RiscV64 => {
31983254 // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
3255+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on RISC-V" ) ;
3256+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on RISC-V" ) ;
31993257 check_matches ! (
3200- & * self . llvm_abiname,
3201- "lp64" | "lp64f" | "lp64d" | "lp64e" ,
3202- "invalid RISC-V ABI name: {}" ,
3258+ ( & * self . llvm_abiname, & self . abi) ,
3259+ ( "lp64" , Abi :: Unspecified | Abi :: Other ( _) )
3260+ | ( "lp64f" , Abi :: Unspecified | Abi :: Other ( _) )
3261+ | ( "lp64d" , Abi :: Unspecified | Abi :: Other ( _) )
3262+ | ( "lp64e" , Abi :: Unspecified | Abi :: Other ( _) ) ,
3263+ "invalid RISC-V ABI name and `cfg(target_abi)` combination:\n \
3264+ ABI name: {}\n \
3265+ cfg(target_abi): {}",
32033266 self . llvm_abiname,
3267+ self . abi,
32043268 ) ;
32053269 }
32063270 Arch :: Arm => {
3207- check ! (
3208- self . llvm_floatabi. is_some( ) ,
3209- "ARM targets must set `llvm-floatabi` to `hard` or `soft`" ,
3271+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on ARM" ) ;
3272+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on ARM" ) ;
3273+ check_matches ! (
3274+ ( & self . llvm_floatabi, & self . abi) ,
3275+ (
3276+ Some ( FloatAbi :: Hard ) ,
3277+ Abi :: EabiHf | Abi :: Uwp | Abi :: Unspecified | Abi :: Other ( _)
3278+ ) | ( Some ( FloatAbi :: Soft ) , Abi :: Eabi ) ,
3279+ "Invalid combination of float ABI and `cfg(target_abi)` for ARM target\n \
3280+ float ABI: {:?}\n \
3281+ cfg(target_abi): {}",
3282+ self . llvm_floatabi,
3283+ self . abi,
32103284 )
32113285 }
3212- // PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
3286+ Arch :: AArch64 => {
3287+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on aarch64" ) ;
3288+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on aarch64" ) ;
3289+ // FIXME: Ensure that target_abi = "ilp32" correlates with actually using that ABI.
3290+ // Do any of the others need a similar check?
3291+ check_matches ! (
3292+ ( & self . rustc_abi, & self . abi) ,
3293+ ( Some ( RustcAbi :: Softfloat ) , Abi :: SoftFloat )
3294+ | (
3295+ None ,
3296+ Abi :: Ilp32
3297+ | Abi :: Llvm
3298+ | Abi :: MacAbi
3299+ | Abi :: Sim
3300+ | Abi :: Uwp
3301+ | Abi :: Unspecified
3302+ | Abi :: Other ( _)
3303+ ) ,
3304+ "invalid aarch64 Rust-specific ABI and `cfg(target_abi)` combination:\n \
3305+ Rust-specific ABI: {:?}\n \
3306+ cfg(target_abi): {}",
3307+ self . rustc_abi,
3308+ self . abi,
3309+ ) ;
3310+ }
3311+ Arch :: PowerPC => {
3312+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on PowerPC" ) ;
3313+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on PowerPC" ) ;
3314+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on PowerPC" ) ;
3315+ // FIXME: Check that `target_abi` matches the actually configured ABI (with or
3316+ // without SPE).
3317+ check_matches ! (
3318+ self . abi,
3319+ Abi :: Spe | Abi :: Unspecified | Abi :: Other ( _) ,
3320+ "invalid `target_abi` for PowerPC"
3321+ ) ;
3322+ }
32133323 Arch :: PowerPC64 => {
3324+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on PowerPC64" ) ;
3325+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on PowerPC64" ) ;
3326+ // PowerPC64 targets that are not AIX must set their ABI to either ELFv1 or ELFv2
32143327 if self . os == Os :: Aix {
3215- check ! (
3216- self . llvm_abiname. is_empty( ) ,
3217- "AIX targets always use the AIX ABI and `llvm_abiname` should be left empty" ,
3328+ // FIXME: Check that `target_abi` matches the actually configured ABI
3329+ // (vec-default vs vec-ext).
3330+ check_matches ! (
3331+ ( & * self . llvm_abiname, & self . abi) ,
3332+ ( "" , Abi :: VecDefault | Abi :: VecExtAbi ) ,
3333+ "invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n \
3334+ ABI name: {}\n \
3335+ cfg(target_abi): {}",
3336+ self . llvm_abiname,
3337+ self . abi,
32183338 ) ;
32193339 } else if self . endian == Endian :: Big {
32203340 check_matches ! (
3221- & * self . llvm_abiname,
3222- "elfv1" | "elfv2" ,
3223- "invalid PowerPC64 ABI name: {}" ,
3341+ ( & * self . llvm_abiname, & self . abi) ,
3342+ ( "elfv1" , Abi :: ElfV1 ) | ( "elfv2" , Abi :: ElfV2 ) ,
3343+ "invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\n \
3344+ ABI name: {}\n \
3345+ cfg(target_abi): {}",
32243346 self . llvm_abiname,
3347+ self . abi,
32253348 ) ;
32263349 } else {
3227- check ! (
3228- self . llvm_abiname == "elfv2" ,
3229- "little-endian PowerPC64 targets only support the `elfv2` ABI" ,
3350+ check_matches ! (
3351+ ( & * self . llvm_abiname, & self . abi) ,
3352+ ( "elfv2" , Abi :: ElfV2 ) ,
3353+ "invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\n \
3354+ ABI name: {}\n \
3355+ cfg(target_abi): {}",
3356+ self . llvm_abiname,
3357+ self . abi,
32303358 ) ;
32313359 }
32323360 }
3233- _ => { }
3234- }
3235-
3236- // Check consistency of Rust ABI declaration.
3237- if let Some ( rust_abi) = self . rustc_abi {
3238- match rust_abi {
3239- RustcAbi :: X86Sse2 => check_matches ! (
3240- self . arch,
3241- Arch :: X86 ,
3242- "`x86-sse2` ABI is only valid for x86-32 targets"
3243- ) ,
3244- RustcAbi :: Softfloat => check_matches ! (
3245- self . arch,
3246- Arch :: X86 | Arch :: X86_64 | Arch :: S390x | Arch :: AArch64 ,
3247- "`softfloat` ABI is only valid for x86, s390x, and aarch64 targets"
3248- ) ,
3361+ Arch :: S390x => {
3362+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on s390x" ) ;
3363+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on s390x" ) ;
3364+ check_matches ! (
3365+ ( & self . rustc_abi, & self . abi) ,
3366+ ( Some ( RustcAbi :: Softfloat ) , Abi :: SoftFloat )
3367+ | ( None , Abi :: Unspecified | Abi :: Other ( _) ) ,
3368+ "invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\n \
3369+ Rust-specific ABI: {:?}\n \
3370+ cfg(target_abi): {}",
3371+ self . rustc_abi,
3372+ self . abi,
3373+ ) ;
3374+ }
3375+ Arch :: LoongArch32 => {
3376+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on LoongArch" ) ;
3377+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on LoongArch" ) ;
3378+ check_matches ! (
3379+ ( & * self . llvm_abiname, & self . abi) ,
3380+ ( "ilp32s" , Abi :: SoftFloat )
3381+ | ( "ilp32f" , Abi :: Unspecified | Abi :: Other ( _) )
3382+ | ( "ilp32d" , Abi :: Unspecified | Abi :: Other ( _) ) ,
3383+ "invalid LoongArch ABI name and `cfg(target_abi)` combination:\n \
3384+ ABI name: {}\n \
3385+ cfg(target_abi): {}",
3386+ self . llvm_abiname,
3387+ self . abi,
3388+ ) ;
3389+ }
3390+ Arch :: LoongArch64 => {
3391+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on LoongArch" ) ;
3392+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on LoongArch" ) ;
3393+ check_matches ! (
3394+ ( & * self . llvm_abiname, & self . abi) ,
3395+ ( "lp64s" , Abi :: SoftFloat )
3396+ | ( "lp64f" , Abi :: Unspecified | Abi :: Other ( _) )
3397+ | ( "lp64d" , Abi :: Unspecified | Abi :: Other ( _) ) ,
3398+ "invalid LoongArch ABI name and `cfg(target_abi)` combination:\n \
3399+ ABI name: {}\n \
3400+ cfg(target_abi): {}",
3401+ self . llvm_abiname,
3402+ self . abi,
3403+ ) ;
3404+ }
3405+ Arch :: Mips => {
3406+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on MIPS" ) ;
3407+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on MIPS" ) ;
3408+ check_matches ! (
3409+ ( & * self . llvm_abiname, & self . abi) ,
3410+ // FIXME: we should force it to always be non-empty.
3411+ ( "o32" , Abi :: Unspecified | Abi :: Other ( _) )
3412+ | ( "" , Abi :: Unspecified | Abi :: Other ( _) ) ,
3413+ "invalid MIPS ABI name and `cfg(target_abi)` combination:\n \
3414+ ABI name: {}\n \
3415+ cfg(target_abi): {}",
3416+ self . llvm_abiname,
3417+ self . abi,
3418+ ) ;
3419+ }
3420+ Arch :: Mips64 | Arch :: Mips64r6 => {
3421+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on MIPS" ) ;
3422+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on MIPS" ) ;
3423+ check_matches ! (
3424+ ( & * self . llvm_abiname, & self . abi) ,
3425+ ( "n64" , Abi :: Abi64 ) ,
3426+ "invalid MIPS ABI name and `cfg(target_abi)` combination:\n \
3427+ ABI name: {}\n \
3428+ cfg(target_abi): {}",
3429+ self . llvm_abiname,
3430+ self . abi,
3431+ ) ;
3432+ }
3433+ Arch :: CSky => {
3434+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on CSky" ) ;
3435+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on CSky" ) ;
3436+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on CSky" ) ;
3437+ // FIXME: Check that `target_abi` matches the actually configured ABI (v2 vs v2hf).
3438+ check_matches ! (
3439+ self . abi,
3440+ Abi :: AbiV2 | Abi :: AbiV2Hf ,
3441+ "invalid `target_abi` for CSky"
3442+ ) ;
3443+ }
3444+ ref arch => {
3445+ check ! ( self . rustc_abi. is_none( ) , "`rustc_abi` is unused on {arch}" ) ;
3446+ // Ensure consistency among built-in targets, but give JSON targets the opportunity
3447+ // to experiment with these.
3448+ if kind == TargetKind :: Builtin {
3449+ check ! ( self . llvm_abiname. is_empty( ) , "`llvm_abiname` is unused on {arch}" ) ;
3450+ check ! ( self . llvm_floatabi. is_none( ) , "`llvm_floatabi` is unused on {arch}" ) ;
3451+ check_matches ! (
3452+ self . abi,
3453+ Abi :: Unspecified | Abi :: Other ( _) ,
3454+ "`target_abi` is unused on {arch}"
3455+ ) ;
3456+ }
32493457 }
32503458 }
32513459
@@ -3305,7 +3513,8 @@ impl Target {
33053513 let recycled_target =
33063514 Target :: from_json ( & serde_json:: to_string ( & self . to_json ( ) ) . unwrap ( ) ) . map ( |( j, _) | j) ;
33073515 self . update_to_cli ( ) ;
3308- self . check_consistency ( TargetKind :: Builtin ) . unwrap ( ) ;
3516+ self . check_consistency ( TargetKind :: Builtin )
3517+ . unwrap_or_else ( |err| panic ! ( "Target consistency check failed:\n {err}" ) ) ;
33093518 assert_eq ! ( recycled_target, Ok ( self ) ) ;
33103519 }
33113520
0 commit comments