Skip to content

extern "C" functions don't generate the same IR definitions as clang on x86, causing problems with cross-language LTO #102174

Open
@glandium

Description

@glandium

After llvm/llvm-project@6c8adc5, inlining in cross-language LTO happens in cases where it didn't happen before, including cases where things go very bad (more details in https://bugzilla.mozilla.org/show_bug.cgi?id=1789779#c7)

It seems to boil down to LLVM not liking that rust defines its extern "C" functions in significantly different ways than clang does for the C/C++ code that calls it. For example:

// rustc --emit=llvm-ir foo.rs --crate-type=lib --target=i686-unknown-linux-gnu
#[repr(C)]
pub struct Foo(pub u32);

#[no_mangle]
pub unsafe extern "C" fn foo(foo: Foo) -> u32 {
    foo.0
}

The caller:

// clang -o - -S foo.c -emit-llvm --target=i686-unknown-linux-gnu
struct Foo { int a; };

extern int foo(struct Foo f);

int var(struct Foo f) {
    return foo(f);
}

Rust defines the function as:

Foo = type { i32 }

; Function Attrs: nonlazybind uwtable
define i32 @foo(%Foo* byval(%Foo) %foo) unnamed_addr #0 {

while the caller C code does this:

%struct.Foo = type { i32 }
(...)
declare i32 @foo(i32) #1

The equivalent C code:

// clang -o - -S foo.c -emit-llvm --target=i686-unknown-linux-gnu
struct Foo { int a; };

int foo(Foo foo) {
    return foo.a;
}

defines the function as:

%struct.Foo = type { i32 }

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @foo(i32 %0) #0 {

(Ironically, rustc transforms a non-extern "C" version of the function to the same declaration as clang's)

Arguably, there's an underlying LLVM bug not being able to handle this case, which /could/ be considered fine, but I'm not sure it's supposed to be.

It's worth noting that rustc does not use a byval for e.g. x86_64-unknown-linux-gnu.

Cc: @nikic

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)A-FFIArea: Foreign function interface (FFI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-x86_32Target: x86 processors, 32 bit (like i686-*) (IA-32)P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.WG-llvmWorking group: LLVM backend code generationregression-untriagedUntriaged performance or correctness regression.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions