Skip to content

Commit a7c6b50

Browse files
authored
Rollup merge of rust-lang#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
2 parents 7300b97 + 57941af commit a7c6b50

9 files changed

+66
-27
lines changed

compiler/rustc_codegen_ssa/src/back/metadata.rs

+41-25
Original file line numberDiff line numberDiff line change
@@ -270,45 +270,61 @@ pub(super) fn elf_os_abi(sess: &Session) -> u8 {
270270

271271
pub(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;

compiler/rustc_target/src/spec/mod.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -3567,7 +3567,19 @@ impl Target {
35673567
"x86" => (Architecture::I386, None),
35683568
"s390x" => (Architecture::S390x, None),
35693569
"mips" | "mips32r6" => (Architecture::Mips, None),
3570-
"mips64" | "mips64r6" => (Architecture::Mips64, None),
3570+
"mips64" | "mips64r6" => (
3571+
// While there are currently no builtin targets
3572+
// using the N32 ABI, it is possible to specify
3573+
// it using a custom target specification. N32
3574+
// is an ILP32 ABI like the Aarch64_Ilp32
3575+
// and X86_64_X32 cases above and below this one.
3576+
if self.options.llvm_abiname.as_ref() == "n32" {
3577+
Architecture::Mips64_N32
3578+
} else {
3579+
Architecture::Mips64
3580+
},
3581+
None,
3582+
),
35713583
"x86_64" => (
35723584
if self.pointer_width == 32 {
35733585
Architecture::X86_64_X32

compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) fn target() -> Target {
2727
abi: "abi64".into(),
2828
endian: Endian::Big,
2929
mcount: "_mcount".into(),
30+
llvm_abiname: "n64".into(),
3031
..base
3132
},
3233
}

compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
2222
features: "+mips64r2,+xgot".into(),
2323
max_atomic_width: Some(64),
2424
mcount: "_mcount".into(),
25+
llvm_abiname: "n64".into(),
2526

2627
..base::linux_gnu::opts()
2728
},

compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub(crate) fn target() -> Target {
2525
mcount: "_mcount".into(),
2626
// FIXME(compiler-team#422): musl targets should be dynamically linked by default.
2727
crt_static_default: true,
28+
llvm_abiname: "n64".into(),
2829
..base
2930
},
3031
}

compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) fn target() -> Target {
1919
features: "+mips64r2,+xgot".into(),
2020
max_atomic_width: Some(64),
2121
mcount: "_mcount".into(),
22+
llvm_abiname: "n64".into(),
2223

2324
..base::linux_gnu::opts()
2425
},

compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ pub(crate) fn target() -> Target {
1919
pointer_width: 64,
2020
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
2121
arch: "mips64".into(),
22-
options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
22+
options: TargetOptions {
23+
abi: "abi64".into(),
24+
mcount: "_mcount".into(),
25+
llvm_abiname: "n64".into(),
26+
..base
27+
},
2328
}
2429
}

compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
2222
features: "+mips64r6".into(),
2323
max_atomic_width: Some(64),
2424
mcount: "_mcount".into(),
25+
llvm_abiname: "n64".into(),
2526

2627
..base::linux_gnu::opts()
2728
},

compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) fn target() -> Target {
1919
features: "+mips64r6".into(),
2020
max_atomic_width: Some(64),
2121
mcount: "_mcount".into(),
22+
llvm_abiname: "n64".into(),
2223

2324
..base::linux_gnu::opts()
2425
},

0 commit comments

Comments
 (0)