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;
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;
422 MI->getOperand(3).setIsDead();
427template <
typename FoundT,
typename CalcT>
430 FoundT FoundStackAdjust,
432 bool doMergeWithPrevious)
const {
435 return CalcNewOffset(0);
451 if (doMergeWithPrevious && PI !=
MBB.
begin() && PI->isCFIInstruction())
456 unsigned Opc = PI->getOpcode();
458 if ((
Opc == X86::ADD64ri32 ||
Opc == X86::ADD32ri ||
459 Opc == X86::ADD64ri32_NF) &&
460 PI->getOperand(0).getReg() ==
StackPtr) {
462 Offset = PI->getOperand(2).getImm();
463 }
else if ((
Opc == X86::LEA32r ||
Opc == X86::LEA64_32r) &&
464 PI->getOperand(0).getReg() ==
StackPtr &&
465 PI->getOperand(1).getReg() ==
StackPtr &&
466 PI->getOperand(2).getImm() == 1 &&
467 PI->getOperand(3).getReg() == X86::NoRegister &&
468 PI->getOperand(5).getReg() == X86::NoRegister) {
470 Offset = PI->getOperand(4).getImm();
471 }
else if ((
Opc == X86::SUB64ri32 ||
Opc == X86::SUB32ri ||
472 Opc == X86::SUB64ri32_NF) &&
473 PI->getOperand(0).getReg() ==
StackPtr) {
475 Offset = -PI->getOperand(2).getImm();
477 return CalcNewOffset(0);
479 FoundStackAdjust(PI,
Offset);
483 if (doMergeWithPrevious ? (PI ==
MBB.
begin()) : (PI ==
MBB.
end()))
484 return CalcNewOffset(0);
486 PI = doMergeWithPrevious ? std::prev(PI) : std::next(PI);
490 if (PI !=
MBB.
end() && PI->isCFIInstruction()) {
492 MCCFIInstruction CI = CIs[PI->getOperand(0).getCFIIndex()];
497 if (!doMergeWithPrevious)
500 return CalcNewOffset(
Offset);
506 bool doMergeWithPrevious)
const {
507 return mergeSPUpdates(
509 doMergeWithPrevious);
576 CfaExpr.
push_back(dwarf::DW_CFA_expression);
582 STI.isTarget64BitILP32()
585 unsigned DwarfFramePtr = MRI->
getDwarfRegNum(MachineFramePtr,
true);
601 int FI =
MI->getOperand(1).getIndex();
606 STI.isTarget64BitILP32()
609 unsigned DwarfFramePtr = MRI->
getDwarfRegNum(MachineFramePtr,
true);
616 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
626void X86FrameLowering::emitZeroCallUsedRegs(
BitVector RegsToZero,
642 if (!X86::RFP80RegClass.
contains(Reg))
647 unsigned NumFPRegs = 8;
648 if (
MBBI->hasRegisterImplicitUseOperand(X86::ST0))
650 if (
MBBI->hasRegisterImplicitUseOperand(X86::ST1))
653 for (
unsigned i = 0; i != NumFPRegs; ++i)
656 for (
unsigned i = 0; i != NumFPRegs; ++i)
664 if (
TRI->isGeneralPurposeRegister(MF,
Reg)) {
670 for (MCRegister
Reg : GPRsToZero.set_bits())
681 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
683 if (
STI.isTargetWindowsCoreCLR()) {
688 emitStackProbeInline(MF,
MBB,
MBBI,
DL,
false);
691 emitStackProbeCall(MF,
MBB,
MBBI,
DL, InProlog, InstrNum);
696 return STI.isOSWindows() && !
STI.isTargetWin64();
702 return MI.getOpcode() == X86::STACKALLOC_W_PROBING;
704 if (Where != PrologMBB.
end()) {
706 emitStackProbeInline(MF, PrologMBB, Where,
DL,
true);
707 Where->eraseFromParent();
715 bool InProlog)
const {
718 emitStackProbeInlineWindowsCoreCLR64(MF,
MBB,
MBBI,
DL, InProlog);
720 emitStackProbeInlineGeneric(MF,
MBB,
MBBI,
DL, InProlog);
723void X86FrameLowering::emitStackProbeInlineGeneric(
732 "different expansion expected for CoreCLR 64 bit");
734 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
735 uint64_t ProbeChunk = StackProbeSize * 8;
738 TRI->hasStackRealignment(MF) ? calculateMaxStackAlign(MF) : 0;
743 if (
Offset > ProbeChunk) {
745 MaxAlign % StackProbeSize);
748 MaxAlign % StackProbeSize);
752void X86FrameLowering::emitStackProbeInlineGenericBlock(
755 uint64_t AlignOffset)
const {
757 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
760 const X86TargetLowering &TLI = *
STI.getTargetLowering();
761 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
762 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
764 uint64_t CurrentOffset = 0;
766 assert(AlignOffset < StackProbeSize);
769 if (StackProbeSize <
Offset + AlignOffset) {
772 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackAdjustment,
false)
774 if (!HasFP && NeedsDwarfCFI) {
785 NumFrameExtraProbe++;
786 CurrentOffset = StackProbeSize - AlignOffset;
792 while (CurrentOffset + StackProbeSize <
Offset) {
793 BuildStackAdjustment(
MBB,
MBBI,
DL, -StackProbeSize,
false)
796 if (!HasFP && NeedsDwarfCFI) {
806 NumFrameExtraProbe++;
807 CurrentOffset += StackProbeSize;
811 uint64_t ChunkSize =
Offset - CurrentOffset;
816 unsigned Opc =
Is64Bit ? X86::PUSH64r : X86::PUSH32r;
821 BuildStackAdjustment(
MBB,
MBBI,
DL, -ChunkSize,
false)
828void X86FrameLowering::emitStackProbeInlineGenericLoop(
831 uint64_t AlignOffset)
const {
836 "Inline stack probe loop will clobber live EFLAGS.");
838 const bool NeedsDwarfCFI = needsDwarfCFI(MF);
841 const X86TargetLowering &TLI = *
STI.getTargetLowering();
842 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
843 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
846 if (AlignOffset < StackProbeSize) {
848 BuildStackAdjustment(
MBB,
MBBI,
DL, -AlignOffset,
false)
856 NumFrameExtraProbe++;
869 MF.
insert(MBBIter, testMBB);
870 MF.
insert(MBBIter, tailMBB);
910 if (!HasFP && NeedsDwarfCFI) {
913 const Register DwarfFinalStackProbed =
914 STI.isTarget64BitILP32()
920 nullptr,
TRI->getDwarfRegNum(DwarfFinalStackProbed,
true)));
927 BuildStackAdjustment(*testMBB, testMBB->
end(),
DL, -StackProbeSize,
958 const uint64_t TailOffset =
Offset % StackProbeSize;
961 BuildStackAdjustment(*tailMBB, TailMBBIter,
DL, -TailOffset,
967 if (!HasFP && NeedsDwarfCFI) {
971 STI.isTarget64BitILP32()
977 nullptr,
TRI->getDwarfRegNum(DwarfStackPtr,
true)));
984void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
988 assert(
STI.is64Bit() &&
"different expansion needed for 32 bit");
989 assert(
STI.isTargetWindowsCoreCLR() &&
"custom expansion expects CoreCLR");
990 const TargetInstrInfo &
TII = *
STI.getInstrInfo();
995 "Inline stack probe loop will clobber live EFLAGS.");
1030 MF.
insert(MBBIter, RoundMBB);
1031 MF.
insert(MBBIter, LoopMBB);
1032 MF.
insert(MBBIter, ContinueMBB);
1040 const int64_t ThreadEnvironmentStackLimit = 0x10;
1042 const int64_t PageMask = ~(
PageSize - 1);
1060 int64_t RCXShadowSlot = 0;
1061 int64_t RDXShadowSlot = 0;
1068 X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
1077 int64_t InitSlot = 8 + CalleeSaveSize + (
HasFP ? 8 : 0);
1081 RCXShadowSlot = InitSlot;
1083 RDXShadowSlot = InitSlot;
1084 if (IsRDXLiveIn && IsRCXLiveIn)
1125 .
addImm(ThreadEnvironmentStackLimit)
1136 BuildMI(RoundMBB,
DL,
TII.get(X86::AND64ri32), RoundedReg)
1181 TII.get(X86::MOV64rm), X86::RCX),
1182 X86::RSP,
false, RCXShadowSlot);
1185 TII.get(X86::MOV64rm), X86::RDX),
1186 X86::RSP,
false, RDXShadowSlot);
1191 BuildMI(*ContinueMBB, ContinueMBBI,
DL,
TII.get(X86::SUB64rr), X86::RSP)
1203 LivePhysRegs LiveRegs;
1209 for (++BeforeMBBI; BeforeMBBI !=
MBB.
end(); ++BeforeMBBI) {
1212 for (MachineInstr &
MI : *RoundMBB) {
1215 for (MachineInstr &
MI : *LoopMBB) {
1218 for (MachineInstr &
MI :
1225void X86FrameLowering::emitStackProbeCall(
1228 std::optional<MachineFunction::DebugInstrOperandPair> InstrNum)
const {
1232 if (
Is64Bit && IsLargeCodeModel &&
STI.useIndirectThunkCalls())
1234 "code model and indirect thunks not yet implemented.");
1238 "Stack probe calls will clobber live EFLAGS.");
1242 CallOp = IsLargeCodeModel ? X86::CALL64r : X86::CALL64pcrel32;
1244 CallOp = X86::CALLpcrel32;
1246 StringRef
Symbol =
STI.getTargetLowering()->getStackProbeSymbolName(MF);
1248 MachineInstrBuilder CI;
1272 MachineInstr *ModInst = CI;
1273 if (
STI.isTargetWin64() || !
STI.isOSWindows()) {
1290 if (
STI.isTargetWin64() || !
STI.isOSWindows()) {
1305 for (++ExpansionMBBI; ExpansionMBBI !=
MBBI; ++ExpansionMBBI)
1313 const uint64_t Win64MaxSEHOffset = 128;
1314 uint64_t SEHFrameOffset = std::min(SPAdjust, Win64MaxSEHOffset);
1316 return SEHFrameOffset & -16;
1324X86FrameLowering::calculateMaxStackAlign(
const MachineFunction &MF)
const {
1331 MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign;
1338 MaxAlign = (MaxAlign > 16) ? MaxAlign :
Align(16);
1340 MaxAlign =
Align(16);
1342 return MaxAlign.
value();
1348 uint64_t MaxAlign)
const {
1349 uint64_t Val = -MaxAlign;
1354 const X86TargetLowering &TLI = *
STI.getTargetLowering();
1355 const uint64_t StackProbeSize = TLI.getStackProbeSize(MF);
1356 const bool EmitInlineStackProbe = TLI.hasInlineStackProbe(MF);
1361 if (
Reg ==
StackPtr && EmitInlineStackProbe && MaxAlign >= StackProbeSize) {
1363 NumFrameLoopProbe++;
1364 MachineBasicBlock *entryMBB =
1366 MachineBasicBlock *headMBB =
1368 MachineBasicBlock *bodyMBB =
1370 MachineBasicBlock *footMBB =
1374 MF.
insert(MBBIter, entryMBB);
1375 MF.
insert(MBBIter, headMBB);
1376 MF.
insert(MBBIter, bodyMBB);
1377 MF.
insert(MBBIter, footMBB);
1378 const unsigned MovMIOpc =
Is64Bit ? X86::MOV64mi32 : X86::MOV32mi;
1387 BuildMI(entryMBB,
DL,
TII.get(TargetOpcode::COPY), FinalStackProbed)
1391 BuildMI(entryMBB,
DL,
TII.get(AndOp), FinalStackProbed)
1392 .
addReg(FinalStackProbed)
1397 MI->getOperand(3).setIsDead();
1401 .
addReg(FinalStackProbed)
1424 .
addReg(FinalStackProbed)
1454 .
addReg(FinalStackProbed)
1470 .
addReg(FinalStackProbed)
1489 MI->getOperand(3).setIsDead();
1497 "MF used frame lowering for wrong subtarget");
1506bool X86FrameLowering::isWin64Prologue(
const MachineFunction &MF)
const {
1510bool X86FrameLowering::needsDwarfCFI(
const MachineFunction &MF)
const {
1517 case X86::REPNE_PREFIX:
1518 case X86::REP_MOVSB_32:
1519 case X86::REP_MOVSB_64:
1520 case X86::REP_MOVSD_32:
1521 case X86::REP_MOVSD_64:
1522 case X86::REP_MOVSQ_32:
1523 case X86::REP_MOVSQ_64:
1524 case X86::REP_MOVSW_32:
1525 case X86::REP_MOVSW_64:
1526 case X86::REP_PREFIX:
1527 case X86::REP_STOSB_32:
1528 case X86::REP_STOSB_64:
1529 case X86::REP_STOSD_32:
1530 case X86::REP_STOSD_64:
1531 case X86::REP_STOSQ_32:
1532 case X86::REP_STOSQ_64:
1533 case X86::REP_STOSW_32:
1534 case X86::REP_STOSW_64:
1630 "MF used frame lowering for wrong subtarget");
1635 uint64_t MaxAlign = calculateMaxStackAlign(MF);
1637 bool IsFunclet =
MBB.isEHFuncletEntry();
1641 bool FnHasClrFunclet =
1643 bool IsClrFunclet = IsFunclet && FnHasClrFunclet;
1644 bool HasFP =
hasFP(MF);
1645 bool IsWin64Prologue = isWin64Prologue(MF);
1648 bool NeedsWinFPO = !IsFunclet &&
STI.isTargetWin32() &&
1650 bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO;
1651 bool NeedsDwarfCFI = needsDwarfCFI(MF);
1658 bool HasWinCFI =
false;
1667 auto EmitSEHBefore = [&](
auto EmitFn) {
1668 if (NeedsWinCFI && IsWin64UnwindV3) {
1673 auto EmitSEHAfter = [&](
auto EmitFn) {
1674 if (NeedsWinCFI && !IsWin64UnwindV3) {
1689 ArgBaseReg =
MI->getOperand(0).getReg();
1702 if (NeedsDwarfCFI) {
1704 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(ArgBaseReg,
true);
1723 if (TailCallArgReserveSize && IsWin64Prologue)
1726 const bool EmitStackProbeCall =
1727 STI.getTargetLowering()->hasStackProbeSymbol(MF);
1728 unsigned StackProbeSize =
STI.getTargetLowering()->getStackProbeSize(MF);
1733 if (
STI.swiftAsyncContextIsDynamicallySet()) {
1743 .
addUse(X86::NoRegister);
1751 "win64 prologue does not set the bit 60 in the saved frame pointer");
1793 !EmitStackProbeCall &&
1801 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
1808 if (TailCallArgReserveSize != 0) {
1809 BuildStackAdjustment(
MBB,
MBBI,
DL, -(
int)TailCallArgReserveSize,
1838 if (IsWin64Prologue && IsFunclet && !IsClrFunclet) {
1846 MBB.addLiveIn(Establisher);
1858 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
1859 NumBytes =
alignTo(NumBytes, MaxAlign);
1862 auto EmitSEHPushFramePtr = [&]() {
1867 EmitSEHBefore(EmitSEHPushFramePtr);
1872 EmitSEHAfter(EmitSEHPushFramePtr);
1874 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1880 nullptr, -2 * stackGrowth + (
int)TailCallArgReserveSize),
1884 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1888 (
int)TailCallArgReserveSize),
1894 assert(!IsWin64Prologue &&
1895 "win64 prologue does not store async context right below rbp");
1901 auto EmitSEHPushR14 = [&]() {
1906 EmitSEHBefore(EmitSEHPushR14);
1907 if (Attrs.hasAttrSomewhere(Attribute::SwiftAsync)) {
1910 MBB.addLiveIn(X86::R14);
1923 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1930 EmitSEHAfter(EmitSEHPushR14);
1941 if (NeedsDwarfCFI && !ArgBaseReg.
isValid()) {
1942 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1946 (
int)TailCallArgReserveSize),
1956 if (!IsWin64Prologue && !IsFunclet) {
1965 if (NeedsDwarfCFI) {
1968 CfaExpr.
push_back(dwarf::DW_CFA_expression);
1970 unsigned DwarfReg =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1982 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
1994 assert(!IsWin64UnwindV3);
2004 assert(!IsFunclet &&
"funclets without FPs not yet implemented");
2012 if (HasFP &&
TRI->hasStackRealignment(MF))
2020 unsigned ParentFrameNumBytes = NumBytes;
2022 NumBytes = getWinEHFuncletFrameSize(MF);
2025 bool PushedRegs =
false;
2031 unsigned Opc =
MBBI->getOpcode();
2032 return Opc == X86::PUSH32r ||
Opc == X86::PUSH64r ||
Opc == X86::PUSHP64r ||
2033 Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
2036 while (IsCSPush(
MBBI)) {
2040 unsigned Opc = LastCSPush->getOpcode();
2041 bool IsPush2 =
Opc == X86::PUSH2 ||
Opc == X86::PUSH2P;
2044 EmitSEHBefore([&]() {
2048 .
addImm(LastCSPush->getOperand(1).getReg())
2058 if (!HasFP && NeedsDwarfCFI) {
2073 EmitSEHAfter([&]() {
2079 .
addImm(LastCSPush->getOperand(1).getReg())
2087 if (!IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF) &&
2089 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2090 auto EmitSEHStackAlign = [&]() {
2095 EmitSEHBefore(EmitSEHStackAlign);
2097 EmitSEHAfter(EmitSEHStackAlign);
2103 NumBytes = mergeSPUpdates(
2117 uint64_t AlignedNumBytes = NumBytes;
2118 if (IsWin64Prologue && !IsFunclet &&
TRI->hasStackRealignment(MF))
2119 AlignedNumBytes =
alignTo(AlignedNumBytes, MaxAlign);
2121 auto EmitSEHStackAlloc = [&]() {
2127 EmitSEHBefore(EmitSEHStackAlloc);
2129 if (AlignedNumBytes >= StackProbeSize && EmitStackProbeCall) {
2131 "The Red Zone is not accounted for in stack probes");
2153 int64_t
Alloc = isEAXAlive ? NumBytes - 8 : NumBytes;
2162 .
addImm(isEAXAlive ? NumBytes - 4 : NumBytes)
2181 }
else if (NumBytes) {
2186 EmitSEHAfter(EmitSEHStackAlloc);
2188 int SEHFrameOffset = 0;
2196 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2198 MBB.addLiveIn(Establisher);
2200 Establisher,
false, PSPSlotOffset)
2207 false, PSPSlotOffset)
2214 SPOrEstablisher = Establisher;
2219 if (IsWin64Prologue && HasFP) {
2226 if (NeedsWinCFI && !IsFunclet) {
2227 assert(!NeedsWinFPO &&
"this setframe incompatible with FPO data");
2230 if (
TRI->hasBasePointer(MF))
2238 auto EmitSEHSetFrame = [&]() {
2246 EmitSEHBefore(EmitSEHSetFrame);
2250 SPOrEstablisher,
false, SEHFrameOffset);
2253 .
addReg(SPOrEstablisher);
2256 EmitSEHAfter(EmitSEHSetFrame);
2257 }
else if (IsFunclet &&
STI.is32Bit()) {
2262 if (!
MBB.isCleanupFuncletEntry()) {
2279 if (
Register Reg =
TII.isStoreToStackSlot(FrameInstr, FI)) {
2280 if (X86::FR64RegClass.
contains(Reg)) {
2283 if (IsWin64Prologue && IsFunclet)
2290 assert(!NeedsWinFPO &&
"SEH_SaveXMM incompatible with FPO data");
2291 auto EmitSEHSaveXMM = [&]() {
2297 EmitSEHBefore(EmitSEHSaveXMM);
2299 EmitSEHAfter(EmitSEHSaveXMM);
2307 if (NeedsWinCFI && HasWinCFI) {
2312 if (FnHasClrFunclet && !IsFunclet) {
2316 unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF);
2330 if (IsWin64Prologue &&
TRI->hasStackRealignment(MF)) {
2331 assert(HasFP &&
"There should be a frame pointer if stack is realigned.");
2332 BuildStackAlignAND(
MBB,
MBBI,
DL, SPOrEstablisher, MaxAlign);
2336 if (IsFunclet &&
STI.is32Bit())
2343 if (
TRI->hasBasePointer(MF)) {
2369 assert(UsedReg == BasePtr);
2378 int FI =
MI->getOperand(1).getIndex();
2379 unsigned MOVmr =
Is64Bit ? X86::MOV64mr : X86::MOV32mr;
2386 if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) {
2388 if (!HasFP && NumBytes) {
2414 bool NeedsCLD =
false;
2428 if (
MI.isInlineAsm()) {
2460 switch (
MI.getOpcode()) {
2462 case X86::CLEANUPRET:
2484X86FrameLowering::getPSPSlotOffsetFromSP(
const MachineFunction &MF)
const {
2491 return static_cast<unsigned>(
Offset);
2495X86FrameLowering::getWinEHFuncletFrameSize(
const MachineFunction &MF)
const {
2496 const X86MachineFunctionInfo *X86FI = MF.
getInfo<X86MachineFunctionInfo>();
2502 WinEHXMMSlotInfo.
size() *
TRI->getSpillSize(X86::VR128RegClass);
2511 UsedSize = getPSPSlotOffsetFromSP(MF) +
SlotSize;
2522 return FrameSizeMinusRBP + XMMSize - CSSize;
2526 return Opc == X86::TCRETURNri ||
Opc == X86::TCRETURN_WIN64ri ||
2527 Opc == X86::TCRETURN_HIPE32ri ||
Opc == X86::TCRETURNdi ||
2528 Opc == X86::TCRETURNmi ||
Opc == X86::TCRETURNri64 ||
2529 Opc == X86::TCRETURNri64_ImpCall ||
Opc == X86::TCRETURNdi64 ||
2530 Opc == X86::TCRETURNmi64 ||
Opc == X86::TCRETURN_WINmi64;
2541 DL =
MBBI->getDebugLoc();
2543 const bool Is64BitILP32 =
STI.isTarget64BitILP32();
2549 bool NeedsWin64CFI =
2553 bool IsWin64UnwindV3 =
2559 uint64_t MaxAlign = calculateMaxStackAlign(MF);
2562 bool HasFP =
hasFP(MF);
2565 bool NeedsDwarfCFI = (!MF.
getTarget().getTargetTriple().isOSDarwin() &&
2572 unsigned Opc = X86::LEA32r;
2574 ArgBaseReg =
MI->getOperand(0).getReg();
2575 if (
STI.is64Bit()) {
2577 StackReg = X86::RSP;
2588 if (NeedsDwarfCFI) {
2589 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(StackReg,
true);
2599 assert(HasFP &&
"EH funclets without FP not yet implemented");
2600 NumBytes = getWinEHFuncletFrameSize(MF);
2604 NumBytes = FrameSize - CSSize - TailCallArgReserveSize;
2608 if (
TRI->hasStackRealignment(MF) && !IsWin64Prologue)
2609 NumBytes =
alignTo(FrameSize, MaxAlign);
2611 NumBytes = StackSize - CSSize - TailCallArgReserveSize;
2613 uint64_t SEHStackAllocAmt = NumBytes;
2615 unsigned SEHFrameOffset = 0;
2616 if (IsWin64Prologue && HasFP)
2628 if (IsWin64UnwindV3)
2646 if (NeedsDwarfCFI) {
2648 unsigned DwarfStackPtr =
2649 TRI->getDwarfRegNum(
Is64Bit ? X86::RSP : X86::ESP,
true);
2654 if (!
MBB.succ_empty() && !
MBB.isReturnBlock()) {
2655 unsigned DwarfFramePtr =
TRI->getDwarfRegNum(MachineFramePtr,
true);
2670 unsigned Opc = PI->getOpcode();
2672 if (
Opc != X86::DBG_VALUE && !PI->isTerminator()) {
2674 (
Opc != X86::POP32r &&
Opc != X86::POP64r &&
Opc != X86::BTR64ri8 &&
2675 Opc != X86::ADD64ri32 &&
Opc != X86::POPP64r &&
Opc != X86::POP2 &&
2676 Opc != X86::POP2P &&
Opc != X86::LEA64r &&
Opc != X86::SEH_PushReg &&
2677 Opc != X86::SEH_Push2Regs &&
Opc != X86::SEH_StackAlloc &&
2678 Opc != X86::ADD64ri32_NF))
2688 int FI =
MI->getOperand(1).getIndex();
2689 unsigned MOVrm =
Is64Bit ? X86::MOV64rm : X86::MOV32rm;
2696 if (IsFunclet && Terminator->getOpcode() == X86::CATCHRET)
2697 emitCatchRetReturnValue(
MBB, FirstCSPop, &*Terminator);
2700 DL =
MBBI->getDebugLoc();
2706 if (IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI()) {
2709 auto EpilogStart =
MBBI;
2712 while (ScanIt !=
MBB.begin()) {
2713 auto PI = std::prev(ScanIt);
2716 TII.isLoadFromStackSlot(*PI, FI)) {
2717 Register Reg = PI->getOperand(0).getReg();
2718 if (X86::FR64RegClass.
contains(Reg)) {
2731 EpilogStart = std::prev(PI);
2732 ScanIt = EpilogStart;
2750 if (
TRI->hasStackRealignment(MF))
2753 IsWin64Prologue ? SEHStackAllocAmt - SEHFrameOffset : -CSSize;
2765 if (IsWin64UnwindV3) {
2770 if (SEHStackAllocAmt)
2772 .
addImm(SEHStackAllocAmt)
2775 if (LEAAmount != 0) {
2785 }
else if (NumBytes) {
2787 if (IsWin64UnwindV3)
2792 if (!HasFP && NeedsDwarfCFI) {
2796 nullptr, CSSize + TailCallArgReserveSize +
SlotSize),
2803 if (!IsWin64UnwindV3 && NeedsWin64CFI && MF.
hasWinCFI())
2806 if (!HasFP && NeedsDwarfCFI) {
2813 unsigned Opc = PI->getOpcode();
2815 if (
Opc == X86::POP32r ||
Opc == X86::POP64r ||
Opc == X86::POPP64r ||
2816 Opc == X86::POP2 ||
Opc == X86::POP2P) {
2820 if (
Opc == X86::POP2 ||
Opc == X86::POP2P)
2832 if (NeedsDwarfCFI && !
MBB.succ_empty())
2838 assert(Delta <= 0 &&
"TCDelta should never be positive");
2863 if (
TRI->hasBasePointer(MF))
2864 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getBaseRegister();
2865 else if (
TRI->hasStackRealignment(MF))
2866 FrameReg = IsFixed ?
TRI->getFramePtr() :
TRI->getStackRegister();
2868 FrameReg =
TRI->getFrameRegister(MF);
2879 int64_t FPDelta = 0;
2890 if (IsWin64Prologue) {
2899 uint64_t NumBytes = FrameSize - CSSize;
2909 FPDelta = FrameSize - SEHFrameOffset;
2911 "FPDelta isn't aligned per the Win64 ABI!");
2914 if (FrameReg ==
TRI->getFramePtr()) {
2923 if (TailCallReturnAddrDelta < 0)
2924 Offset -= TailCallReturnAddrDelta;
2932 if (
TRI->hasStackRealignment(MF) ||
TRI->hasBasePointer(MF))
2942 const auto it = WinEHXMMSlotInfo.find(FI);
2944 if (it == WinEHXMMSlotInfo.end())
2947 FrameReg =
TRI->getStackRegister();
2955 int Adjustment)
const {
2957 FrameReg =
TRI->getStackRegister();
2965 bool IgnoreSPUpdates)
const {
3004 !
STI.isTargetWin64())
3015 "we don't handle this case!");
3047 std::vector<CalleeSavedInfo> &CSI)
const {
3051 unsigned CalleeSavedFrameSize = 0;
3052 unsigned XMMCalleeSavedFrameSize = 0;
3058 if (TailCallReturnAddrDelta < 0) {
3069 TailCallReturnAddrDelta -
SlotSize,
true);
3073 if (this->TRI->hasBasePointer(MF)) {
3082 bool IsFPRemovedFromCSI =
false;
3100 for (
unsigned i = 0; i < CSI.size(); ++i) {
3101 if (
TRI->regsOverlap(CSI[i].getReg(),
FPReg)) {
3102 CSI.erase(CSI.begin() + i);
3103 IsFPRemovedFromCSI =
true;
3119 unsigned NumRegsForPush2 = 0;
3122 return X86::GR64RegClass.contains(
I.getReg());
3124 bool UsePush2Pop2 = !IsFPRemovedFromCSI ? NumCSGPR > 2 : NumCSGPR > 1;
3127 ?
alignDown(IsFPRemovedFromCSI ? NumCSGPR : NumCSGPR - 1, 2)
3141 (SpillSlotOffset % 16 == 0 ||
3163 "Expect even candidates for push2/pop2");
3165 ++NumFunctionUsingPush2Pop2;
3176 unsigned Size =
TRI->getSpillSize(*RC);
3177 Align Alignment =
TRI->getSpillAlign(*RC);
3179 assert(SpillSlotOffset < 0 &&
"SpillSlotOffset should always < 0 on X86");
3180 SpillSlotOffset = -
alignTo(-SpillSlotOffset, Alignment);
3183 SpillSlotOffset -=
Size;
3189 if (X86::VR128RegClass.
contains(Reg)) {
3190 WinEHXMMSlotInfo[
SlotIndex] = XMMCalleeSavedFrameSize;
3191 XMMCalleeSavedFrameSize +=
Size;
3205 if (
MBB.isEHFuncletEntry() &&
STI.is32Bit() &&
STI.isOSWindows())
3214 auto UpdateLiveInCheckCanKill = [&](
Register Reg) {
3230 auto UpdateLiveInGetKillRegState = [&](
Register Reg) {
3234 for (
auto RI = CSI.
rbegin(), RE = CSI.
rend(); RI != RE; ++RI) {
3242 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3243 .
addReg(Reg2, UpdateLiveInGetKillRegState(Reg2))
3247 .
addReg(Reg, UpdateLiveInGetKillRegState(Reg))
3253 unsigned Opc =
STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r;
3254 Register BaseReg = this->TRI->getBaseRegister();
3283 MBB.getParent()->getFunction().getPersonalityFn())) &&
3284 "SEH should not use CATCHRET");
3289 if (
STI.is64Bit()) {
3321 if (
MI->getOpcode() == X86::CATCHRET) {
3334 bool NeedsWin64CFI =
3351 if (IsWin64UnwindV3)
3353 .
addImm(this->TRI->getBaseRegister())
3355 unsigned Opc =
STI.is64Bit() ? X86::POP64r : X86::POP32r;
3356 Register BaseReg = this->TRI->getBaseRegister();
3362 for (
auto I = CSI.
begin(), E = CSI.
end();
I != E; ++
I) {
3369 if (IsWin64UnwindV3) {
3379 if (IsWin64UnwindV3)
3397 if (
TRI->hasBasePointer(MF)) {
3399 if (
STI.isTarget64BitILP32())
3401 SavedRegs.
set(BasePtr);
3403 if (
STI.hasUserReservedRegisters()) {
3404 for (
int Reg = SavedRegs.
find_first(); Reg != -1;
3406 if (
STI.isRegisterReservedByUser(Reg)) {
3407 SavedRegs.
reset(Reg);
3417 if (
I->hasNestAttr() && !
I->use_empty())
3434 return Primary ? X86::R14 : X86::R13;
3436 return Primary ? X86::EBX : X86::EDI;
3441 return Primary ? X86::R11 : X86::R12;
3443 return Primary ? X86::R11D : X86::R12D;
3453 "nested function.");
3454 return Primary ? X86::EAX : X86::ECX;
3457 return Primary ? X86::EDX : X86::EAX;
3458 return Primary ? X86::ECX : X86::EAX;
3469 unsigned TlsReg, TlsOffset;
3474 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3478 "Scratch register is live-in");
3482 if (!
STI.isTargetLinux() && !
STI.isTargetDarwin() && !
STI.isTargetWin32() &&
3483 !
STI.isTargetWin64() && !
STI.isTargetFreeBSD() &&
3484 !
STI.isTargetDragonFly())
3498 bool IsNested =
false;
3507 for (
const auto &LI : PrologueMBB.
liveins()) {
3524 if (
STI.isTargetLinux()) {
3526 TlsOffset =
IsLP64 ? 0x70 : 0x40;
3527 }
else if (
STI.isTargetDarwin()) {
3529 TlsOffset = 0x60 + 90 * 8;
3530 }
else if (
STI.isTargetWin64()) {
3533 }
else if (
STI.isTargetFreeBSD()) {
3536 }
else if (
STI.isTargetDragonFly()) {
3543 if (CompareStackPointer)
3544 ScratchReg =
IsLP64 ? X86::RSP : X86::ESP;
3562 if (
STI.isTargetLinux()) {
3565 }
else if (
STI.isTargetDarwin()) {
3567 TlsOffset = 0x48 + 90 * 4;
3568 }
else if (
STI.isTargetWin32()) {
3571 }
else if (
STI.isTargetDragonFly()) {
3574 }
else if (
STI.isTargetFreeBSD()) {
3580 if (CompareStackPointer)
3581 ScratchReg = X86::ESP;
3583 BuildMI(checkMBB,
DL,
TII.get(X86::LEA32r), ScratchReg)
3590 if (
STI.isTargetLinux() ||
STI.isTargetWin32() ||
STI.isTargetWin64() ||
3591 STI.isTargetDragonFly()) {
3599 }
else if (
STI.isTargetDarwin()) {
3602 unsigned ScratchReg2;
3604 if (CompareStackPointer) {
3607 SaveScratch2 =
false;
3619 "Scratch register is live-in and not saved");
3625 BuildMI(checkMBB,
DL,
TII.get(X86::MOV32ri), ScratchReg2)
3636 BuildMI(checkMBB,
DL,
TII.get(X86::POP32r), ScratchReg2);
3652 const unsigned RegAX =
IsLP64 ? X86::RAX : X86::EAX;
3653 const unsigned Reg10 =
IsLP64 ? X86::R10 : X86::R10D;
3654 const unsigned Reg11 =
IsLP64 ? X86::R11 : X86::R11D;
3655 const unsigned MOVrr =
IsLP64 ? X86::MOV64rr : X86::MOV32rr;
3690 if (
STI.useIndirectThunkCalls())
3692 "code model and thunks not yet implemented.");
3709 BuildMI(allocMBB,
DL,
TII.get(X86::MORESTACK_RET_RESTORE_R10));
3718#ifdef EXPENSIVE_CHECKS
3729 for (
int i = 0, e = HiPELiteralsMD->
getNumOperands(); i != e; ++i) {
3731 if (
Node->getNumOperands() != 2)
3735 if (!NodeName || !NodeVal)
3738 if (ValConst && NodeName->
getString() == LiteralName) {
3744 " required but not provided");
3755 return MI.isMetaInstruction();
3781 assert(&(*MF.
begin()) == &PrologueMBB &&
"Shrink-wrapping not supported yet");
3786 if (!HiPELiteralsMD)
3788 "Can't generate HiPE prologue without runtime parameters");
3790 HiPELiteralsMD,
Is64Bit ?
"AMD64_LEAF_WORDS" :
"X86_LEAF_WORDS");
3791 const unsigned CCRegisteredArgs =
Is64Bit ? 6 : 5;
3792 const unsigned Guaranteed = HipeLeafWords *
SlotSize;
3799 "HiPE prologue is only supported on Linux operating systems.");
3809 unsigned MoreStackForCalls = 0;
3811 for (
auto &
MBB : MF) {
3812 for (
auto &
MI :
MBB) {
3832 if (
F->getName().contains(
"erlang.") ||
F->getName().contains(
"bif_") ||
3836 unsigned CalleeStkArity =
F->arg_size() > CCRegisteredArgs
3837 ?
F->arg_size() - CCRegisteredArgs
3839 if (HipeLeafWords - 1 > CalleeStkArity)
3841 std::max(MoreStackForCalls,
3842 (HipeLeafWords - 1 - CalleeStkArity) *
SlotSize);
3845 MaxStack += MoreStackForCalls;
3850 if (MaxStack > Guaranteed) {
3854 for (
const auto &LI : PrologueMBB.
liveins()) {
3862 unsigned ScratchReg,
SPReg, PReg, SPLimitOffset;
3863 unsigned LEAop, CMPop, CALLop;
3868 LEAop = X86::LEA64r;
3869 CMPop = X86::CMP64rm;
3870 CALLop = X86::CALL64pcrel32;
3874 LEAop = X86::LEA32r;
3875 CMPop = X86::CMP32rm;
3876 CALLop = X86::CALLpcrel32;
3881 "HiPE prologue scratch register is live-in");
3888 PReg,
false, SPLimitOffset);
3898 PReg,
false, SPLimitOffset);
3908#ifdef EXPENSIVE_CHECKS
3925 if (NumPops != 1 && NumPops != 2)
3933 if (!Prev->isCall() || !Prev->getOperand(1).isRegMask())
3937 unsigned FoundRegs = 0;
3943 Is64Bit ? X86::GR64_NOREX_NOSPRegClass : X86::GR32_NOREX_NOSPRegClass;
3945 for (
auto Candidate : RegClass) {
3958 if (MO.isReg() && MO.isDef() &&
3959 TRI->isSuperOrSubRegisterEq(MO.getReg(), Candidate)) {
3968 Regs[FoundRegs++] = Candidate;
3969 if (FoundRegs == (
unsigned)NumPops)
3977 while (FoundRegs < (
unsigned)NumPops)
3978 Regs[FoundRegs++] = Regs[0];
3980 for (
int i = 0; i < NumPops; ++i)
3991 unsigned Opcode =
I->getOpcode();
3992 bool isDestroy = Opcode ==
TII.getCallFrameDestroyOpcode();
3995 uint64_t InternalAmt = (isDestroy || Amount) ?
TII.getFrameAdjustment(*
I) : 0;
4005 if (!reserveCallFrame) {
4026 bool HasDwarfEHHandlers = !WindowsCFI && !MF.
getLandingPads().empty();
4028 if (HasDwarfEHHandlers && !isDestroy &&
4038 Amount -= InternalAmt;
4048 int64_t StackAdjustment = isDestroy ? Amount : -Amount;
4049 int64_t CfaAdjustment = StackAdjustment;
4051 if (StackAdjustment) {
4060 auto CalcNewOffset = [&StackAdjustment](int64_t
Offset) {
4061 return StackAdjustment +
Offset;
4064 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
true);
4066 mergeSPUpdates(
MBB, InsertPos, CalcCfaAdjust, CalcNewOffset,
false);
4068 if (StackAdjustment) {
4069 if (!(
F.hasMinSize() &&
4070 adjustStackWithPops(
MBB, InsertPos,
DL, StackAdjustment)))
4071 BuildStackAdjustment(
MBB, InsertPos,
DL, StackAdjustment,
4097 while (CI !=
B && !std::prev(CI)->isCall())
4099 BuildStackAdjustment(
MBB, CI,
DL, -InternalAmt,
false);
4106 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4108 if (!
MBB.isLiveIn(X86::EFLAGS))
4115 if (TLI.hasInlineStackProbe(MF) || TLI.hasStackProbeSymbol(MF))
4123 assert(
MBB.getParent() &&
"Block is not attached to a function!");
4129 if (
STI.isTargetWin64() && !
MBB.succ_empty() && !
MBB.isReturnBlock())
4151 bool CompactUnwind =
4167 assert(
STI.isTargetWindowsMSVC() &&
"funclets only supported in MSVC env");
4168 assert(
STI.isTargetWin32() &&
"EBP/ESI restoration only required on win32");
4170 "restoring EBP/ESI on non-32-bit target");
4182 int EHRegSize = MFI.getObjectSize(FI);
4187 X86::EBP,
true, -EHRegSize)
4193 int EndOffset = -EHRegOffset - EHRegSize;
4206 "end of registration object above normal EBP position!");
4207 }
else if (UsedReg == BasePtr) {
4217 assert(UsedReg == BasePtr);
4228 return TRI->getSlotSize();
4243 FrameBase.
Kind = DwarfFrameBase::CFA;
4249 return DwarfFrameBase{DwarfFrameBase::Register, {FrameRegister}};
4254struct X86FrameSortingObject {
4255 bool IsValid =
false;
4256 unsigned ObjectIndex = 0;
4257 unsigned ObjectSize = 0;
4259 unsigned ObjectNumUses = 0;
4275struct X86FrameSortingComparator {
4276 inline bool operator()(
const X86FrameSortingObject &
A,
4277 const X86FrameSortingObject &
B)
const {
4278 uint64_t DensityAScaled, DensityBScaled;
4298 DensityAScaled =
static_cast<uint64_t>(
A.ObjectNumUses) *
4300 DensityBScaled =
static_cast<uint64_t>(
B.ObjectNumUses) *
4311 if (DensityAScaled == DensityBScaled)
4312 return A.ObjectAlignment <
B.ObjectAlignment;
4314 return DensityAScaled < DensityBScaled;
4328 if (ObjectsToAllocate.
empty())
4340 for (
auto &Obj : ObjectsToAllocate) {
4341 SortingObjects[Obj].IsValid =
true;
4342 SortingObjects[Obj].ObjectIndex = Obj;
4346 if (ObjectSize == 0)
4348 SortingObjects[Obj].ObjectSize = 4;
4350 SortingObjects[Obj].ObjectSize = ObjectSize;
4354 for (
auto &
MBB : MF) {
4355 for (
auto &
MI :
MBB) {
4356 if (
MI.isDebugInstr())
4362 int Index = MO.getIndex();
4366 SortingObjects[Index].IsValid)
4367 SortingObjects[Index].ObjectNumUses++;
4382 for (
auto &Obj : SortingObjects) {
4386 ObjectsToAllocate[i++] = Obj.ObjectIndex;
4390 if (!
TRI->hasStackRealignment(MF) &&
hasFP(MF))
4391 std::reverse(ObjectsToAllocate.
begin(), ObjectsToAllocate.
end());
4403 Offset += getWinEHFuncletFrameSize(MF);
4418 RS->addScavengingFrameIndex(FI);
4431 adjustFrameForMsvcCxxEh(MF);
4435void X86FrameLowering::adjustFrameForMsvcCxxEh(
MachineFunction &MF)
const {
4443 int64_t MinFixedObjOffset = -
SlotSize;
4449 int FrameIndex =
H.CatchObj.FrameIndex;
4450 if ((FrameIndex != INT_MAX) && MFI.
getObjectOffset(FrameIndex) == 0) {
4453 MinFixedObjOffset -= std::abs(MinFixedObjOffset) %
Align;
4461 MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8;
4462 int64_t UnwindHelpOffset = MinFixedObjOffset -
SlotSize;
4469 MachineBasicBlock &
MBB = MF.
front();
4489 MI->eraseFromParent();
4502 bool NeedsRestore =
MBB.isEHPad() && !
MBB.isEHFuncletEntry();
4513 unsigned NumSpilledRegs) {
4515 unsigned AllocSize =
TRI->getSpillSize(*RC) * NumSpilledRegs;
4517 unsigned AlignedSize =
alignTo(AllocSize, StackAlign);
4518 return AlignedSize - AllocSize;
4524 int SPAdjust)
const {
4527 MachineBasicBlock *
MBB = BeforeMI->getParent();
4549 if (
FP.isValid() && needsDwarfCFI(MF)) {
4558 SmallString<64> CfaExpr;
4562 Offset +=
TRI->getSpillSize(*
TRI->getMinimalPhysRegClass(BP));
4565 if (
TII.isFrameSetup(*BeforeMI)) {
4567 BeforeMI = std::next(BeforeMI);
4570 if (
STI.isTarget64BitILP32())
4572 unsigned DwarfStackPtr =
TRI->getDwarfRegNum(
StackPtr,
true);
4573 CfaExpr.
push_back((uint8_t)(dwarf::DW_OP_breg0 + DwarfStackPtr));
4578 CfaExpr.
push_back((uint8_t)dwarf::DW_OP_plus);
4580 SmallString<64> DefCfaExpr;
4581 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
4593 int SPAdjust)
const {
4597 MachineBasicBlock *
MBB = AfterMI->getParent();
4615 if (needsDwarfCFI(MF)) {
4625void X86FrameLowering::saveAndRestoreFPBPUsingSP(
4628 assert(SpillFP || SpillBP);
4632 unsigned NumRegs = 0;
4635 FP =
TRI->getFrameRegister(MF);
4636 if (
STI.isTarget64BitILP32())
4638 RC =
TRI->getMinimalPhysRegClass(
FP);
4642 BP =
TRI->getBaseRegister();
4643 if (
STI.isTarget64BitILP32())
4645 RC =
TRI->getMinimalPhysRegClass(BP);
4650 spillFPBPUsingSP(MF, BeforeMI,
FP, BP, SPAdjust);
4651 restoreFPBPUsingSP(MF, AfterMI,
FP, BP, SPAdjust);
4654bool X86FrameLowering::skipSpillFPBP(
4656 if (
MI->getOpcode() == X86::LCMPXCHG16B_SAVE_RBX) {
4664 while (!(
MI->getOpcode() == TargetOpcode::COPY &&
4665 MI->getOperand(1).getReg() == X86::RBX) &&
4666 !((
Reg =
TII.isStoreToStackSlot(*
MI, FI)) &&
Reg == X86::RBX))
4676 AccessFP = AccessBP =
false;
4678 if (
MI.findRegisterUseOperandIdx(
FP,
TRI,
false) != -1 ||
4679 MI.findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4683 if (
MI.findRegisterUseOperandIdx(BP,
TRI,
false) != -1 ||
4684 MI.findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4687 return AccessFP || AccessBP;
4700 if (!
MBB->hasEHPadSuccessor())
4713void X86FrameLowering::checkInterferedAccess(
4716 bool SpillBP)
const {
4717 if (
DefMI == KillMI)
4719 if (
TRI->hasBasePointer(MF)) {
4730 [](
const MachineOperand &MO) { return MO.isFI(); }))
4732 "Interference usage of base pointer/frame "
4763 FP =
TRI->getFrameRegister(MF);
4764 if (
TRI->hasBasePointer(MF))
4765 BP =
TRI->getBaseRegister();
4780 bool InsideEHLabels =
false;
4781 auto MI =
MBB.rbegin(), ME =
MBB.rend();
4782 auto TermMI =
MBB.getFirstTerminator();
4783 if (TermMI ==
MBB.begin())
4785 MI = *(std::prev(TermMI));
4793 isInvoke(*
MI, InsideEHLabels) || skipSpillFPBP(MF,
MI)) {
4798 if (
MI->getOpcode() == TargetOpcode::EH_LABEL) {
4799 InsideEHLabels = !InsideEHLabels;
4804 bool AccessFP, AccessBP;
4813 bool FPLive =
false, BPLive =
false;
4814 bool SpillFP =
false, SpillBP =
false;
4817 SpillFP |= AccessFP;
4818 SpillBP |= AccessBP;
4821 if (FPLive &&
MI->findRegisterDefOperandIdx(
FP,
TRI,
false,
true) != -1)
4823 if (
FP &&
MI->findRegisterUseOperandIdx(
FP,
TRI,
false) != -1)
4825 if (BPLive &&
MI->findRegisterDefOperandIdx(BP,
TRI,
false,
true) != -1)
4827 if (BP &&
MI->findRegisterUseOperandIdx(BP,
TRI,
false) != -1)
4831 }
while ((
MI != ME) &&
4832 (FPLive || BPLive ||
4836 if (FPLive && !SpillBP)
4841 if (KillMI->isCall() &&
DefMI != ME) {
4842 auto FrameSetup = std::next(
DefMI);
4846 while (FrameSetup != ME && !
TII.isFrameSetup(*FrameSetup) &&
4847 !FrameSetup->isCall())
4851 if (FrameSetup != ME &&
TII.isFrameSetup(*FrameSetup) &&
4852 (
TII.getFrameSize(*FrameSetup) ||
4853 TII.getFrameAdjustment(*FrameSetup))) {
4854 while (!
TII.isFrameInstr(*KillMI))
4862 checkInterferedAccess(MF,
DefMI, KillMI, SpillFP, SpillBP);
4865 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
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 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...
bool usesWindowsCFI() const
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...
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
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 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 the alignment in bytes that this function must be aligned to, which is greater than the defaul...
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.
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.
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
BasicBlockListType::iterator iterator
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
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 & 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
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
SwiftAsyncFramePointerMode SwiftAsyncFramePointer
Control when and how the Swift async frame pointer bit should be set.
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
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)
@ DwarfCFI
DWARF-like instruction based exceptions.
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.
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.
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.
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.
static const MachineInstrBuilder & addRegOffset(const MachineInstrBuilder &MIB, Register Reg, bool isKill, int Offset)
addRegOffset - This function is used to add a memory reference of the form [Reg + Offset],...
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.
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