diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-05-06 16:28:42 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-06 16:28:42 +1000 |
| commit | 8e9a878a2a2e7297f0fe416044e423c7515e61b7 (patch) | |
| tree | e9e7dfb60263966087cc97b548d0314c9859a6d6 /compiler/rustc_codegen_ssa | |
| parent | 6238555e72b2a794c277f0a95be269aca49da093 (diff) | |
| parent | 57941afb23ef59e956d2a5ef6604369543edf419 (diff) | |
Rollup merge of #140634 - smrobtzz:mips-elf-fixes, r=workingjubilee
Use more accurate ELF flags on MIPS Changes the MIPS ELF flags used for metadata objects to be closer to what LLVM uses so the linker doesn't complain
Diffstat (limited to 'compiler/rustc_codegen_ssa')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ebcccf1b97d..ec46c71b0e4 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 { pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { match architecture { - Architecture::Mips => { - let arch = match sess.target.options.cpu.as_ref() { - "mips1" => elf::EF_MIPS_ARCH_1, - "mips2" => elf::EF_MIPS_ARCH_2, + Architecture::Mips | Architecture::Mips64 | Architecture::Mips64_N32 => { + // "N32" indicates an "ILP32" data model on a 64-bit MIPS CPU + // like SPARC's "v8+", x86_64's "x32", or the watchOS "arm64_32". + let is_32bit = architecture == Architecture::Mips; + let mut e_flags = match sess.target.options.cpu.as_ref() { + "mips1" if is_32bit => elf::EF_MIPS_ARCH_1, + "mips2" if is_32bit => elf::EF_MIPS_ARCH_2, "mips3" => elf::EF_MIPS_ARCH_3, "mips4" => elf::EF_MIPS_ARCH_4, "mips5" => elf::EF_MIPS_ARCH_5, - s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6, - _ => elf::EF_MIPS_ARCH_32R2, + "mips32r2" if is_32bit => elf::EF_MIPS_ARCH_32R2, + "mips32r6" if is_32bit => elf::EF_MIPS_ARCH_32R6, + "mips64r2" if !is_32bit => elf::EF_MIPS_ARCH_64R2, + "mips64r6" if !is_32bit => elf::EF_MIPS_ARCH_64R6, + s if s.starts_with("mips32") && !is_32bit => { + sess.dcx().fatal(format!("invalid CPU `{}` for 64-bit MIPS target", s)) + } + s if s.starts_with("mips64") && is_32bit => { + sess.dcx().fatal(format!("invalid CPU `{}` for 32-bit MIPS target", s)) + } + _ if is_32bit => elf::EF_MIPS_ARCH_32R2, + _ => elf::EF_MIPS_ARCH_64R2, }; - let mut e_flags = elf::EF_MIPS_CPIC | arch; - - // If the ABI is explicitly given, use it or default to O32. - match sess.target.options.llvm_abiname.to_lowercase().as_str() { - "n32" => e_flags |= elf::EF_MIPS_ABI2, - "o32" => e_flags |= elf::EF_MIPS_ABI_O32, - _ => e_flags |= elf::EF_MIPS_ABI_O32, + // If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS, + // which is the only "true" 32-bit option that LLVM supports. + match sess.target.options.llvm_abiname.as_ref() { + "o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32, + "n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2, + "n64" if !is_32bit => {} + "" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32, + "" => sess.dcx().fatal("LLVM ABI must be specifed for 64-bit MIPS targets"), + s if is_32bit => { + sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s)) + } + s => sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 64-bit MIPS target", s)), }; if sess.target.options.relocation_model != RelocModel::Static { - e_flags |= elf::EF_MIPS_PIC; + // PIC means position-independent code. CPIC means "calls PIC". + // CPIC was mutually exclusive with PIC according to + // the SVR4 MIPS ABI https://refspecs.linuxfoundation.org/elf/mipsabi.pdf + // and should have only appeared on static objects with dynamically calls. + // At some point someone (GCC?) decided to set CPIC even for PIC. + // Nowadays various things expect both set on the same object file + // and may even error if you mix CPIC and non-CPIC object files, + // despite that being the entire point of the CPIC ABI extension! + // As we are in Rome, we do as the Romans do. + e_flags |= elf::EF_MIPS_PIC | elf::EF_MIPS_CPIC; } if sess.target.options.cpu.contains("r6") { e_flags |= elf::EF_MIPS_NAN2008; } e_flags } - Architecture::Mips64 => { - // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` - let e_flags = elf::EF_MIPS_CPIC - | elf::EF_MIPS_PIC - | if sess.target.options.cpu.contains("r6") { - elf::EF_MIPS_ARCH_64R6 | elf::EF_MIPS_NAN2008 - } else { - elf::EF_MIPS_ARCH_64R2 - }; - e_flags - } Architecture::Riscv32 | Architecture::Riscv64 => { // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc let mut e_flags: u32 = 0x0; |
