I want to know how MSVC 2010 generates code for volatile local variable and have done a test. This simple test function uses a volatile local variable:

int proc1(int a, int b) {
    int volatile volvar=0;

    int c=a;
    if (b>a) 
    return c;

The initialization of the integer volvar should not be eliminated by the optimizer due to the volatile keyword. The generated 64bit assembly is like this:

volvar$ = 8
a$ = 8
b$ = 16
?proc1@@YAHHH@Z PROC                    ; proc1, COMDAT

; 3    : int volatile volvar=0;

    xor eax, eax

; 4    : 
; 5    :    int c=a;
; 6    :    if (b>a) 

    cmp edx, ecx
    cmovg   ecx, eax
    mov DWORD PTR volvar$[rsp], eax;<---what is 'mov DWORD PTR [8+rsp], eax'?

; 7    :        c=0;
; 8    :    return c;

    mov eax, ecx

; 9    : }

    ret 0
?proc1@@YAHHH@Z ENDP                    ; proc1

Notice the symbol volvar$ equals to 8, so the instruction generated for the volatile local variable assignment write to the address [8+rsp]. RSP wasn't modified so should point to the return address. But my understanding of the 64bit stack layout is that there is no longer any parameters above the return address. Instead, [8+rsp] should point to the RCX storage location for the CALLING FUNCTION which has nothing to do with our current function. Does that overwrite the stack of the calling function incorrectly?

Is it a bug with the compiler?


No, it's not a compiler bug.

The x64 calling convention on Windows says that the caller needs to allocate space on the stack for 4 register parameters even if the called function has less than 4 arguments. Whilst, notionally, these are for the called function to spill the 1st four parameters (passed in registers RCX, RDX, R8 and R9) to, there is no requirement for it do so.

In fact, even if the called function has fewer than 4 parameters, these 4 stack locations are effectively owned by the called function, and may be used by the called function for other purposes besides saving parameter register values.

See Microsoft's documentation for details.

In your example, proc1 doesn't need to spill any registers so the compiler can efficiently use this allocated space for your volvar local variable instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.