@@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 {
270
270
271
271
pub ( super ) fn elf_e_flags ( architecture : Architecture , sess : & Session ) -> u32 {
272
272
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 ,
277
280
"mips3" => elf:: EF_MIPS_ARCH_3 ,
278
281
"mips4" => elf:: EF_MIPS_ARCH_4 ,
279
282
"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 ,
282
295
} ;
283
296
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) ) ,
291
309
} ;
292
310
293
311
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 ;
295
322
}
296
323
if sess. target . options . cpu . contains ( "r6" ) {
297
324
e_flags |= elf:: EF_MIPS_NAN2008 ;
298
325
}
299
326
e_flags
300
327
}
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
- }
312
328
Architecture :: Riscv32 | Architecture :: Riscv64 => {
313
329
// Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
314
330
let mut e_flags: u32 = 0x0 ;
0 commit comments