41#define DEBUG_TYPE "x86-fl"
43STATISTIC(NumFrameLoopProbe,
"Number of loop stack probes used in prologue");
45 "Number of extra stack probes generated in prologue");
46STATISTIC(NumFunctionUsingPush2Pop2,
"Number of functions using push2/pop2");
71 return STI.hasBWI() ? &X86::VK64RegClass : &X86::VK16RegClass;
72 return TRI.getMinimalPhysRegClass(
Reg);
104 (
hasFP(MF) && !
TRI->hasStackRealignment(MF)) ||
105 TRI->hasBasePointer(MF);
137 return IsLP64 ? X86::SUB64ri32 : X86::SUB32ri;
141 return IsLP64 ? X86::ADD64ri32 : X86::ADD32ri;
145 return IsLP64 ? X86::SUB64rr : X86::SUB32rr;
149 return IsLP64 ? X86::ADD64rr : X86::ADD32rr;
153 return IsLP64 ? X86::AND64ri32 : X86::AND32ri;
157 return IsLP64 ? X86::LEA64r : X86::LEA32r;
178 return ST.is64Bit() ? (ST.hasPPX() ? X86::PUSHP64r : X86::PUSH64r)
182 return ST.is64Bit() ? (ST.hasPPX() ? X86::POPP64r : X86::POP64r)
186 return ST.hasPPX() ? X86::PUSH2P : X86::PUSH2;
189 return ST.hasPPX() ? X86::POP2P : X86::POP2;
196 if (
Reg == X86::RAX ||
Reg == X86::EAX ||
Reg == X86::AX ||
197 Reg == X86::AH ||
Reg == X86::AL)
211 bool BreakNext =
false;
216 if (
Reg != X86::EFLAGS)
237 if (Succ->isLiveIn(X86::EFLAGS))
250 bool InEpilogue)
const {
251 bool isSub = NumBytes < 0;
252 uint64_t
Offset = isSub ? -NumBytes : NumBytes;
267 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
271 if (EmitInlineStackProbe && !InEpilogue) {
299 MI->getOperand(3).setIsDead();
326 MI->getOperand(3).setIsDead();
345 unsigned Opc = isSub ? (
Is64Bit ? X86::PUSH64r : X86::PUSH32r)
346 : (
Is64Bit ? X86::POP64r : X86::POP32r);
356 BuildStackAdjustment(
MBB,
MBBI,
DL, isSub ? -ThisVal : ThisVal, InEpilogue)
366 assert(
Offset != 0 &&
"zero offset stack adjustment requested");
376 UseLEA =
STI.useLeaForSP() ||
MBB.isLiveIn(X86::EFLAGS);
384 if (UseLEA && !
STI.useLeaForSP())
389 "We shouldn't have allowed this insertion point");
392 MachineInstrBuilder
MI;
406 const unsigned Opc = IsSub ? X86::SUB64ri32_NF : X86::ADD64ri32_NF;
419 int64_t
Imm = AbsOffset;
430 if (AbsOffset == 128 &&
432 Opc = IsSub ? getADDriOpcode(Uses64BitFramePtr)
433 : getSUBriOpcode(Uses64BitFramePtr);
444template <
typename FoundT,
typename CalcT>
447 FoundT FoundStackAdjust,
449 bool doMergeWithPrevious)
const {
452 return CalcNewOffset(0);
468 if (doMergeWithPrevious && PI !=
MBB.
begin() && PI->isCFIInstruction())
473 unsigned Opc = PI->getOpcode();
475 if ((
Opc == X86::ADD64ri32 ||
Opc == X86::ADD32ri ||
476 Opc == X86::ADD64ri32_NF) &&
477 PI->getOperand(0).getReg() ==
StackPtr) {
479 Offset = PI->getOperand(2).getImm();
480 }
else if ((
Opc == X86::LEA32r ||
Opc == X86::LEA64_32r) &&
481 PI->getOperand(0).getReg() ==
StackPtr &&
482 PI->getOperand(1).getReg() ==
StackPtr &&
483 PI->getOperand(2).getImm() == 1 &&
484 PI->getOperand(3).getReg() == X86::NoRegister &&
485 PI->getOperand(5).getReg() == X86::NoRegister) {
487 Offset = PI->getOperand(4).getImm();
488 }
else if ((
Opc == X86::SUB64ri32 ||
Opc == X86::SUB32ri ||
489 Opc == X86::SUB64ri32_NF) &&
490 PI->getOperand(0).getReg() ==
StackPtr) {
492 Offset = -PI->getOperand(2).getImm();
494 return CalcNewOffset(0);
496 FoundStackAdjust(PI,
Offset);
500 if (doMergeWithPrevious ? (PI ==
MBB.
begin()) : (PI ==
MBB.
end()))
501 return CalcNewOffset(0);
503 PI = doMergeWithPrevious ? std::prev(PI) : std::next(PI);
507 if (PI !=
MBB.
end() && PI->isCFIInstruction()) {
509 MCCFIInstruction CI = CIs[PI->getOperand(0).getCFIIndex()];
514 if (!doMergeWithPrevious)
517 return CalcNewOffset(
Offset);
523 bool doMergeWithPrevious)
const {
524 return mergeSPUpdates(
526 doMergeWithPrevious);
559 unsigned DwarfReg =
MRI->getDwarfRegNum(MachineFramePtr,
true);
582 unsigned DwarfReg =
MRI->getDwarfRegNum(Reg,
true);
593 CfaExpr.
push_back(dwarf::DW_CFA_expression);
599 STI.isTarget64BitILP32()
602 unsigned DwarfFramePtr =
MRI->getDwarfRegNum(MachineFramePtr,
true);
618 int FI =
MI->getOperand(1).getIndex();
623 STI.isTarget64BitILP32()
626 unsigned DwarfFramePtr =
MRI->getDwarfRegNum(MachineFramePtr,
true);
633 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
643void X86FrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
659 if (!X86::RFP80RegClass.
contains(Reg))
664 unsigned NumFPRegs = 8;
665 if (
MBBI->hasRegisterImplicitUseOperand(X86::ST0))
667 if (
MBBI->hasRegisterImplicitUseOperand(X86::ST1))
670 for (
unsigned i = 0; i != NumFPRegs; ++i)
673 for (
unsigned i = 0; i != NumFPRegs; ++i)
681 if (
TRI->isGeneralPurposeRegister(MF,
Reg)) {
687 for (MCRegister
Reg : GPRsToZero.set_bits())
692 auto getVectorClearReg = [&](MCRegister
Reg) -> MCRegister {
701 MCRegister Xmm =
TRI->getSubReg(
Reg, X86::sub_xmm);
704 if (X86::VR128RegClass.
contains(Xmm))
707 TRI->getMatchingSuperReg(Xmm, X86::sub_xmm, &X86::VR512RegClass);
708 assert(Zmm &&
"XMM16-31 must have an enclosing ZMM to clear through");
712 BitVector VecRegsToZero(
TRI->getNumRegs());
714 if (MCRegister Clear = getVectorClearReg(
Reg)) {
715 VecRegsToZero.set(Clear.id());
719 for (MCRegister
Reg : VecRegsToZero.set_bits())
730 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
732 if (
STI.isTargetWindowsCoreCLR()) {
737 emitStackProbeInline(MF,
MBB,
MBBI,
DL,
false);
740 emitStackProbeCall(MF,
MBB,
MBBI,
DL, InProlog, InstrNum);
745 return STI.isOSWindows() && !
STI.isTargetWin64();
751 return MI.getOpcode() == X86::STACKALLOC_W_PROBING;
753 if (Where != PrologMBB.
end()) {
755 emitStackProbeInline(MF, PrologMBB, Where,
DL,
true);
756 Where->eraseFromParent();
764 bool InProlog)
const {
767 emitStackProbeInlineWindowsCoreCLR64(MF,
MBB,
MBBI,
DL, InProlog);
769 emitStackProbeInlineGeneric(MF,
MBB,
MBBI,
DL, InProlog);
772void X86FrameLowering::emitStackProbeInlineGeneric(
781 "different expansion expected for CoreCLR 64 bit");
783 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
784 uint64_t ProbeChunk = StackProbeSize * 8;
787 TRI->hasStackRealignment(MF) ? calculateMaxStackAlign(MF) : 0;
792 if (
Offset > ProbeChunk) {
794 MaxAlign % StackProbeSize);
797 MaxAlign % StackProbeSize);
801void X86FrameLowering::emitStackProbeInlineGenericBlock(
821 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
824 const X86TargetLowering &TLI = *
STI.getTargetLowering();
825 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
826 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
830 assert(AlignOffset < StackProbeSize);
833 if (StackProbeSize <
Offset + AlignOffset) {
836 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackAdjustment,
false)
838 if (!HasFP && NeedsDwarfCFI) {
849 NumFrameExtraProbe++;
850 CurrentOffset = StackProbeSize - AlignOffset;
854 while (CurrentOffset + StackProbeSize <=
Offset) {
855 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackProbeSize,
false)
858 if (!HasFP && NeedsDwarfCFI) {
868 NumFrameExtraProbe++;
869 CurrentOffset += StackProbeSize;
881 unsigned Opc =
Is64Bit ? X86::PUSH64r : X86::PUSH32r;
886 assert(!(ChunkSize > StackProbeSize) &&
887 "Tail allocation greater than page size");
888 BuildStackAdjustment(
MBB,
MBBI,
DL, -ChunkSize,
false)
895void X86FrameLowering::emitStackProbeInlineGenericLoop(
903 "Inline stack probe loop will clobber live EFLAGS.");
905 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
908 const X86TargetLowering &TLI = *
STI.getTargetLowering();
909 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
910 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
913 if (AlignOffset < StackProbeSize) {
915 BuildStackAdjustment(
MBB,
MBBI,
DL, -AlignOffset,
false)
923 NumFrameExtraProbe++;
936 MF.
insert(MBBIter, testMBB);
937 MF.
insert(MBBIter, tailMBB);
979 if (!HasFP && NeedsDwarfCFI) {
982 const Register DwarfFinalStackProbed =
983 STI.isTarget64BitILP32()
989 nullptr,
TRI->getDwarfRegNum(DwarfFinalStackProbed,
true)));
996 BuildStackAdjustment(*testMBB, testMBB->
end(),
DL, -StackProbeSize,
1010 .
addReg(FinalStackProbed)
1030 BuildStackAdjustment(*tailMBB, TailMBBIter,
DL, -TailOffset,
1036 if (!HasFP && NeedsDwarfCFI) {
1040 STI.isTarget64BitILP32()
1046 nullptr,
TRI->getDwarfRegNum(DwarfStackPtr,
true)));
1053void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
1057 assert(
STI.is64Bit() &&
"different expansion needed for 32 bit");
1058 assert(
STI.isTargetWindowsCoreCLR() &&
"custom expansion expects CoreCLR");
1059 const TargetInstrInfo &
TII = *
STI.getInstrInfo();
1064 "Inline stack probe loop will clobber live EFLAGS.");
1099 MF.
insert(MBBIter, RoundMBB);
1100 MF.
insert(MBBIter, LoopMBB);
1101 MF.
insert(MBBIter, ContinueMBB);
1109 const int64_t ThreadEnvironmentStackLimit = 0x10;
1111 const int64_t PageMask = ~(
PageSize - 1);
1129 int64_t RCXShadowSlot = 0;
1130 int64_t RDXShadowSlot = 0;
1137 X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
1146 int64_t InitSlot = 8 + CalleeSaveSize + (
HasFP ? 8 : 0);
1150 RCXShadowSlot = InitSlot;
1152 RDXShadowSlot = InitSlot;
1153 if (IsRDXLiveIn && IsRCXLiveIn)
1195 .
addImm(ThreadEnvironmentStackLimit)
1206 BuildMI(RoundMBB,
DL,
TII.get(X86::AND64ri32), RoundedReg)
1252 TII.get(X86::MOV64rm), X86::RCX),
1253 X86::RSP, RCXShadowSlot);
1256 TII.get(X86::MOV64rm), X86::RDX),
1257 X86::RSP, RDXShadowSlot);
1262 BuildMI(*ContinueMBB, ContinueMBBI,
DL,
TII.get(X86::SUB64rr), X86::RSP)
1275 LivePhysRegs LiveRegs;
1281 for (++BeforeMBBI; BeforeMBBI !=
MBB.
end(); ++BeforeMBBI) {
1284 for (MachineInstr &
MI : *RoundMBB) {
1287 for (MachineInstr &
MI : *LoopMBB) {
1290 for (MachineInstr &
MI :
1297void X86FrameLowering::emitStackProbeCall(
1300 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
1304 if (
Is64Bit && IsLargeCodeModel &&
STI.useIndirectThunkCalls())
1306 "code model and indirect thunks not yet implemented.");
1310 "Stack probe calls will clobber live EFLAGS.");
1314 CallOp = IsLargeCodeModel ? X86::CALL64r : X86::CALL64pcrel32;
1316 CallOp = X86::CALLpcrel32;
1318 StringRef
Symbol =
STI.getTargetLowering()->getStackProbeSymbolName(MF);
1320 MachineInstrBuilder CI;
1338 bool EmitSPSub =
STI.isTargetWin64() || !
STI.isOSWindows();
1348 MachineInstr *ModInst = CI;
1382 for (++ExpansionMBBI; ExpansionMBBI !=
MBBI; ++ExpansionMBBI)
1390 const uint64_t Win64MaxSEHOffset = 128;
1391 uint64_t SEHFrameOffset = std::min(SPAdjust, Win64MaxSEHOffset);
1393 return SEHFrameOffset & -16;
1401X86FrameLowering::calculateMaxStackAlign(
const MachineFunction &MF)
const {
1408 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
1414 MaxAlign = std::max(MaxAlign,
Align(16));
1416 return MaxAlign.
value();
1428 const X86TargetLowering &TLI = *
STI.getTargetLowering();
1429 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
1430 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
1435 if (
Reg ==
StackPtr && EmitInlineStackProbe && MaxAlign >= StackProbeSize) {
1437 NumFrameLoopProbe++;
1438 MachineBasicBlock *entryMBB =
1440 MachineBasicBlock *headMBB =
1442 MachineBasicBlock *bodyMBB =
1444 MachineBasicBlock *footMBB =
1448 MF.
insert(MBBIter, entryMBB);
1449 MF.
insert(MBBIter, headMBB);
1450 MF.
insert(MBBIter, bodyMBB);
1451 MF.
insert(MBBIter, footMBB);
1452 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
1461 BuildMI(entryMBB,
DL,
TII.get(TargetOpcode::COPY), FinalStackProbed)
1465 BuildMI(entryMBB,
DL,
TII.get(AndOp), FinalStackProbed)
1466 .
addReg(FinalStackProbed)
1475 .
addReg(FinalStackProbed)
1499 .
addReg(FinalStackProbed)
1530 .
addReg(FinalStackProbed)
1546 .
addReg(FinalStackProbed)
1573 "MF used frame lowering for wrong subtarget");
1579bool X86FrameLowering::needsDwarfCFI(
const MachineFunction &MF)
const {
1586 case X86::REPNE_PREFIX:
1587 case X86::REP_MOVSB_32:
1588 case X86::REP_MOVSB_64:
1589 case X86::REP_MOVSD_32:
1590 case X86::REP_MOVSD_64:
1591 case X86::REP_MOVSQ_32:
1592 case X86::REP_MOVSQ_64:
1593 case X86::REP_MOVSW_32:
1594 case X86::REP_MOVSW_64:
1595 case X86::REP_PREFIX:
1596 case X86::REP_STOSB_32:
1597 case X86::REP_STOSB_64:
1598 case X86::REP_STOSD_32:
1599 case X86::REP_STOSD_64:
1600 case X86::REP_STOSQ_32:
1601 case X86::REP_STOSQ_64:
1602 case X86::REP_STOSW_32:
1603 case X86::REP_STOSW_64:
1615 int64_t FixedEnd = 0;
1616 int64_t LocalsTop = std::numeric_limits<int64_t>::max();
1626 FixedEnd = std::max(FixedEnd, -ObjOffset);
1628 LocalsTop = std::min<int64_t>(LocalsTop, -ObjOffset - ObjSize);
1630 if (LocalsTop == std::numeric_limits<int64_t>::max())
1633 assert(LocalsTop >= FixedEnd &&
"Local object overlaps the fixed area");
1634 return LocalsTop - FixedEnd;
1725 "MF used frame lowering for wrong subtarget");
1730 uint64_t MaxAlign = calculateMaxStackAlign(MF);
1732 bool IsFunclet =
MBB.isEHFuncletEntry();
1736 bool FnHasClrFunclet =
1738 bool IsClrFunclet = IsFunclet && FnHasClrFunclet;
1739 bool HasFP =
hasFP(MF);
1743 bool NeedsWinFPO = !IsFunclet &&
STI.isTargetWin32() &&
1745 bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;
1746 bool NeedsDwarfCFI = needsDwarfCFI(MF);
1753 bool HasWinCFI =
false;
1762 auto EmitSEHBefore = [&](
auto EmitFn) {
1763 if (NeedsWinCFI && IsWin64UnwindV3) {
1768 auto EmitSEHAfter = [&](
auto EmitFn) {
1769 if (NeedsWinCFI && !IsWin64UnwindV3) {
1784 ArgBaseReg =
MI->getOperand(0).getReg();
1797 if (NeedsDwarfCFI) {
1799 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(ArgBaseReg,
true);
1818 if (TailCallArgReserveSize && IsWin64Prologue)
1821 const bool EmitStackProbeCall =
1822 STI.getTargetLowering()->hasStackProbeSymbol(MF);
1823 unsigned StackProbeSize =
STI.getTargetLowering()->getStackProbeSize(MF);
1828 if (
STI.swiftAsyncContextIsDynamicallySet()) {
1838 .
addUse(X86::NoRegister);
1846 "win64 prologue does not set the bit 60 in the saved frame pointer");
1885 !EmitStackProbeCall &&
1893 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
1900 if (TailCallArgReserveSize != 0) {
1901 BuildStackAdjustment(
MBB,
MBBI,
DL, -(
int)TailCallArgReserveSize,
1920 uint64_t NumBytes = 0;
1930 if (IsWin64Prologue && IsFunclet && !IsClrFunclet) {
1938 MBB.addLiveIn(Establisher);
1945 uint64_t FrameSize = StackSize -
SlotSize;
1952 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue) {
1954 assert(Padding <= NumBytes &&
"Padding exceeds the local area");
1955 NumBytes =
alignTo(NumBytes - Padding, MaxAlign);
1959 auto EmitSEHPushFramePtr = [&]() {
1964 EmitSEHBefore(EmitSEHPushFramePtr);
1969 EmitSEHAfter(EmitSEHPushFramePtr);
1971 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1977 nullptr, -2 * stackGrowth + (
int)TailCallArgReserveSize),
1981 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1985 (
int)TailCallArgReserveSize),
1991 assert(!IsWin64Prologue &&
1992 "win64 prologue does not store async context right below rbp");
1998 auto EmitSEHPushR14 = [&]() {
2003 EmitSEHBefore(EmitSEHPushR14);
2004 if (Attrs.hasAttrSomewhere(Attribute::SwiftAsync)) {
2007 MBB.addLiveIn(X86::R14);
2020 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
2027 EmitSEHAfter(EmitSEHPushR14);
2038 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
2039 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2043 (
int)TailCallArgReserveSize),
2053 if (!IsWin64Prologue && !IsFunclet) {
2062 if (NeedsDwarfCFI) {
2065 CfaExpr.
push_back(dwarf::DW_CFA_expression);
2067 unsigned DwarfReg =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2079 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2091 assert(!IsWin64UnwindV3);
2101 assert(!IsFunclet &&
"funclets without FPs not yet implemented");
2109 if (HasFP &&
TRI->hasStackRealignment(MF))
2117 unsigned ParentFrameNumBytes = NumBytes;
2119 NumBytes = getWinEHFuncletFrameSize(MF);
2122 bool PushedRegs =
false;
2128 unsigned Opc =
MBBI->getOpcode();
2129 return Opc == X86::PUSH32r ||
Opc == X86::PUSH64r ||
Opc == X86::PUSHP64r ||
2130 Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
2133 while (IsCSPush(
MBBI)) {
2137 unsigned Opc = LastCSPush->getOpcode();
2138 bool IsPush2 =
Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
2141 EmitSEHBefore([&]() {
2145 .
addImm(LastCSPush->getOperand(1).getReg())
2155 if (!HasFP && NeedsDwarfCFI) {
2170 EmitSEHAfter([&]() {
2176 .
addImm(LastCSPush->getOperand(1).getReg())
2184 if (!IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF) &&
2186 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2187 auto EmitSEHStackAlign = [&]() {
2192 EmitSEHBefore(EmitSEHStackAlign);
2194 EmitSEHAfter(EmitSEHStackAlign);
2200 NumBytes = mergeSPUpdates(
2214 uint64_t AlignedNumBytes = NumBytes;
2215 if (IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF))
2216 AlignedNumBytes =
alignTo(AlignedNumBytes, MaxAlign);
2218 auto EmitSEHStackAlloc = [&]() {
2224 EmitSEHBefore(EmitSEHStackAlloc);
2226 if (AlignedNumBytes >= StackProbeSize && EmitStackProbeCall) {
2228 "The Red Zone is not accounted for in stack probes");
2250 int64_t
Alloc = isEAXAlive ? NumBytes - 8 : NumBytes;
2259 .
addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
2278 }
else if (NumBytes) {
2283 EmitSEHAfter(EmitSEHStackAlloc);
2285 int SEHFrameOffset = 0;
2293 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2295 MBB.addLiveIn(Establisher);
2297 Establisher, PSPSlotOffset)
2311 SPOrEstablisher = Establisher;
2316 if (IsWin64Prologue && HasFP) {
2323 if (NeedsWinCFI && !IsFunclet) {
2324 assert(!NeedsWinFPO &&
"this setframe incompatible with FPO data");
2327 if (
TRI->hasBasePointer(MF))
2335 auto EmitSEHSetFrame = [&]() {
2343 EmitSEHBefore(EmitSEHSetFrame);
2347 SPOrEstablisher, SEHFrameOffset);
2350 .
addReg(SPOrEstablisher);
2353 EmitSEHAfter(EmitSEHSetFrame);
2354 }
else if (IsFunclet &&
STI.is32Bit()) {
2359 if (!
MBB.isCleanupFuncletEntry()) {
2376 if (
Register Reg =
TII.isStoreToStackSlot(FrameInstr, FI)) {
2377 if (X86::FR64RegClass.
contains(Reg)) {
2380 if (IsWin64Prologue && IsFunclet)
2387 assert(!NeedsWinFPO &&
"SEH_SaveXMM incompatible with FPO data");
2388 auto EmitSEHSaveXMM = [&]() {
2394 EmitSEHBefore(EmitSEHSaveXMM);
2396 EmitSEHAfter(EmitSEHSaveXMM);
2404 if (NeedsWinCFI && HasWinCFI) {
2409 if (FnHasClrFunclet && !IsFunclet) {
2413 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2427 if (IsWin64Prologue &&
TRI->hasStackRealignment(MF)) {
2428 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2429 BuildStackAlignAND(
MBB,
MBBI,
DL, SPOrEstablisher, MaxAlign);
2433 if (IsFunclet &&
STI.is32Bit())
2440 if (
TRI->hasBasePointer(MF)) {
2466 assert(UsedReg == BasePtr);
2475 int FI =
MI->getOperand(1).getIndex();
2476 unsigned MOVmr =
Is64Bit ? X86::MOV64mr : X86::MOV32mr;
2483 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
2485 if (!HasFP && NumBytes) {
2511 bool NeedsCLD =
false;
2525 if (
MI.isInlineAsm()) {
2557 switch (
MI.getOpcode()) {
2559 case X86::CLEANUPRET:
2581X86FrameLowering::getPSPSlotOffsetFromSP(
const MachineFunction &MF)
const {
2588 return static_cast<unsigned>(
Offset);
2592X86FrameLowering::getWinEHFuncletFrameSize(
const MachineFunction &MF)
const {
2593 const X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
2599 WinEHXMMSlotInfo.
size() *
TRI->getSpillSize(X86::VR128RegClass);
2608 UsedSize = getPSPSlotOffsetFromSP(MF) +
SlotSize;
2619 return FrameSizeMinusRBP + XMMSize - CSSize;
2623 return Opc == X86::TCRETURNri ||
Opc == X86::TCRETURN_WIN64ri ||
2624 Opc == X86::TCRETURN_HIPE32ri ||
Opc == X86::TCRETURNdi ||
2625 Opc == X86::TCRETURNmi ||
Opc == X86::TCRETURNri64 ||
2626 Opc == X86::TCRETURNri64_ImpCall ||
Opc == X86::TCRETURNdi64 ||
2627 Opc == X86::TCRETURNmi64 ||
Opc == X86::TCRETURN_WINmi64;
2638 DL =
MBBI->getDebugLoc();
2640 const bool Is64BitILP32 =
STI.isTarget64BitILP32();
2646 bool NeedsWin64CFI =
2650 bool IsWin64UnwindV3 =
2656 uint64_t MaxAlign = calculateMaxStackAlign(MF);
2659 bool HasFP =
hasFP(MF);
2660 uint64_t NumBytes = 0;
2662 bool NeedsDwarfCFI = (!MF.
getTarget().getTargetTriple().isOSDarwin() &&
2669 unsigned Opc = X86::LEA32r;
2671 ArgBaseReg =
MI->getOperand(0).getReg();
2672 if (
STI.is64Bit()) {
2674 StackReg = X86::RSP;
2685 if (NeedsDwarfCFI) {
2686 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(StackReg,
true);
2696 assert(HasFP &&
"EH funclets without FP not yet implemented");
2697 NumBytes = getWinEHFuncletFrameSize(MF);
2700 uint64_t FrameSize = StackSize -
SlotSize;
2701 NumBytes = FrameSize - CSSize - TailCallArgReserveSize;
2705 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
2706 NumBytes =
alignTo(FrameSize, MaxAlign);
2708 NumBytes = StackSize - CSSize - TailCallArgReserveSize;
2710 uint64_t SEHStackAllocAmt = NumBytes;
2712 unsigned SEHFrameOffset = 0;
2713 if (IsWin64Prologue && HasFP)
2725 if (IsWin64UnwindV3)
2743 if (NeedsDwarfCFI) {
2745 unsigned DwarfStackPtr =
2746 TRI->getDwarfRegNum(
Is64Bit ? X86::RSP : X86::ESP,
true);
2751 if (!
MBB.succ_empty() && !
MBB.isReturnBlock()) {
2752 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2767 unsigned Opc = PI->getOpcode();
2769 if (
Opc != X86::DBG_VALUE && !PI->isTerminator()) {
2771 (
Opc != X86::POP32r &&
Opc != X86::POP64r &&
Opc != X86::BTR64ri8 &&
2772 Opc != X86::ADD64ri32 &&
Opc != X86::POPP64r &&
Opc != X86::POP2 &&
2773 Opc != X86::POP2P &&
Opc != X86::LEA64r &&
Opc != X86::SEH_PushReg &&
2774 Opc != X86::SEH_Push2Regs &&
Opc != X86::SEH_StackAlloc &&
2775 Opc != X86::ADD64ri32_NF))
2785 int FI =
MI->getOperand(1).getIndex();
2786 unsigned MOVrm =
Is64Bit ? X86::MOV64rm : X86::MOV32rm;
2793 if (IsFunclet && Terminator->getOpcode() == X86::CATCHRET)
2794 emitCatchRetReturnValue(
MBB, FirstCSPop, &*Terminator);
2797 DL =
MBBI->getDebugLoc();
2803 if (IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI()) {
2806 auto EpilogStart =
MBBI;
2809 while (ScanIt !=
MBB.begin()) {
2810 auto PI = std::prev(ScanIt);
2813 TII.isLoadFromStackSlot(*PI, FI)) {
2814 Register Reg = PI->getOperand(0).getReg();
2815 if (X86::FR64RegClass.
contains(Reg)) {
2828 EpilogStart = std::prev(PI);
2829 ScanIt = EpilogStart;
2848 if (
TRI->hasStackRealignment(MF))
2850 uint64_t LEAAmount =
2851 IsWin64Prologue ? SEHStackAllocAmt - SEHFrameOffset : -CSSize;
2863 if (IsWin64UnwindV3) {
2868 if (SEHStackAllocAmt)
2870 .
addImm(SEHStackAllocAmt)
2873 if (LEAAmount != 0) {
2883 }
else if (NumBytes) {
2885 if (IsWin64UnwindV3)
2890 if (!HasFP && NeedsDwarfCFI) {
2894 nullptr, CSSize + TailCallArgReserveSize +
SlotSize),
2901 if (!IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI())
2905 if (!HasFP && NeedsDwarfCFI) {
2912 unsigned Opc = PI->getOpcode();
2914 if (
Opc == X86::POP32r ||
Opc == X86::POP64r ||
Opc == X86::POPP64r ||
2915 Opc == X86::POP2 ||
Opc == X86::POP2P) {
2919 if (
Opc == X86::POP2 ||
Opc == X86::POP2P)
2931 if (NeedsDwarfCFI && !
MBB.succ_empty())
2937 assert(Delta <= 0 &&
"TCDelta should never be positive");
2963 if (
TRI->hasBasePointer(MF))
2964 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getBaseRegister();
2965 else if (
TRI->hasStackRealignment(MF))
2966 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getStackRegister();
2968 FrameReg =
TRI->getFrameRegister(MF);
2979 int64_t FPDelta = 0;
2990 if (IsWin64Prologue) {
2994 uint64_t FrameSize = StackSize -
SlotSize;
2999 uint64_t NumBytes = FrameSize - CSSize;
3009 FPDelta = FrameSize - SEHFrameOffset;
3011 "FPDelta isn't aligned per the Win64 ABI!");
3014 if (FrameReg ==
TRI->getFramePtr()) {
3023 if (TailCallReturnAddrDelta < 0)
3024 Offset -= TailCallReturnAddrDelta;
3032 if (
TRI->hasStackRealignment(MF) ||
TRI->hasBasePointer(MF))
3042 const auto it = WinEHXMMSlotInfo.find(FI);
3044 if (it == WinEHXMMSlotInfo.end())
3047 FrameReg =
TRI->getStackRegister();
3055 int Adjustment)
const {
3057 FrameReg =
TRI->getStackRegister();
3065 bool IgnoreSPUpdates)
const {
3104 !
STI.isTargetWin64())
3115 "we don't handle this case!");
3147 std::vector<CalleeSavedInfo> &CSI)
const {
3151 unsigned CalleeSavedFrameSize = 0;
3152 unsigned XMMCalleeSavedFrameSize = 0;
3158 if (TailCallReturnAddrDelta < 0) {
3169 TailCallReturnAddrDelta -
SlotSize,
true);
3173 if (this->TRI->hasBasePointer(MF)) {
3182 bool IsFPRemovedFromCSI =
false;
3200 for (
unsigned i = 0; i < CSI.size(); ++i) {
3201 if (
TRI->regsOverlap(CSI[i].getReg(),
FPReg)) {
3202 CSI.erase(CSI.begin() + i);
3203 IsFPRemovedFromCSI =
true;
3219 unsigned NumRegsForPush2 = 0;
3222 return X86::GR64RegClass.contains(
I.getReg());
3224 bool UsePush2Pop2 = !IsFPRemovedFromCSI ? NumCSGPR > 2 : NumCSGPR > 1;
3227 ?
alignDown(IsFPRemovedFromCSI ? NumCSGPR : NumCSGPR - 1, 2)
3241 (SpillSlotOffset % 16 == 0 ||
3263 "Expect even candidates for push2/pop2");
3265 ++NumFunctionUsingPush2Pop2;
3276 unsigned Size =
TRI->getSpillSize(*RC);
3281 assert(SpillSlotOffset < 0 &&
"SpillSlotOffset should always < 0 on X86");
3282 SpillSlotOffset = -
alignTo(-SpillSlotOffset, Alignment);
3285 SpillSlotOffset -=
Size;
3291 if (X86::VR128RegClass.
contains(Reg)) {
3292 WinEHXMMSlotInfo[
SlotIndex] = XMMCalleeSavedFrameSize;
3293 XMMCalleeSavedFrameSize +=
Size;
3307 if (
MBB.isEHFuncletEntry() &&
STI.is32Bit() &&
STI.isOSWindows())
3316 auto UpdateLiveInCheckCanKill = [&](
Register Reg) {
3323 if (
MRI.isLiveIn(Reg))
3328 if (
MRI.isLiveIn(*AReg))
3332 auto UpdateLiveInGetKillRegState = [&](
Register Reg) {
3336 for (
auto RI = CSI.
rbegin(), RE = CSI.
rend(); RI != RE; ++RI) {
3344 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3345 .
addReg(Reg2, UpdateLiveInGetKillRegState(Reg2))
3349 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3355 unsigned Opc =
STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r;
3356 Register BaseReg = this->TRI->getBaseRegister();
3385 MBB.getParent()->getFunction().getPersonalityFn())) &&
3386 "SEH should not use CATCHRET");
3391 if (
STI.is64Bit()) {
3423 if (
MI->getOpcode() == X86::CATCHRET) {
3452 if (IsWin64UnwindV3)
3454 .
addImm(this->TRI->getBaseRegister())
3456 unsigned Opc =
STI.is64Bit() ? X86::POP64r : X86::POP32r;
3457 Register BaseReg = this->TRI->getBaseRegister();
3463 for (
auto I = CSI.
begin(), E = CSI.
end();
I != E; ++
I) {
3470 if (IsWin64UnwindV3) {
3480 if (IsWin64UnwindV3)
3498 if (
TRI->hasBasePointer(MF)) {
3500 if (
STI.isTarget64BitILP32())
3502 SavedRegs.
set(BasePtr);
3504 if (
STI.hasUserReservedRegisters()) {
3505 for (
int Reg = SavedRegs.
find_first(); Reg != -1;
3507 if (
STI.isRegisterReservedByUser(Reg)) {
3508 SavedRegs.
reset(Reg);
3518 if (
I->hasNestAttr() && !
I->use_empty())
3535 return Primary ? X86::R14 : X86::R13;
3537 return Primary ? X86::EBX : X86::EDI;
3542 return Primary ? X86::R11 : X86::R12;
3544 return Primary ? X86::R11D : X86::R12D;
3554 "nested function.");
3555 return Primary ? X86::EAX : X86::ECX;
3558 return Primary ? X86::EDX : X86::EAX;
3559 return Primary ? X86::ECX : X86::EAX;
3570 unsigned TlsReg, TlsOffset;
3575 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3579 "Scratch register is live-in");
3583 if (!
STI.isTargetLinux() && !
STI.isTargetDarwin() && !
STI.isTargetWin32() &&
3584 !
STI.isTargetWin64() && !
STI.isTargetFreeBSD() &&
3585 !
STI.isTargetDragonFly())
3599 bool IsNested =
false;
3608 for (
const auto &LI : PrologueMBB.
liveins()) {
3625 if (
STI.isTargetLinux()) {
3627 TlsOffset =
IsLP64 ? 0x70 : 0x40;
3628 }
else if (
STI.isTargetDarwin()) {
3630 TlsOffset = 0x60 + 90 * 8;
3631 }
else if (
STI.isTargetWin64()) {
3634 }
else if (
STI.isTargetFreeBSD()) {
3637 }
else if (
STI.isTargetDragonFly()) {
3644 if (CompareStackPointer)
3645 ScratchReg =
IsLP64 ? X86::RSP : X86::ESP;
3663 if (
STI.isTargetLinux()) {
3666 }
else if (
STI.isTargetDarwin()) {
3668 TlsOffset = 0x48 + 90 * 4;
3669 }
else if (
STI.isTargetWin32()) {
3672 }
else if (
STI.isTargetDragonFly()) {
3675 }
else if (
STI.isTargetFreeBSD()) {
3681 if (CompareStackPointer)
3682 ScratchReg = X86::ESP;
3684 BuildMI(checkMBB,
DL,
TII.get(X86::LEA32r), ScratchReg)
3691 if (
STI.isTargetLinux() ||
STI.isTargetWin32() ||
STI.isTargetWin64() ||
3692 STI.isTargetDragonFly()) {
3700 }
else if (
STI.isTargetDarwin()) {
3703 unsigned ScratchReg2;
3705 if (CompareStackPointer) {
3708 SaveScratch2 =
false;
3720 "Scratch register is live-in and not saved");
3726 BuildMI(checkMBB,
DL,
TII.get(X86::MOV32ri), ScratchReg2)
3737 BuildMI(checkMBB,
DL,
TII.get(X86::POP32r), ScratchReg2);
3753 const unsigned RegAX =
IsLP64 ? X86::RAX : X86::EAX;
3754 const unsigned Reg10 =
IsLP64 ? X86::R10 : X86::R10D;
3755 const unsigned Reg11 =
IsLP64 ? X86::R11 : X86::R11D;
3756 const unsigned MOVrr =
IsLP64 ? X86::MOV64rr : X86::MOV32rr;
3791 if (
STI.useIndirectThunkCalls())
3793 "code model and thunks not yet implemented.");
3810 BuildMI(allocMBB,
DL,
TII.get(X86::MORESTACK_RET_RESTORE_R10));
3819#ifdef EXPENSIVE_CHECKS
3830 for (
int i = 0, e = HiPELiteralsMD->
getNumOperands(); i != e; ++i) {
3832 if (
Node->getNumOperands() != 2)
3836 if (!NodeName || !NodeVal)
3839 if (ValConst && NodeName->
getString() == LiteralName) {
3845 " required but not provided");
3856 return MI.isMetaInstruction();
3882 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3887 if (!HiPELiteralsMD)
3889 "Can't generate HiPE prologue without runtime parameters");
3891 HiPELiteralsMD,
Is64Bit ?
"AMD64_LEAF_WORDS" :
"X86_LEAF_WORDS");
3892 const unsigned CCRegisteredArgs =
Is64Bit ? 6 : 5;
3893 const unsigned Guaranteed = HipeLeafWords *
SlotSize;
3900 "HiPE prologue is only supported on Linux operating systems.");
3910 unsigned MoreStackForCalls = 0;
3912 for (
auto &
MBB : MF) {
3913 for (
auto &
MI :
MBB) {
3933 if (
F->getName().contains(
"erlang.") ||
F->getName().contains(
"bif_") ||
3937 unsigned CalleeStkArity =
F->arg_size() > CCRegisteredArgs
3938 ?
F->arg_size() - CCRegisteredArgs
3940 if (HipeLeafWords - 1 > CalleeStkArity)
3942 std::max(MoreStackForCalls,
3943 (HipeLeafWords - 1 - CalleeStkArity) *
SlotSize);
3946 MaxStack += MoreStackForCalls;
3951 if (MaxStack > Guaranteed) {
3955 for (
const auto &LI : PrologueMBB.
liveins()) {
3963 unsigned ScratchReg,
SPReg, PReg, SPLimitOffset;
3964 unsigned LEAop, CMPop, CALLop;
3969 LEAop = X86::LEA64r;
3970 CMPop = X86::CMP64rm;
3971 CALLop = X86::CALL64pcrel32;
3975 LEAop = X86::LEA32r;
3976 CMPop = X86::CMP32rm;
3977 CALLop = X86::CALLpcrel32;
3982 "HiPE prologue scratch register is live-in");
3989 PReg, SPLimitOffset);
3999 PReg, SPLimitOffset);
4009#ifdef EXPENSIVE_CHECKS
4026 if (NumPops != 1 && NumPops != 2)
4034 if (!Prev->isCall() || !Prev->getOperand(1).isRegMask())
4038 unsigned FoundRegs = 0;
4044 Is64Bit ? X86::GR64_NOREX_NOSPRegClass : X86::GR32_NOREX_NOSPRegClass;
4046 for (
auto Candidate : RegClass) {
4054 if (
MRI.isReserved(Candidate))
4059 if (MO.isReg() && MO.isDef() &&
4060 TRI->isSuperOrSubRegisterEq(MO.getReg(), Candidate)) {
4069 Regs[FoundRegs++] = Candidate;
4070 if (FoundRegs == (
unsigned)NumPops)
4078 while (FoundRegs < (
unsigned)NumPops)
4079 Regs[FoundRegs++] = Regs[0];
4081 for (
int i = 0; i < NumPops; ++i)
4092 unsigned Opcode =
I->getOpcode();
4093 bool isDestroy = Opcode ==
TII.getCallFrameDestroyOpcode();
4095 uint64_t Amount =
TII.getFrameSize(*
I);
4096 uint64_t InternalAmt = (isDestroy || Amount) ?
TII.getFrameAdjustment(*
I) : 0;
4106 if (!reserveCallFrame) {
4127 bool HasDwarfEHHandlers = !WindowsCFI && !MF.
getLandingPads().empty();
4129 if (HasDwarfEHHandlers && !isDestroy &&
4139 Amount -= InternalAmt;
4149 int64_t StackAdjustment = isDestroy ? Amount : -Amount;
4150 int64_t CfaAdjustment = StackAdjustment;
4152 if (StackAdjustment) {
4161 auto CalcNewOffset = [&StackAdjustment](int64_t
Offset) {
4162 return StackAdjustment +
Offset;
4165 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
true);
4167 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
false);
4169 if (StackAdjustment) {
4170 if (!(
F.hasMinSize() &&
4171 adjustStackWithPops(
MBB, InsertPos,
DL, StackAdjustment)))
4172 BuildStackAdjustment(
MBB, InsertPos,
DL, StackAdjustment,
4198 while (CI !=
B && !std::prev(CI)->isCall())
4200 BuildStackAdjustment(
MBB, CI,
DL, -InternalAmt,
false);
4207 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4209 if (!
MBB.isLiveIn(X86::EFLAGS))
4216 if (TLI.hasInlineStackProbe(MF) || TLI.hasStackProbeSymbol(MF))
4224 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4230 if (
STI.isTargetWin64() && !
MBB.succ_empty() && !
MBB.isReturnBlock())
4252 bool CompactUnwind =
4268 assert(
STI.isTargetWindowsMSVC() &&
"funclets only supported in MSVC env");
4269 assert(
STI.isTargetWin32() &&
"EBP/ESI restoration only required on win32");
4271 "restoring EBP/ESI on non-32-bit target");
4283 int EHRegSize = MFI.getObjectSize(FI);
4288 X86::EBP, -EHRegSize)
4294 int EndOffset = -EHRegOffset - EHRegSize;
4307 "end of registration object above normal EBP position!");
4308 }
else if (UsedReg == BasePtr) {
4318 assert(UsedReg == BasePtr);
4329 return TRI->getSlotSize();
4344 FrameBase.
Kind = DwarfFrameBase::CFA;
4350 return DwarfFrameBase{DwarfFrameBase::Register, {FrameRegister}};
4355struct X86FrameSortingObject {
4356 bool IsValid =
false;
4357 unsigned ObjectIndex = 0;
4358 unsigned ObjectSize = 0;
4360 unsigned ObjectNumUses = 0;
4376struct X86FrameSortingComparator {
4377 inline bool operator()(
const X86FrameSortingObject &
A,
4378 const X86FrameSortingObject &
B)
const {
4379 uint64_t DensityAScaled, DensityBScaled;
4399 DensityAScaled =
static_cast<uint64_t>(
A.ObjectNumUses) *
4401 DensityBScaled =
static_cast<uint64_t>(
B.ObjectNumUses) *
4412 if (DensityAScaled == DensityBScaled)
4413 return A.ObjectAlignment <
B.ObjectAlignment;
4415 return DensityAScaled < DensityBScaled;
4429 if (ObjectsToAllocate.
empty())
4441 for (
auto &Obj : ObjectsToAllocate) {
4442 SortingObjects[Obj].IsValid =
true;
4443 SortingObjects[Obj].ObjectIndex = Obj;
4447 if (ObjectSize == 0)
4449 SortingObjects[Obj].ObjectSize = 4;
4451 SortingObjects[Obj].ObjectSize = ObjectSize;
4455 for (
auto &
MBB : MF) {
4456 for (
auto &
MI :
MBB) {
4457 if (
MI.isDebugInstr())
4463 int Index = MO.getIndex();
4467 SortingObjects[Index].IsValid)
4468 SortingObjects[Index].ObjectNumUses++;
4483 for (
auto &Obj : SortingObjects) {
4487 ObjectsToAllocate[i++] = Obj.ObjectIndex;
4491 if (!
TRI->hasStackRealignment(MF) &&
hasFP(MF))
4492 std::reverse(ObjectsToAllocate.
begin(), ObjectsToAllocate.
end());
4504 Offset += getWinEHFuncletFrameSize(MF);
4519 RS->addScavengingFrameIndex(FI);
4532 adjustFrameForMsvcCxxEh(MF);
4536void X86FrameLowering::adjustFrameForMsvcCxxEh(
MachineFunction &MF)
const {
4544 int64_t MinFixedObjOffset = -
SlotSize;
4550 int FrameIndex =
H.CatchObj.FrameIndex;
4551 if ((FrameIndex != INT_MAX) && MFI.
getObjectOffset(FrameIndex) == 0) {
4554 MinFixedObjOffset -= std::abs(MinFixedObjOffset) %
Align;
4562 MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8;
4563 int64_t UnwindHelpOffset = MinFixedObjOffset -
SlotSize;
4570 MachineBasicBlock &
MBB = MF.
front();
4590 MI->eraseFromParent();
4603 bool NeedsRestore =
MBB.isEHPad() && !
MBB.isEHFuncletEntry();
4614 unsigned NumSpilledRegs) {
4616 unsigned AllocSize =
TRI->getSpillSize(*RC) * NumSpilledRegs;
4618 unsigned AlignedSize =
alignTo(AllocSize, StackAlign);
4619 return AlignedSize - AllocSize;
4625 int SPAdjust)
const {
4628 MachineBasicBlock *
MBB = BeforeMI->getParent();
4650 if (
FP.isValid() && needsDwarfCFI(MF)) {
4659 SmallString<64> CfaExpr;
4663 Offset +=
TRI->getSpillSize(*
TRI->getMinimalPhysRegClass(BP));
4666 if (
TII.isFrameSetup(*BeforeMI)) {
4668 BeforeMI = std::next(BeforeMI);
4671 if (
STI.isTarget64BitILP32())
4673 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(
StackPtr,
true);
4674 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfStackPtr));
4679 CfaExpr.
push_back((uint8_t)dwarf::DW_OP_plus);
4681 SmallString<64> DefCfaExpr;
4682 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
4694 int SPAdjust)
const {
4698 MachineBasicBlock *
MBB = AfterMI->getParent();
4716 if (needsDwarfCFI(MF)) {
4726void X86FrameLowering::saveAndRestoreFPBPUsingSP(
4729 assert(SpillFP || SpillBP);
4733 unsigned NumRegs = 0;
4736 FP =
TRI->getFrameRegister(MF);
4737 if (
STI.isTarget64BitILP32())
4739 RC =
TRI->getMinimalPhysRegClass(
FP);
4743 BP =
TRI->getBaseRegister();
4744 if (
STI.isTarget64BitILP32())
4746 RC =
TRI->getMinimalPhysRegClass(BP);
4751 spillFPBPUsingSP(MF, BeforeMI,
FP, BP, SPAdjust);
4752 restoreFPBPUsingSP(MF, AfterMI,
FP, BP, SPAdjust);
4755bool X86FrameLowering::skipSpillFPBP(
4757 if (
MI->getOpcode() == X86::LCMPXCHG16B_SAVE_RBX) {
4765 while (!(
MI->getOpcode() == TargetOpcode::COPY &&
4766 MI->getOperand(1).getReg() == X86::RBX) &&
4767 !((
Reg =
TII.isStoreToStackSlot(*
MI, FI)) &&
Reg == X86::RBX))
4777 AccessFP = AccessBP =
false;
4779 if (
MI.findRegisterUseOperandIdx(
FP,
TRI,
false) != -1 ||
4780 MI.findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4784 if (
MI.findRegisterUseOperandIdx(BP,
TRI,
false) != -1 ||
4785 MI.findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4788 return AccessFP || AccessBP;
4801 if (!
MBB->hasEHPadSuccessor())
4814void X86FrameLowering::checkInterferedAccess(
4817 bool SpillBP)
const {
4818 if (
DefMI == KillMI)
4820 if (
TRI->hasBasePointer(MF)) {
4831 [](
const MachineOperand &MO) { return MO.isFI(); }))
4833 "Interference usage of base pointer/frame "
4864 FP =
TRI->getFrameRegister(MF);
4865 if (
TRI->hasBasePointer(MF))
4866 BP =
TRI->getBaseRegister();
4881 bool InsideEHLabels =
false;
4882 auto MI =
MBB.rbegin(), ME =
MBB.rend();
4883 auto TermMI =
MBB.getFirstTerminator();
4884 if (TermMI ==
MBB.begin())
4886 MI = *(std::prev(TermMI));
4894 isInvoke(*
MI, InsideEHLabels) || skipSpillFPBP(MF,
MI)) {
4899 if (
MI->getOpcode() == TargetOpcode::EH_LABEL) {
4900 InsideEHLabels = !InsideEHLabels;
4905 bool AccessFP, AccessBP;
4914 bool FPLive =
false, BPLive =
false;
4915 bool SpillFP =
false, SpillBP =
false;
4918 SpillFP |= AccessFP;
4919 SpillBP |= AccessBP;
4922 if (FPLive &&
MI->findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4924 if (
FP &&
MI->findRegisterUseOperandIdx(
FP,
TRI,
false) != -1)
4926 if (BPLive &&
MI->findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4928 if (BP &&
MI->findRegisterUseOperandIdx(BP,
TRI,
false) != -1)
4932 }
while ((
MI != ME) &&
4933 (FPLive || BPLive ||
4937 if (FPLive && !SpillBP)
4942 if (KillMI->isCall() &&
DefMI != ME) {
4943 auto FrameSetup = std::next(
DefMI);
4947 while (FrameSetup != ME && !
TII.isFrameSetup(*FrameSetup) &&
4948 !FrameSetup->isCall())
4952 if (FrameSetup != ME &&
TII.isFrameSetup(*FrameSetup) &&
4953 (
TII.getFrameSize(*FrameSetup) ||
4954 TII.getFrameAdjustment(*FrameSetup))) {
4955 while (!
TII.isFrameInstr(*KillMI))
4963 checkInterferedAccess(MF,
DefMI, KillMI, SpillFP, SpillBP);
4966 saveAndRestoreFPBPUsingSP(MF, &(*
DefMI), &(*KillMI), SpillFP, SpillBP);
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const uint64_t kSplitStackAvailable
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static bool isTailCallOpcode(unsigned Opc)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg FPReg
static constexpr MCPhysReg SPReg
MachineRegisterInfo & MRI
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool is64Bit(const char *name)
static unsigned calculateSetFPREG(uint64_t SPAdjust)
static unsigned GetScratchRegister(bool Is64Bit, bool IsLP64, const MachineFunction &MF, bool Primary)
GetScratchRegister - Get a temp register for performing work in the segmented stack and the Erlang/Hi...
static unsigned getADDriOpcode(bool IsLP64)
static unsigned getPUSH2Opcode(const X86Subtarget &ST)
static uint64_t getUnusedLocalAreaPadding(const MachineFrameInfo &MFI)
Returns the number of bytes between the end of the fixed and callee-save area and the first local obj...
static unsigned getLEArOpcode(bool IsLP64)
static unsigned getSUBriOpcode(bool IsLP64)
static bool flagsNeedToBePreservedBeforeTheTerminators(const MachineBasicBlock &MBB)
Check if the flags need to be preserved before the terminators.
static bool isFPBPAccess(const MachineInstr &MI, Register FP, Register BP, const TargetRegisterInfo *TRI, bool &AccessFP, bool &AccessBP)
static const TargetRegisterClass * getCalleeSavedSpillRC(MCRegister Reg, const X86Subtarget &STI, const TargetRegisterInfo &TRI)
static bool isOpcodeRep(unsigned Opcode)
Return true if an opcode is part of the REP group of instructions.
static unsigned getANDriOpcode(bool IsLP64, int64_t Imm)
static bool isEAXLiveIn(MachineBasicBlock &MBB)
static int computeFPBPAlignmentGap(MachineFunction &MF, const TargetRegisterClass *RC, unsigned NumSpilledRegs)
static unsigned getADDrrOpcode(bool IsLP64)
static bool HasNestArgument(const MachineFunction *MF)
static unsigned getPOPOpcode(const X86Subtarget &ST)
static bool isInvoke(const MachineInstr &MI, bool InsideEHLabels)
static unsigned getPOP2Opcode(const X86Subtarget &ST)
static unsigned getHiPELiteral(NamedMDNode *HiPELiteralsMD, const StringRef LiteralName)
Lookup an ERTS parameter in the !hipe.literals named metadata node.
static bool blockEndIsUnreachable(const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI)
static unsigned getSUBrrOpcode(bool IsLP64)
static unsigned getPUSHOpcode(const X86Subtarget &ST)
constexpr uint64_t MaxSPChunk
static const unsigned FramePtr
Represent a constant reference to an array (0 or more elements consecutively in memory),...
reverse_iterator rend() const
bool empty() const
Check if the array is empty.
reverse_iterator rbegin() const
BitVector & reset()
Reset all bits in the bitvector.
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
BitVector & set()
Set all bits in the bitvector.
int find_next(unsigned Prev) const
Returns the index of the next set bit following the "Prev" bit.
iterator_range< const_set_bits_iterator > set_bits() const
static constexpr BranchProbability getOne()
static constexpr BranchProbability getZero()
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
AttributeList getAttributes() const
Return the attribute list for this Function.
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
const Argument * const_arg_iterator
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Module * getParent()
Get the module that this global value is contained inside of...
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size, SMLoc Loc={})
A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_restore says that the rule for Register is now the same as it was at the beginning of the functi...
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc={})
.cfi_remember_state Save all current rules for all registers.
OpType getOperation() const
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment, SMLoc Loc={})
.cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but Offset is a relative value that is added/subt...
static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc={})
.cfi_restore_state Restore the previously saved state.
const MCObjectFileInfo * getObjectFileInfo() const
const MCRegisterInfo * getRegisterInfo() const
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
MCSection * getCompactUnwindSection() const
MCRegAliasIterator enumerates all registers aliasing Reg.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
LLVM_ABI StringRef getString() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MachineInstrBundleIterator< const MachineInstr > const_iterator
iterator_range< livein_iterator > liveins() const
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Live
Register is known to be (at least partially) live.
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool needsSplitStackProlog() const
Return true if this function requires a split stack prolog, even if it uses no stack space.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
LLVM_ABI void ensureMaxAlignment(Align Alignment)
Make sure the function's frame is at least Align bytes aligned.
bool hasCalls() const
Return true if the current function has any function calls.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return alignment of this function's frame.
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool hasOpaqueSPAdjustment() const
Returns true if the function contains opaque dynamic stack adjustments.
void setCVBytesOfCalleeSavedRegisters(unsigned S)
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment, TargetStackID::Value StackID=TargetStackID::Default)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool isVariableSizedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a variable sized object.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
bool hasCopyImplyingStackAdjustment() const
Returns true if the function contains operations which will lower down to instructions which manipula...
bool hasStackObjects() const
Return true if there are any stack objects in this function.
LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
uint8_t getStackID(int ObjectIdx) const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
const WinEHFuncInfo * getWinEHFuncInfo() const
getWinEHFuncInfo - Return information about how the current function uses Windows exception handling.
unsigned addFrameInst(const MCCFIInstruction &Inst)
void setHasWinCFI(bool v)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const std::vector< MCCFIInstruction > & getFrameInstructions() const
Returns a reference to a list of cfi instructions in the function's prologue.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
void makeDebugValueSubstitution(DebugInstrOperandPair, DebugInstrOperandPair, unsigned SubReg=0)
Create a substitution between one <instr,operand> value to a different, new value.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
bool callsUnwindInit() const
void push_front(MachineBasicBlock *MBB)
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
MCContext & getContext() const
bool callsEHReturn() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use.
bool needsWinCFI() const
True if this function uses SEH unwind opcodes and needs an unwind table entry.
Function & getFunction()
Return the LLVM function that this machine code represents.
bool usesWindowsUnwindInfo() const
True if this function describes its unwind information with Windows SEH unwind opcodes (....
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
BasicBlockListType::iterator iterator
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
bool shouldSplitStack() const
Should we be emitting segmented stack stuff for the function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
bool hasEHFunclets() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI unsigned getDebugInstrNum()
Fetch the instruction number of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI bool isLiveIn(Register Reg) const
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
WinX64EHUnwindMode getWinX64EHUnwindMode() const
Get how unwind information should be generated for x64 Windows.
unsigned getCodeViewFlag() const
Returns the CodeView Version by checking module flags.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SlotIndex - An opaque wrapper around machine indexes.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
static StackOffset getFixed(int64_t Fixed)
Represent a constant reference to a string, i.e.
static constexpr size_t npos
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
const Triple & getTargetTriple() const
CodeModel::Model getCodeModel() const
Returns the code model.
SwiftAsyncFramePointerMode SwiftAsyncFramePointer
Control when and how the Swift async frame pointer bit should be set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
bool isUEFI() const
Tests whether the OS is UEFI.
bool isOSWindows() const
Tests whether the OS is Windows.
bool has128ByteRedZone(const MachineFunction &MF) const
Return true if the function has a redzone (accessible bytes past the frame of the top of stack functi...
void spillFPBP(MachineFunction &MF) const override
If a function uses base pointer and the base pointer is clobbered by inline asm, RA doesn't detect th...
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
bool needsFrameIndexResolution(const MachineFunction &MF) const override
X86FrameLowering(const X86Subtarget &STI, MaybeAlign StackAlignOverride)
const X86RegisterInfo * TRI
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool hasFPImpl(const MachineFunction &MF) const override
hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.
MachineBasicBlock::iterator restoreWin32EHStackPointers(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool RestoreSP=false) const
Sets up EBP and optionally ESI based on the incoming EBP value.
int getInitialCFAOffset(const MachineFunction &MF) const override
Return initial CFA offset value i.e.
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog, std::optional< MachineFunction::DebugInstrOperandPair > InstrNum=std::nullopt) const
Emit target stack probe code.
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool IsPrologue) const
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int64_t mergeSPAdd(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int64_t AddOffset, bool doMergeWithPrevious) const
Equivalent to: mergeSPUpdates(MBB, MBBI, [AddOffset](int64_t Offset) { return AddOffset + Offset; }...
StackOffset getFrameIndexReferenceSP(const MachineFunction &MF, int FI, Register &SPReg, int Adjustment) const
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override
Replace a StackProbe inline-stub with the actual probe code inline.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const
Emit a series of instructions to increment / decrement the stack pointer by a constant value.
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
bool Is64Bit
Is64Bit implies that x86_64 instructions are available.
Register getInitialCFARegister(const MachineFunction &MF) const override
Return initial CFA register value i.e.
bool Uses64BitFramePtr
True if the 64-bit frame or stack pointer should be used.
unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override
Adjust the prologue to have the function use segmented stacks.
DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override
Return the frame base information to be encoded in the DWARF subprogram debug info.
void emitCalleeSavedFrameMovesFullCFA(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override
Emits Dwarf Info specifying offsets of callee saved registers and frame pointer.
int getWin64EHFrameIndexRef(const MachineFunction &MF, int FI, Register &SPReg) const
bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const
Check that LEA can be used on SP in an epilogue sequence for MF.
bool stackProbeFunctionModifiesSP() const override
Does the stack probe function call return with a modified stack pointer?
void orderFrameObjects(const MachineFunction &MF, SmallVectorImpl< int > &ObjectsToAllocate) const override
Order the symbols in the local stack.
void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCCFIInstruction &CFIInst, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
Wraps up getting a CFI index and building a MachineInstr for it.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
void processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameIndicesReplaced - This method is called immediately before MO_FrameIndex op...
StackOffset getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, Register &FrameReg, bool IgnoreSPUpdates) const override
Same as getFrameIndexReference, except that the stack pointer (as opposed to the frame pointer) will ...
void restoreWinEHStackPointersInParent(MachineFunction &MF) const
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
void adjustForHiPEPrologue(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const override
Erlang programs may need a special prologue to handle the stack size they might need at runtime.
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
bool getForceFramePointer() const
bool isCandidateForPush2Pop2(Register Reg) const
unsigned getArgumentStackSize() const
bool getFPClobberedByCall() const
int getRestoreBasePointerOffset() const
int getSEHFramePtrSaveIndex() const
bool hasCFIAdjustCfa() const
int getTCReturnAddrDelta() const
void setRestoreBasePointer(const MachineFunction *MF)
bool getHasSEHFramePtrSave() const
DenseMap< int, unsigned > & getWinEHXMMSlotInfo()
bool getBPClobberedByCall() const
void setUsesRedZone(bool V)
bool hasPreallocatedCall() const
bool hasSwiftAsyncContext() const
void setHasSEHFramePtrSave(bool V)
bool getRestoreBasePointer() const
MachineInstr * getStackPtrSaveMI() const
size_t getNumCandidatesForPush2Pop2() const
AMXProgModelEnum getAMXProgModel() const
void addCandidateForPush2Pop2(Register Reg)
unsigned getCalleeSavedFrameSize() const
bool getHasPushSequences() const
void setStackPtrSaveMI(MachineInstr *MI)
bool getUsesRedZone() const
void setCalleeSavedFrameSize(unsigned bytes)
void setSEHFramePtrSaveIndex(int Index)
const X86TargetLowering * getTargetLowering() const override
bool isTargetWindowsCoreCLR() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
uint16_t StackAdjustment(const RuntimeFunction &RF)
StackAdjustment - calculated stack adjustment in words.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ HiPE
Used by the High-Performance Erlang Compiler (HiPE).
@ X86_INTR
x86 hardware interrupt context.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ X86_FastCall
'fast' analog of X86_StdCall.
@ BasicBlock
Various leaf nodes.
@ MO_GOTPCREL
MO_GOTPCREL - On a symbol operand this indicates that the immediate is offset to the GOT entry for th...
unsigned getMOVriOpcode(bool Use64BitReg, int64_t Imm)
Return a MOVri opcode for materializing Imm into a 32- or 64-bit GPR.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0, bool mem=true)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr RegState getDeadRegState(bool B)
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
static bool isFuncletReturnInstr(const MachineInstr &MI)
auto reverse(ContainerTy &&C)
@ Always
Always set the bit.
@ Never
Never set the bit.
@ DeploymentBased
Determine whether to set the bit statically or dynamically based on the deployment target.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr RegState getDefRegState(bool B)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool requireWinX64UnwindV3(const MachineFunction &MF)
Returns true when MF must use Windows x64 Unwind V3: the module is in V3 mode, or the function needs ...
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
IterT skipDebugInstructionsBackward(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It until it points to a non-debug instruction or to Begin and return the resulting iterator...
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
@ DwarfCFI
DWARF-like instruction based exceptions.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
constexpr RegState getUndefRegState(bool B)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
static const MachineInstrBuilder & addRegOffset(const MachineInstrBuilder &MIB, Register Reg, int Offset)
addRegOffset - This function is used to add a memory reference of the form [Reg + Offset],...
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Pair of physical register and lane mask.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
union llvm::TargetFrameLowering::DwarfFrameBase::@004076321055032247336074224075335064105264310375 Location
enum llvm::TargetFrameLowering::DwarfFrameBase::FrameBaseKind Kind
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
SmallVector< WinEHHandlerType, 1 > HandlerArray