Skip to content

Commit

Permalink
Auto merge of #114332 - nbdd0121:riscv, r=compiler-errors
Browse files Browse the repository at this point in the history
Fix ABI flags in RISC-V/LoongArch ELF file generated by rustc

Fix #114153

It turns out the current way to set these flags are completely wrong. In LLVM the target ABI is used instead of target features to determine these flags.

Not sure how to write a test though. Or maybe a test isn't necessary because this affects only those touching target json?

r? `@Nilstrieb`
  • Loading branch information
bors committed Aug 20, 2023
2 parents 82c5732 + 2f68d97 commit 484cb4e
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 70 deletions.
38 changes: 21 additions & 17 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_metadata::fs::METADATA_FILENAME;
use rustc_metadata::EncodedMetadata;
use rustc_session::cstore::MetadataLoader;
use rustc_session::Session;
use rustc_span::sym;
use rustc_target::abi::Endian;
use rustc_target::spec::{ef_avr_arch, RelocModel, Target};

Expand Down Expand Up @@ -272,35 +273,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
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;
let features = &sess.target.options.features;

// Check if compressed is enabled
if features.contains("+c") {
// `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
if sess.unstable_target_features.contains(&sym::c) {
e_flags |= elf::EF_RISCV_RVC;
}

// Select the appropriate floating-point ABI
if features.contains("+d") {
e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE;
} else if features.contains("+f") {
e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE;
} else {
e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT;
// Set the appropriate flag based on ABI
// This needs to match LLVM `RISCVELFStreamer.cpp`
match &*sess.target.llvm_abiname {
"" | "ilp32" | "lp64" => (),
"ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
"ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
"ilp32e" => e_flags |= elf::EF_RISCV_RVE,
_ => bug!("unknown RISC-V ABI name"),
}

e_flags
}
Architecture::LoongArch64 => {
// Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
let features = &sess.target.options.features;

// Select the appropriate floating-point ABI
if features.contains("+d") {
e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT;
} else if features.contains("+f") {
e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT;
} else {
e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT;
// Set the appropriate flag based on ABI
// This needs to match LLVM `LoongArchELFStreamer.cpp`
match &*sess.target.llvm_abiname {
"ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
"ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
"ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
_ => bug!("unknown RISC-V ABI name"),
}

e_flags
}
Architecture::Avr => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ symbols! {
bridge,
bswap,
builtin_syntax,
c,
c_str,
c_str_literals,
c_unwind,
Expand Down
68 changes: 34 additions & 34 deletions tests/ui/or-patterns/missing-bindings.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
| |
| pattern doesn't bind `a`

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:12
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| ^^^^^^^ - variable not in all patterns
| |
| pattern doesn't bind `c`

error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:22
|
Expand All @@ -96,12 +104,12 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| variable not in all patterns

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:12
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| ^^^^^^^ - variable not in all patterns
| |
| pattern doesn't bind `c`
| - ^^^^ pattern doesn't bind `c`
| |
| variable not in all patterns

error[E0408]: variable `d` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
Expand Down Expand Up @@ -135,14 +143,6 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| |
| variable not in all patterns

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| - ^^^^ pattern doesn't bind `c`
| |
| variable not in all patterns

error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:61:29
|
Expand Down Expand Up @@ -185,6 +185,28 @@ LL | B(b),
LL | B(_)
| ^^^^ pattern doesn't bind `b`

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:57:13
|
LL | / V1(
LL | |
LL | |
LL | | A(
... |
LL | | B(Ok(a) | Err(a))
LL | | ) |
| |_____________^ pattern doesn't bind `c`
LL | / V2(
LL | | A(
LL | | A(_, a) |
LL | | B(b),
... |
LL | |
LL | | ) |
| |_____________^ pattern doesn't bind `c`
LL | V3(c),
| - variable not in all patterns

error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:76:13
|
Expand Down Expand Up @@ -215,28 +237,6 @@ LL | B(b),
LL | V3(c),
| ^^^^^ pattern doesn't bind `b`

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:57:13
|
LL | / V1(
LL | |
LL | |
LL | | A(
... |
LL | | B(Ok(a) | Err(a))
LL | | ) |
| |_____________^ pattern doesn't bind `c`
LL | / V2(
LL | | A(
LL | | A(_, a) |
LL | | B(b),
... |
LL | |
LL | | ) |
| |_____________^ pattern doesn't bind `c`
LL | V3(c),
| - variable not in all patterns

error: aborting due to 26 previous errors

For more information about this error, try `rustc --explain E0408`.
18 changes: 9 additions & 9 deletions tests/ui/resolve/resolve-inconsistent-names.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ LL | a | b => {}
| |
| pattern doesn't bind `b`

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:19:9
|
LL | (A, B) | (ref B, c) | (c, A) => ()
| ^^^^^^ - - variable not in all patterns
| | |
| | variable not in all patterns
| pattern doesn't bind `c`

error[E0408]: variable `A` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:19:18
|
Expand All @@ -37,15 +46,6 @@ LL | (A, B) | (ref B, c) | (c, A) => ()
| | variable not in all patterns
| variable not in all patterns

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:19:9
|
LL | (A, B) | (ref B, c) | (c, A) => ()
| ^^^^^^ - - variable not in all patterns
| | |
| | variable not in all patterns
| pattern doesn't bind `c`

error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|`
--> $DIR/resolve-inconsistent-names.rs:19:23
|
Expand Down
20 changes: 10 additions & 10 deletions tests/ui/span/issue-39698.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
error[E0408]: variable `c` is not bound in all patterns
--> $DIR/issue-39698.rs:10:9
|
LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c`
| | | |
| | | variable not in all patterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`

error[E0408]: variable `d` is not bound in all patterns
--> $DIR/issue-39698.rs:10:37
|
Expand Down Expand Up @@ -28,16 +38,6 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
| | variable not in all patterns
| pattern doesn't bind `b`

error[E0408]: variable `c` is not bound in all patterns
--> $DIR/issue-39698.rs:10:9
|
LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c`
| | | |
| | | variable not in all patterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0408`.

0 comments on commit 484cb4e

Please sign in to comment.