0

I want to know how MSVC 2010 generates code for volatile local variables 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) 
        c=0;
    return c;
}

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

_TEXT   SEGMENT
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
_TEXT   ENDS
END

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 or my misunderstanding of the 64 bit stack frame layout?

JavaMan
  • 4,954
  • 4
  • 41
  • 69
  • At least it I sense a misunderstanding of the meaning of `volatile`. The language defines that a variable assumes its `volatile` properties only after its initialization has completed. Since the variable in your example is not accessed after the initialization, all assumptions about not being allowed to optimized away do not apply. My conclusion is that the compiler is allowed to optimize away this variable. – j6t Feb 18 '17 at 16:26
  • It is a leaf-function (no calls into other functions), so the optimizer can cut a lot of corners. So no need to setup a stack frame, and exception handling is table-based in x64, allowing the +8 offset. It can easily detect that volvar isn't used anywhere and can have no side-effects, so it eliminated it completely. Some confusion in the codegen since c now occupies the storage location formerly reserved for volvar. This code would normally be inlined, eliminating more code, but you looked at the non-inlined version. – Hans Passant Feb 18 '17 at 16:52
  • fyi, 32bit code generated by msvc handles the same volatile local variable correctly. It either explicitly creates a local variable in the stack as the volatile variable or reuse a function parameters in the stack (since in 32bit parameters are passed in the stack) as the volatile variable. – JavaMan Feb 18 '17 at 17:01

0 Answers0