Skip to content

Rust LLVMIR causes errors after LTO on x86-32 #143818

Open
@jrmuizel

Description

@jrmuizel
#[repr(C)]
pub struct UrlpPattern(pub *mut c_void);

#[unsafe(no_mangle)]
pub unsafe extern "C" fn square(num: UrlpPattern) -> *mut c_void {
    num.0
}

generates

define noundef ptr @square(ptr noalias nocapture noundef readonly byval([4 x i8]) align 4 dereferenceable(4) %num) unnamed_addr {
start:
  %_0 = load ptr, ptr %num, align 4
  ret ptr %_0
}

but

struct wrapper {
    void *p;
};


void *square(wrapper p) {
    return p.p;
}

generates

define dso_local i8* @square(wrapper)(i8* readnone returned %p.0) local_unnamed_addr {
entry:
  ret i8* %p.0
}

It seems like this mostly works because it compiles to the same thing x86-32 code:

square(wrapper):                      # @square(wrapper)
        mov     eax, dword ptr [esp + 4]
        ret

However, if the rust code is inlined into C++ with LTO we end up with an extra dereference.

We ran into this in Firefox here: https://bugzilla.mozilla.org/show_bug.cgi?id=1973805

rustc --version --verbose:

rustc 1.88.0 (6b00bc388 2025-06-23)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-LTOArea: Link-time optimization (LTO)C-bugCategory: This is a bug.O-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions