Index: lib/Target/X86/X86ExpandPseudo.cpp =================================================================== --- lib/Target/X86/X86ExpandPseudo.cpp +++ lib/Target/X86/X86ExpandPseudo.cpp @@ -58,8 +58,9 @@ } private: - bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); - bool ExpandMBB(MachineBasicBlock &MBB); + bool ExpandMI(X86MachineFunctionInfo *X86FI, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI); + bool ExpandMBB(X86MachineFunctionInfo *X86FI, MachineBasicBlock &MBB); }; char X86ExpandPseudo::ID = 0; } // End anonymous namespace. @@ -67,7 +68,8 @@ /// If \p MBBI is a pseudo instruction, this method expands /// it to the corresponding (sequence of) actual instruction(s). /// \returns true if \p MBBI has been expanded. -bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, +bool X86ExpandPseudo::ExpandMI(X86MachineFunctionInfo *X86FI, + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); @@ -88,11 +90,18 @@ // Adjust stack pointer. int StackAdj = StackAdjust.getImm(); + int MaxTCDelta = X86FI->getTCReturnAddrDelta(); + int Offset = 0; + assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive"); - if (StackAdj) { + // Incoporate the retaddr area. + Offset = StackAdj-MaxTCDelta; + assert(Offset >= 0 && "Offset should never be negative"); + + if (Offset) { // Check for possible merge with preceding ADD instruction. - StackAdj += X86FL->mergeSPUpdates(MBB, MBBI, true); - X86FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true); + Offset += X86FL->mergeSPUpdates(MBB, MBBI, true); + X86FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); } // Jump to label or value in register. @@ -229,14 +238,15 @@ /// Expand all pseudo instructions contained in \p MBB. /// \returns true if any expansion occurred for \p MBB. -bool X86ExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { +bool X86ExpandPseudo::ExpandMBB(X86MachineFunctionInfo *X86FI, + MachineBasicBlock &MBB) { bool Modified = false; // MBBI may be invalidated by the expansion. MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { MachineBasicBlock::iterator NMBBI = std::next(MBBI); - Modified |= ExpandMI(MBB, MBBI); + Modified |= ExpandMI(X86FI, MBB, MBBI); MBBI = NMBBI; } @@ -244,6 +254,7 @@ } bool X86ExpandPseudo::runOnMachineFunction(MachineFunction &MF) { + X86MachineFunctionInfo *X86FI = MF.getInfo(); STI = &static_cast(MF.getSubtarget()); TII = STI->getInstrInfo(); TRI = STI->getRegisterInfo(); @@ -251,7 +262,7 @@ bool Modified = false; for (MachineBasicBlock &MBB : MF) - Modified |= ExpandMBB(MBB); + Modified |= ExpandMBB(X86FI, MBB); return Modified; } Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -1473,6 +1473,7 @@ const MachineFrameInfo *MFI = MF.getFrameInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo(); MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); + unsigned RetOpcode = MBBI->getOpcode(); DebugLoc DL; if (MBBI != MBB.end()) DL = MBBI->getDebugLoc(); @@ -1621,15 +1622,20 @@ if (NeedsWinCFI) BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue)); - // Add the return addr area delta back since we are not tail calling. - int Offset = -1 * X86FI->getTCReturnAddrDelta(); - assert(Offset >= 0 && "TCDelta should never be positive"); - if (Offset) { - MBBI = MBB.getFirstTerminator(); - - // Check for possible merge with preceding ADD instruction. - Offset += mergeSPUpdates(MBB, MBBI, true); - emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); + if (RetOpcode != X86::TCRETURNri && RetOpcode != X86::TCRETURNdi && + RetOpcode != X86::TCRETURNmi && + RetOpcode != X86::TCRETURNri64 && RetOpcode != X86::TCRETURNdi64 && + RetOpcode != X86::TCRETURNmi64) { + // Add the return addr area delta back since we are not tail calling. + int Offset = -1 * X86FI->getTCReturnAddrDelta(); + assert(Offset >= 0 && "TCDelta should never be positive"); + if (Offset) { + MBBI = MBB.getFirstTerminator(); + + // Check for possible merge with preceding ADD instruction. + Offset += mergeSPUpdates(MBB, MBBI, true); + emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); + } } } Index: test/CodeGen/X86/hipe-cc.ll =================================================================== --- test/CodeGen/X86/hipe-cc.ll +++ test/CodeGen/X86/hipe-cc.ll @@ -73,5 +73,19 @@ ret void } +; Sanity-check the tail call sequence. Number of arguments was chosen as to +; expose a bug where the tail call sequence clobbered the stack. +define cc 11 { i32, i32, i32 } @tailcaller(i32 %hp, i32 %p) nounwind { + ; CHECK: movl $15, %eax + ; CHECK-NEXT: movl $31, %edx + ; CHECK-NEXT: movl $47, %ecx + ; CHECK-NEXT: popl %edi + ; CHECK-NEXT: jmp tailcallee + %ret = tail call cc11 { i32, i32, i32 } @tailcallee(i32 %hp, i32 %p, i32 15, + i32 31, i32 47, i32 63) nounwind + ret { i32, i32, i32 } %ret +} + @clos = external constant i32 declare cc 11 void @bar(i32, i32, i32, i32, i32) +declare cc 11 { i32, i32, i32 } @tailcallee(i32, i32, i32, i32, i32, i32) Index: test/CodeGen/X86/hipe-cc64.ll =================================================================== --- test/CodeGen/X86/hipe-cc64.ll +++ test/CodeGen/X86/hipe-cc64.ll @@ -83,5 +83,20 @@ ret void } +; Sanity-check the tail call sequence. Number of arguments was chosen as to +; expose a bug where the tail call sequence clobbered the stack. +define cc 11 { i64, i64, i64 } @tailcaller(i64 %hp, i64 %p) #0 { + ; CHECK: movl $15, %esi + ; CHECK-NEXT: movl $31, %edx + ; CHECK-NEXT: movl $47, %ecx + ; CHECK-NEXT: movl $63, %r8d + ; CHECK-NEXT: popq %rax + ; CHECK-NEXT: jmp tailcallee + %ret = tail call cc11 { i64, i64, i64 } @tailcallee(i64 %hp, i64 %p, i64 15, + i64 31, i64 47, i64 63, i64 79) #1 + ret { i64, i64, i64 } %ret +} + @clos = external constant i64 declare cc 11 void @bar(i64, i64, i64, i64, i64, i64) +declare cc 11 { i64, i64, i64 } @tailcallee(i64, i64, i64, i64, i64, i64, i64)