@@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 {
270270
271271pub ( super ) fn elf_e_flags ( architecture : Architecture , sess : & Session ) -> u32 {
272272 match architecture {
273- Architecture :: Mips => {
274- let arch = match sess. target . options . cpu . as_ref ( ) {
275- "mips1" => elf:: EF_MIPS_ARCH_1 ,
276- "mips2" => elf:: EF_MIPS_ARCH_2 ,
273+ Architecture :: Mips | Architecture :: Mips64 | Architecture :: Mips64_N32 => {
274+ // "N32" indicates an "ILP32" data model on a 64-bit MIPS CPU
275+ // like SPARC's "v8+", x86_64's "x32", or the watchOS "arm64_32".
276+ let is_32bit = architecture == Architecture :: Mips ;
277+ let mut e_flags = match sess. target . options . cpu . as_ref ( ) {
278+ "mips1" if is_32bit => elf:: EF_MIPS_ARCH_1 ,
279+ "mips2" if is_32bit => elf:: EF_MIPS_ARCH_2 ,
277280 "mips3" => elf:: EF_MIPS_ARCH_3 ,
278281 "mips4" => elf:: EF_MIPS_ARCH_4 ,
279282 "mips5" => elf:: EF_MIPS_ARCH_5 ,
280- s if s. contains ( "r6" ) => elf:: EF_MIPS_ARCH_32R6 ,
281- _ => elf:: EF_MIPS_ARCH_32R2 ,
283+ "mips32r2" if is_32bit => elf:: EF_MIPS_ARCH_32R2 ,
284+ "mips32r6" if is_32bit => elf:: EF_MIPS_ARCH_32R6 ,
285+ "mips64r2" if !is_32bit => elf:: EF_MIPS_ARCH_64R2 ,
286+ "mips64r6" if !is_32bit => elf:: EF_MIPS_ARCH_64R6 ,
287+ s if s. starts_with ( "mips32" ) && !is_32bit => {
288+ sess. dcx ( ) . fatal ( format ! ( "invalid CPU `{}` for 64-bit MIPS target" , s) )
289+ }
290+ s if s. starts_with ( "mips64" ) && is_32bit => {
291+ sess. dcx ( ) . fatal ( format ! ( "invalid CPU `{}` for 32-bit MIPS target" , s) )
292+ }
293+ _ if is_32bit => elf:: EF_MIPS_ARCH_32R2 ,
294+ _ => elf:: EF_MIPS_ARCH_64R2 ,
282295 } ;
283296
284- let mut e_flags = elf:: EF_MIPS_CPIC | arch;
285-
286- // If the ABI is explicitly given, use it or default to O32.
287- match sess. target . options . llvm_abiname . to_lowercase ( ) . as_str ( ) {
288- "n32" => e_flags |= elf:: EF_MIPS_ABI2 ,
289- "o32" => e_flags |= elf:: EF_MIPS_ABI_O32 ,
290- _ => e_flags |= elf:: EF_MIPS_ABI_O32 ,
297+ // If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS,
298+ // which is the only "true" 32-bit option that LLVM supports.
299+ match sess. target . options . llvm_abiname . as_ref ( ) {
300+ "o32" if is_32bit => e_flags |= elf:: EF_MIPS_ABI_O32 ,
301+ "n32" if !is_32bit => e_flags |= elf:: EF_MIPS_ABI2 ,
302+ "n64" if !is_32bit => { }
303+ "" if is_32bit => e_flags |= elf:: EF_MIPS_ABI_O32 ,
304+ "" => sess. dcx ( ) . fatal ( "LLVM ABI must be specifed for 64-bit MIPS targets" ) ,
305+ s if is_32bit => {
306+ sess. dcx ( ) . fatal ( format ! ( "invalid LLVM ABI `{}` for 32-bit MIPS target" , s) )
307+ }
308+ s => sess. dcx ( ) . fatal ( format ! ( "invalid LLVM ABI `{}` for 64-bit MIPS target" , s) ) ,
291309 } ;
292310
293311 if sess. target . options . relocation_model != RelocModel :: Static {
294- e_flags |= elf:: EF_MIPS_PIC ;
312+ // PIC means position-independent code. CPIC means "calls PIC".
313+ // CPIC was mutually exclusive with PIC according to
314+ // the SVR4 MIPS ABI https://refspecs.linuxfoundation.org/elf/mipsabi.pdf
315+ // and should have only appeared on static objects with dynamically calls.
316+ // At some point someone (GCC?) decided to set CPIC even for PIC.
317+ // Nowadays various things expect both set on the same object file
318+ // and may even error if you mix CPIC and non-CPIC object files,
319+ // despite that being the entire point of the CPIC ABI extension!
320+ // As we are in Rome, we do as the Romans do.
321+ e_flags |= elf:: EF_MIPS_PIC | elf:: EF_MIPS_CPIC ;
295322 }
296323 if sess. target . options . cpu . contains ( "r6" ) {
297324 e_flags |= elf:: EF_MIPS_NAN2008 ;
298325 }
299326 e_flags
300327 }
301- Architecture :: Mips64 => {
302- // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
303- let e_flags = elf:: EF_MIPS_CPIC
304- | elf:: EF_MIPS_PIC
305- | if sess. target . options . cpu . contains ( "r6" ) {
306- elf:: EF_MIPS_ARCH_64R6 | elf:: EF_MIPS_NAN2008
307- } else {
308- elf:: EF_MIPS_ARCH_64R2
309- } ;
310- e_flags
311- }
312328 Architecture :: Riscv32 | Architecture :: Riscv64 => {
313329 // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
314330 let mut e_flags: u32 = 0x0 ;
0 commit comments