[llvm-commits] Issue with Win64 local area stack offset

Jan Sjodin jan_sjodin at yahoo.com
Mon Jun 21 15:37:29 PDT 2010


I was looking into the Win64 code and the local area offset. I was getting
confused because the LocalAreaOffset (LAO). This is how I understand 
it right now:

The LAO is set to 40 (28h) for Win64. The intent was probably to allocate
the shadow area. The problem is that the shadow area is part of the arguments
and allocated before the return address is pushed on the stack (by the call). 
The LAO basically indicates that 32-bytes are allocated between the return
address and the frame pointer. However, whenhen the prologue is emitted the
size of the stack is adjusted, but the 32 bytes are really allocated after
the frame pointer and not before. 

Below is a small example to show what happens. 
Imagine we want to alloca a 64 byte object that is 64 byte aligned. 
The calculated offset for the object is 128, and the offset from the FP is:
80h - (LAO + 8) = 50h. This is where the problem happens. The stack is 
calculated to be 70h bytes. Because the FP and local are are not in the right
order there is an overlap of the "spill area" and the 64-byte object. The 
object is not aligned properly (32-byte instead of 64-byte), which is also 
a problem. 

              Address
                      ------------------
SP before call 0xC0:  | return address |
                      ------------------
SP after call  0xB8:  |     old FP     |
                      ------------------
New FP         0xB0:  |                |
                      |   32-bytes     |
                      |XXXXXXXXXXXXXXXX| <- 16 byte overlap between Object 
                      ------------------    and "spill area"
                      |                |
                      |                |
                      |  Allocated     |
                      |  Object        |
                      |  64 bytes      |
                      |                |
                      |                |
               0x60:  |                |
                      ------------------
                      |                |
                      |                |
SP after alloc 0x40:  |                |
                      ------------------

I hope this is clear because it is easy to get confused and it would be
nice if someone can confirm this issue. Below is a simple patch that fixes the 
problem by not allocating the spill area and sets the LAO to 8. The shadow
area is already handled by the function call lowering code.

Index: lib/Target/X86/X86RegisterInfo.cpp
===================================================================
--- lib/Target/X86/X86RegisterInfo.cpp  (revision 106454)
+++ lib/Target/X86/X86RegisterInfo.cpp  (working copy)
@@ -914,9 +914,6 @@
     StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
     MFI->setStackSize(StackSize);
   } else if (Subtarget->isTargetWin64()) {
-    // We need to always allocate 32 bytes as register spill area.
-    // FIXME: We might reuse these 32 bytes for leaf functions.
-    StackSize += 32;
     MFI->setStackSize(StackSize);
   }
 
Index: lib/Target/X86/X86TargetMachine.cpp
===================================================================
--- lib/Target/X86/X86TargetMachine.cpp (revision 106454)
+++ lib/Target/X86/X86TargetMachine.cpp (working copy)
@@ -100,7 +100,7 @@
     DataLayout(Subtarget.getDataLayout()),
     FrameInfo(TargetFrameInfo::StackGrowsDown,
               Subtarget.getStackAlignment(),
-              (Subtarget.isTargetWin64() ? -40 :
+              (Subtarget.isTargetWin64() ? -8 :
                (Subtarget.is64Bit() ? -8 : -4))),
     InstrInfo(*this), JITInfo(*this), TLInfo(*this), TSInfo(*this),
     ELFWriterInfo(*this) {



More information about the llvm-commits mailing list