[codeview] Fix 32-bit x86 variable locations in realigned stack frames
Add the .cv_fpo_stackalign directive so that we can define $T0, or the
VFRAME virtual register, with it. This was overlooked in the initial
implementation because unlike MSVC, we push CSRs before allocating stack
space, so this value is only needed to describe local variable
locations. Variables that the compiler now addresses via ESP are instead
described as being stored at offsets from VFRAME, which for us is ESP
after alignment in the prologue.
This adds tests that show that we use the VFRAME register properly in
our S_DEFRANGE records, and that we emit the correct FPO data to define
it.
Fixes PR38857
llvm-svn: 343603
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index aaa1dc9..707ee41 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -1255,6 +1255,7 @@
// instruction (AArch64), this will be zero.
CurFn->CSRSize = MFI.getCVBytesOfCalleeSavedRegisters();
CurFn->FrameSize = MFI.getStackSize();
+ CurFn->HasStackRealignment = TRI->needsStackRealignment(*MF);
// For this function S_FRAMEPROC record, figure out which codeview register
// will be the frame pointer.
@@ -1267,7 +1268,7 @@
} else {
// If there is an FP, parameters are always relative to it.
CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
- if (TRI->needsStackRealignment(*MF)) {
+ if (CurFn->HasStackRealignment) {
// If the stack needs realignment, locals are relative to SP or VFRAME.
CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
} else {
@@ -2502,13 +2503,18 @@
int Offset = DefRange.DataOffset;
unsigned Reg = DefRange.CVRegister;
- // x86 call sequences often use PUSH instructions, which disrupt
+ // 32-bit x86 call sequences often use PUSH instructions, which disrupt
// ESP-relative offsets. Use the virtual frame pointer, VFRAME or $T0,
- // instead. In simple cases, $T0 will be the CFA. If the frame required
- // re-alignment, it will be the CFA aligned downwards.
+ // instead. In simple cases, $T0 will be the CFA.
if (RegisterId(Reg) == RegisterId::ESP) {
Reg = unsigned(RegisterId::VFRAME);
Offset -= FI.FrameSize;
+
+ // If the frame requires realignment, VFRAME will be ESP after it is
+ // aligned. We have to remove the ESP adjustments made to push CSRs and
+ // EBP. EBP is not included in CSRSize.
+ if (FI.HasStackRealignment)
+ Offset += FI.CSRSize + 4;
}
// If we can use the chosen frame pointer for the frame and this isn't a