Skip to content

Linker-plugin-based LTO with -flto in clang not working #138910

Open
@ghost

Description

The original issue title was "Implement cross-language ThinLTO," #49879 but when it was stabilized, the PR title became "Stabilize linker-plugin based LTO (aka cross-language LTO)," #58057 which seems to imply that fullLTO is available. The Rustc book states, "In both cases the Rust code has to be compiled with -C linker-plugin-lto and the C/C++ code with -flto or -flto=thin so that object files are emitted as LLVM bitcode," https://doc.rust-lang.org/rustc/linker-plugin-lto.html which also seems to confirm this. However, the documentation does not provide an example of fullLTO, and simply replacing "-flto=thin" with "-flto" does not work. Therefore, this should be considered a bug.

// with clang -flto=thin
// works
000000000005e054 <c_func_in_rust>:
   5e054:	52800540 	mov	w0, #0x2a                  	// #42
   5e058:	d65f03c0 	ret
// with clang -flto
// doesn't work
000000000005e09c <c_func_in_rust>:
   5e09c:	17ffffd9 	b	5e000 <c_func_in_c>

000000000005e000 <c_func_in_c>:
   5e000:	52800540 	mov	w0, #0x2a                  	// #42
   5e004:	d65f03c0 	ret
$ rustc --version --verbose
rustc 1.85.1 (4eb161250 2025-03-15)
binary: rustc
commit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181
commit-date: 2025-03-15
host: aarch64-unknown-linux-gnu
release: 1.85.1
LLVM version: 19.1.7
# build.sh
# copied from https://doc.rust-lang.org/rustc/linker-plugin-lto.html
clang ./clib.c -flto=thin -c -o ./clib.o -O2
#                   ^^^^^ remove this and it will not work
ar crus ./libxyz.a ./clib.o
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
objdump -d target/release/x > dump
// main.rs
use std::ffi::c_int;

fn main() {
    println!("{}", c_func_in_rust());
}

#[inline(never)]
#[unsafe(no_mangle)]
pub extern "C" fn c_func_in_rust() -> c_int {
    unsafe { c_func_in_c() }
}

unsafe extern "C" {
    fn c_func_in_c() -> c_int;
}
// build.rs
fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rustc-link-search=.");
    println!("cargo:rustc-link-lib=xyz")
}
// clib.c
int c_func_in_c() {
    return 42;
}
# Cargo.toml
[package]
name = "x"
version = "0.1.0"
edition = "2024"
x
├── build.rs
├── build.sh
├── Cargo.toml
├── clib.c
└── src
    └── main.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions