rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.38k stars 12.59k forks source link

inline assembly accepts invalid assembly, changing it #98094

Open TDecking opened 2 years ago

TDecking commented 2 years ago

The following code

pub unsafe fn lea_sub(x: usize) -> usize {
    use std::arch::asm;

    let y: usize;

    asm!(
        "xor rax, rax",
        "lea rax, [rax - 8 * rdx]",
        in("rdx") x,
        out("rax") y,
    );

    y
}

creates the following assembly

example::lea_sub:
        push    rax
        mov     rdx, rdi

        xor     rax, rax
        lea     rax, [rax + 8*rdx]

        mov     qword ptr [rsp], rax
        mov     rax, qword ptr [rsp]
        pop     rcx
        ret

__rustc_debug_gdb_scripts_section__:
        .asciz  "\001gdb_load_rust_pretty_printers.py"

Note that [rax - 8 * rdx] turned into [rax + 8*rdx]. The former version is illegal, since registers can only be added, not subtracted when calculating an address. Given that gcc rejects a similar attempt with its inline assembly, as well as the general confusion anyone uninitiated to the specifics of lea might get, I highly doubt that this behaviour is intentional.

Meta

Godbolt printed the same assembly for rustc versions 1.59, 1.60, 1.61, beta and nightly.

eggyal commented 2 years ago

@rustbot label +A-inline-assembly +T-compiler

asquared31415 commented 1 year ago

This appears to be an LLVM bug, the inline asm makes it all the way to LLVM correctly, and manually passing this inline asm to LLVM emits this invalid asm. Not sure what the process for this is.

workingjubilee commented 3 months ago

Reported upstream at https://github.com/llvm/llvm-project/issues/96427