Windows x64 calling convention

⚓ Rust    📅 2026-04-29    👤 surdeus    👁️ 4      

surdeus

From the docs about Windows x64 calling convention:

The stack pointer must remain 16-byte aligned in any region of code that isn't part of an epilog or prolog, except within leaf functions.

So I tested with this code in godbolt:

#[unsafe(no_mangle)]
pub unsafe extern "win64" fn test() -> i64 {
    unsafe { test2() }
}

#[unsafe(no_mangle)]
pub unsafe extern "win64" fn test2() -> i64 {
    unsafe { test3(1, 2, 3, 4, 5) }
}

#[unsafe(no_mangle)]
pub unsafe extern "win64" fn test3(a: i64, b: i64, c: i64, d: i64, e: i64) -> i64 {
    a + b + c + d + e
}

The compiler generated:

test2:
        sub     rsp, 40
        mov     ecx, 1
        mov     edx, 2
        mov     r8d, 3
        mov     r9d, 4
        mov     qword ptr [rsp + 32], 5
        call    test3
        nop
        add     rsp, 40
        ret

Why is sub rsp, 40 used here? Since 40 is not divisible by 16, doesn't that mean there is a time when the stack pointer does not align by 16 bytes?

3 posts - 2 participants

Read full topic

🏷️ Rust_feed