Description
Cross-language LTO is broken for riscv64 lp64d (e.g. riscv64gc-unknown-linux-gnu).
I tried this code:
A minimal reproduction is available at https://github.com/kxxt/riscv-rust-cross-language-lto-reproducer
make
I expected to see this happen: code compiles and links successfully
Instead, this happened: ld.lld: error: lto.tmp: cannot link object files with different floating-point ABI from /usr/riscv64-linux-gnu/usr/lib/Scrt1.o
This is because the lack of target-abi
in llvm.module.flags
makes lld think that the rust generated bitcode is a soft float object file, contrary to the fact that riscv64gc-unknown-linux-gnu
is lp64d
.
$ llvm-dis main.o
$ grep target-abi main.o.ll
!1 = !{i32 1, !"target-abi", !"lp64d"}
$ ar x libreproducer.rlib
$ llvm-dis reproducer.reproducer.*.rcgu.o
$ grep target-abi reproducer.reproducer.*.rcgu.o.ll
(no output)
Relevant discussions:
- Encode target-abi into LLVM bitcode for LTO. - Project Infrastructure / LLVM Dev List Archives - LLVM Discussion Forums
- Per-Target LLVM Module Flags - compiler - Rust Internals
I think rustc should encode the target-abi into LLVM bitcode as clang already does.
The real world use case for this feature is cross-compiling electron/chromium for riscv64. I attempted to fix this problem by myself but due to my unfamiliarity with llvm and the rustc code base, I only came up with this workaround: embed riscv64 target abi in bc when plugin-lto is used · kxxt/rust@a599284 · GitHub . A rust toolchain including that commit can be found at https://github.com/riscv-forks/electron/releases/tag/rustc-cd6d8f2a04528f827ad3d399581c0f3502b15a72-1-llvmorg-18-init-17730-gf670112a . I believe someone from rust team could fix this problem in a better way than my patch.
Meta
rustc --version --verbose
:
rustc 1.78.0-nightly (878c8a2a6 2024-02-29)
binary: rustc
commit-hash: 878c8a2a62d49ca5c454547ad67290a1df746cb5
commit-date: 2024-02-29
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0