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?