Clobber_abi clobbers non-volatile (callee-saved) registers

I have the following Rust code snippet:

extern "win64" {
    fn foo();
}

pub fn bar() {
    unsafe {
        std::arch::asm!(
            "call foo",
            clobber_abi("win64"),
        );
    }
}

When compiled for x86-64 Windows, rustc emits the following code:

example::bar:
        sub     rsp, 168
        movaps  xmmword ptr [rsp + 144], xmm15
        movaps  xmmword ptr [rsp + 128], xmm14
        movaps  xmmword ptr [rsp + 112], xmm13
        movaps  xmmword ptr [rsp + 96], xmm12
        movaps  xmmword ptr [rsp + 80], xmm11
        movaps  xmmword ptr [rsp + 64], xmm10
        movaps  xmmword ptr [rsp + 48], xmm9
        movaps  xmmword ptr [rsp + 32], xmm8
        movaps  xmmword ptr [rsp + 16], xmm7
        movaps  xmmword ptr [rsp], xmm6

        call    foo

        movaps  xmm6, xmmword ptr [rsp]
        movaps  xmm7, xmmword ptr [rsp + 16]
        movaps  xmm8, xmmword ptr [rsp + 32]
        movaps  xmm9, xmmword ptr [rsp + 48]
        movaps  xmm10, xmmword ptr [rsp + 64]
        movaps  xmm11, xmmword ptr [rsp + 80]
        movaps  xmm12, xmmword ptr [rsp + 96]
        movaps  xmm13, xmmword ptr [rsp + 112]
        movaps  xmm14, xmmword ptr [rsp + 128]
        movaps  xmm15, xmmword ptr [rsp + 144]
        add     rsp, 168
        ret

Seems like that clobber_abi("win64") clobbers registers from XMM6 - XMM15. AFAIK, clobber_abi is used when the inline assembly code calls some external function and thus all volatile (caller-saved) registers according to the external function's ABI are clobbered. However, XMM6 - XMM15 is marked as non-volatile (callee-saved) registers according to the x64 Windows ABI. What's wrong here?

The reason for this is explained in compiler/rustc_target/src/asm/mod.rs:

// xmm6-xmm15 are callee-saved on windows, but we need to
// mark them as clobbered anyways because the upper portions
// of ymm6-ymm15 are volatile.
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.