mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Properly emit stack probe on win64 (for non-mingw targets).
Based on the patch by Cameron Esfahani! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115479 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d32d85e5ba
commit
6af61ca789
@ -171,13 +171,13 @@ let isCall = 1, isCodeGenOnly = 1 in
|
|||||||
Uses = [RSP] in {
|
Uses = [RSP] in {
|
||||||
def WINCALL64pcrel32 : Ii32PCRel<0xE8, RawFrm,
|
def WINCALL64pcrel32 : Ii32PCRel<0xE8, RawFrm,
|
||||||
(outs), (ins i64i32imm_pcrel:$dst, variable_ops),
|
(outs), (ins i64i32imm_pcrel:$dst, variable_ops),
|
||||||
"call\t$dst", []>,
|
"call{q}\t$dst", []>,
|
||||||
Requires<[IsWin64]>;
|
Requires<[IsWin64]>;
|
||||||
def WINCALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops),
|
def WINCALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst, variable_ops),
|
||||||
"call\t{*}$dst",
|
"call{q}\t{*}$dst",
|
||||||
[(X86call GR64:$dst)]>, Requires<[IsWin64]>;
|
[(X86call GR64:$dst)]>, Requires<[IsWin64]>;
|
||||||
def WINCALL64m : I<0xFF, MRM2m, (outs),
|
def WINCALL64m : I<0xFF, MRM2m, (outs), (ins i64mem:$dst,variable_ops),
|
||||||
(ins i64mem:$dst, variable_ops), "call\t{*}$dst",
|
"call{q}\t{*}$dst",
|
||||||
[(X86call (loadi64 addr:$dst))]>,
|
[(X86call (loadi64 addr:$dst))]>,
|
||||||
Requires<[IsWin64]>;
|
Requires<[IsWin64]>;
|
||||||
}
|
}
|
||||||
|
@ -871,6 +871,19 @@ void X86RegisterInfo::emitCalleeSavedFrameMoves(MachineFunction &MF,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isEAXLiveIn(MachineFunction &MF) {
|
||||||
|
for (MachineRegisterInfo::livein_iterator II = MF.getRegInfo().livein_begin(),
|
||||||
|
EE = MF.getRegInfo().livein_end(); II != EE; ++II) {
|
||||||
|
unsigned Reg = II->first;
|
||||||
|
|
||||||
|
if (Reg == X86::EAX || Reg == X86::AX ||
|
||||||
|
Reg == X86::AH || Reg == X86::AL)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// emitPrologue - Push callee-saved registers onto the stack, which
|
/// emitPrologue - Push callee-saved registers onto the stack, which
|
||||||
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
|
/// automatically adjust the stack pointer. Adjust the stack pointer to allocate
|
||||||
/// space for local variables. Also emit labels used by the exception handler to
|
/// space for local variables. Also emit labels used by the exception handler to
|
||||||
@ -915,12 +928,12 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
!needsStackRealignment(MF) &&
|
!needsStackRealignment(MF) &&
|
||||||
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
||||||
!MFI->adjustsStack() && // No calls.
|
!MFI->adjustsStack() && // No calls.
|
||||||
!Subtarget->isTargetWin64()) { // Win64 has no Red Zone
|
!IsWin64) { // Win64 has no Red Zone
|
||||||
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
|
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
|
||||||
if (HasFP) MinSize += SlotSize;
|
if (HasFP) MinSize += SlotSize;
|
||||||
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
|
StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
|
||||||
MFI->setStackSize(StackSize);
|
MFI->setStackSize(StackSize);
|
||||||
} else if (Subtarget->isTargetWin64()) {
|
} else if (IsWin64) {
|
||||||
// We need to always allocate 32 bytes as register spill area.
|
// We need to always allocate 32 bytes as register spill area.
|
||||||
// FIXME: We might reuse these 32 bytes for leaf functions.
|
// FIXME: We might reuse these 32 bytes for leaf functions.
|
||||||
StackSize += 32;
|
StackSize += 32;
|
||||||
@ -1061,28 +1074,29 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
DL = MBB.findDebugLoc(MBBI);
|
DL = MBB.findDebugLoc(MBBI);
|
||||||
|
|
||||||
|
// If there is an SUB32ri of ESP immediately before this instruction, merge
|
||||||
|
// the two. This can be the case when tail call elimination is enabled and
|
||||||
|
// the callee has more arguments then the caller.
|
||||||
|
NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||||
|
|
||||||
|
// If there is an ADD32ri or SUB32ri of ESP immediately after this
|
||||||
|
// instruction, merge the two instructions.
|
||||||
|
mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes);
|
||||||
|
|
||||||
// Adjust stack pointer: ESP -= numbytes.
|
// Adjust stack pointer: ESP -= numbytes.
|
||||||
|
|
||||||
// Windows and cygwin/mingw require a prologue helper routine when allocating
|
// Windows and cygwin/mingw require a prologue helper routine when allocating
|
||||||
// more than 4K bytes on the stack. Windows uses __chkstk and cygwin/mingw
|
// more than 4K bytes on the stack. Windows uses __chkstk and cygwin/mingw
|
||||||
// uses __alloca. __alloca and the 32-bit version of __chkstk will probe
|
// uses __alloca. __alloca and the 32-bit version of __chkstk will probe the
|
||||||
// the stack and adjust the stack pointer in one go. The 64-bit version
|
// stack and adjust the stack pointer in one go. The 64-bit version of
|
||||||
// of __chkstk is only responsible for probing the stack. The 64-bit
|
// __chkstk is only responsible for probing the stack. The 64-bit prologue is
|
||||||
// prologue is responsible for adjusting the stack pointer. Touching the
|
// responsible for adjusting the stack pointer. Touching the stack at 4K
|
||||||
// stack at 4K increments is necessary to ensure that the guard pages used
|
// increments is necessary to ensure that the guard pages used by the OS
|
||||||
// by the OS virtual memory manager are allocated in correct sequence.
|
// virtual memory manager are allocated in correct sequence.
|
||||||
if (NumBytes >= 4096 &&
|
if (NumBytes >= 4096 &&
|
||||||
(Subtarget->isTargetCygMing() || Subtarget->isTargetWin32())) {
|
(Subtarget->isTargetCygMing() || Subtarget->isTargetWin32())) {
|
||||||
// Check, whether EAX is livein for this function.
|
// Check whether EAX is livein for this function.
|
||||||
bool isEAXAlive = false;
|
bool isEAXAlive = isEAXLiveIn(MF);
|
||||||
for (MachineRegisterInfo::livein_iterator
|
|
||||||
II = MF.getRegInfo().livein_begin(),
|
|
||||||
EE = MF.getRegInfo().livein_end(); (II != EE) && !isEAXAlive; ++II) {
|
|
||||||
unsigned Reg = II->first;
|
|
||||||
isEAXAlive = (Reg == X86::EAX || Reg == X86::AX ||
|
|
||||||
Reg == X86::AH || Reg == X86::AL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *StackProbeSymbol =
|
const char *StackProbeSymbol =
|
||||||
Subtarget->isTargetWindows() ? "_chkstk" : "_alloca";
|
Subtarget->isTargetWindows() ? "_chkstk" : "_alloca";
|
||||||
@ -1114,19 +1128,21 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
StackPtr, false, NumBytes - 4);
|
StackPtr, false, NumBytes - 4);
|
||||||
MBB.insert(MBBI, MI);
|
MBB.insert(MBBI, MI);
|
||||||
}
|
}
|
||||||
} else if (NumBytes) {
|
} else if (NumBytes >= 4096 && Subtarget->isTargetWin64()) {
|
||||||
// If there is an SUB32ri of ESP immediately before this instruction, merge
|
// Sanity check that EAX is not livein for this function. It should
|
||||||
// the two. This can be the case when tail call elimination is enabled and
|
// should not be, so throw an assert.
|
||||||
// the callee has more arguments then the caller.
|
assert(!isEAXLiveIn(MF) && "EAX is livein in the Win64 case!");
|
||||||
NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
|
||||||
|
|
||||||
// If there is an ADD32ri or SUB32ri of ESP immediately after this
|
// Handle the 64-bit Windows ABI case where we need to call __chkstk.
|
||||||
// instruction, merge the two instructions.
|
// Function prologue is responsible for adjusting the stack pointer.
|
||||||
mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes);
|
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
||||||
|
.addImm(NumBytes);
|
||||||
if (NumBytes)
|
BuildMI(MBB, MBBI, DL, TII.get(X86::WINCALL64pcrel32))
|
||||||
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
.addExternalSymbol("__chkstk")
|
||||||
}
|
.addReg(StackPtr, RegState::Define | RegState::Implicit);
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
||||||
|
} else if (NumBytes)
|
||||||
|
emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII);
|
||||||
|
|
||||||
if ((NumBytes || PushedRegs) && needsFrameMoves) {
|
if ((NumBytes || PushedRegs) && needsFrameMoves) {
|
||||||
// Mark end of stack pointer adjustment.
|
// Mark end of stack pointer adjustment.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN_X32
|
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN_X32
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s -check-prefix=WIN_X64
|
||||||
; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X32
|
; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X32
|
||||||
; RUN: llc < %s -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X64
|
; RUN: llc < %s -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X64
|
||||||
; RUN: llc < %s -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
|
; RUN: llc < %s -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
|
||||||
@ -13,7 +14,7 @@
|
|||||||
define i32 @main4k() nounwind {
|
define i32 @main4k() nounwind {
|
||||||
entry:
|
entry:
|
||||||
; WIN_X32: calll __chkstk
|
; WIN_X32: calll __chkstk
|
||||||
; WIN_X64: call __chkstk
|
; WIN_X64: callq __chkstk
|
||||||
; MINGW_X32: calll __alloca
|
; MINGW_X32: calll __alloca
|
||||||
; MINGW_X64: callq _alloca
|
; MINGW_X64: callq _alloca
|
||||||
; LINUX-NOT: call __chkstk
|
; LINUX-NOT: call __chkstk
|
||||||
@ -30,7 +31,7 @@ entry:
|
|||||||
; WIN_X32: ret
|
; WIN_X32: ret
|
||||||
|
|
||||||
; WIN_X64: # BB#0:
|
; WIN_X64: # BB#0:
|
||||||
; WIN_X64-NOT: call __chkstk
|
; WIN_X64-NOT: callq __chkstk
|
||||||
; WIN_X64: ret
|
; WIN_X64: ret
|
||||||
|
|
||||||
; MINGW_X64: # BB#0:
|
; MINGW_X64: # BB#0:
|
||||||
|
Loading…
Reference in New Issue
Block a user