35 if (CFSize >= ((1 << 8) - 1) * 4 / 2)
70 Amount = (Amount+Align-1)/Align*Align;
74 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
77 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
99 assert(NumBytes >= ArgRegsSaveSize &&
100 "ArgRegsSaveSize is included in NumBytes");
112 NumBytes = (NumBytes + 3) & ~3;
117 unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0;
118 int FramePtrSpillFI = 0;
120 if (ArgRegsSaveSize) {
121 emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -ArgRegsSaveSize,
123 CFAOffset -= ArgRegsSaveSize;
126 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
127 .addCFIIndex(CFIIndex)
132 if (NumBytes - ArgRegsSaveSize != 0) {
133 emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, -(NumBytes - ArgRegsSaveSize),
135 CFAOffset -= NumBytes - ArgRegsSaveSize;
138 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
139 .addCFIIndex(CFIIndex)
145 for (
unsigned i = 0, e = CSI.size();
i != e; ++
i) {
146 unsigned Reg = CSI[
i].getReg();
147 int FI = CSI[
i].getFrameIdx();
164 FramePtrSpillFI = FI;
172 if (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::tPUSH) {
177 unsigned DPRCSOffset = NumBytes - ArgRegsSaveSize - (GPRCS1Size + GPRCS2Size + DPRCSSize);
178 unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
179 unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
180 bool HasFP =
hasFP(MF);
187 NumBytes = DPRCSOffset;
189 int FramePtrOffsetInBlock = 0;
190 unsigned adjustedGPRCS1Size = GPRCS1Size;
191 if (GPRCS1Size > 0 && GPRCS2Size == 0 &&
193 FramePtrOffsetInBlock = NumBytes;
194 adjustedGPRCS1Size += NumBytes;
198 if (adjustedGPRCS1Size) {
199 CFAOffset -= adjustedGPRCS1Size;
202 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
203 .addCFIIndex(CFIIndex)
206 for (std::vector<CalleeSavedInfo>::const_iterator
I = CSI.begin(),
207 E = CSI.end();
I !=
E; ++
I) {
208 unsigned Reg =
I->getReg();
209 int FI =
I->getFrameIdx();
230 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
231 .addCFIIndex(CFIIndex)
239 FramePtrOffsetInBlock +=
242 .addReg(ARM::SP).
addImm(FramePtrOffsetInBlock / 4)
244 if(FramePtrOffsetInBlock) {
245 CFAOffset += FramePtrOffsetInBlock;
248 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
249 .addCFIIndex(CFIIndex)
255 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
256 .addCFIIndex(CFIIndex)
272 while (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::tMOVr)
274 if (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::tPUSH) {
286 for (
auto &
I : CSI) {
287 unsigned Reg =
I.getReg();
288 int FI =
I.getFrameIdx();
297 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
298 .addCFIIndex(CFIIndex)
312 CFAOffset -= NumBytes;
315 BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
316 .addCFIIndex(CFIIndex)
331 if (RegInfo->needsStackRealignment(MF))
355 }
else if (MI.
getOpcode() == ARM::tMOVr) {
358 return ((ARM::tGPRRegClass.
contains(Src) || Src == ARM::LR) &&
377 assert((
unsigned)NumBytes >= ArgRegsSaveSize &&
378 "ArgRegsSaveSize is included in NumBytes");
379 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
380 unsigned FramePtr = RegInfo->getFrameRegister(MF);
383 if (NumBytes - ArgRegsSaveSize != 0)
384 emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, NumBytes - ArgRegsSaveSize);
387 if (MBBI != MBB.
begin()) {
408 "No scratch register to restore SP from FP!");
419 if (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::tBX_RET &&
420 &MBB.
front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) {
429 if (needPopSpecialFixUp(MF)) {
430 bool Done = emitPopSpecialFixUp(MBB,
true);
432 assert(Done &&
"Emission of the special fixup failed!?");
437 if (!needPopSpecialFixUp(*MBB.
getParent()))
441 return emitPopSpecialFixUp(*TmpMBB,
false);
444 bool Thumb1FrameLowering::needPopSpecialFixUp(
const MachineFunction &MF)
const {
452 if (CSI.getReg() == ARM::LR)
475 bool CanRestoreDirectly =
STI.
hasV5TOps() && !ArgRegsSaveSize;
476 if (CanRestoreDirectly) {
477 if (MBBI != MBB.
end() && MBBI->getOpcode() != ARM::tB)
478 CanRestoreDirectly = (MBBI->getOpcode() == ARM::tBX_RET ||
479 MBBI->getOpcode() == ARM::tPOP_RET);
481 auto MBBI_prev = MBBI;
483 assert(MBBI_prev->getOpcode() == ARM::tPOP);
488 CanRestoreDirectly =
false;
492 if (CanRestoreDirectly) {
493 if (!DoIt || MBBI->getOpcode() == ARM::tPOP_RET)
497 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.
get(ARM::tPOP_RET)));
499 for (
auto MO: MBBI->operands())
500 if (MO.isReg() && (MO.isImplicit() || MO.isDef()))
518 for (
unsigned i = 0; CSRegs[
i]; ++
i)
519 UsedRegs.addReg(CSRegs[
i]);
522 if (MBBI != MBB.
end()) {
523 dl = MBBI->getDebugLoc();
524 auto InstUpToMBBI = MBB.
end();
525 while (InstUpToMBBI != MBBI)
528 UsedRegs.stepBackward(*--InstUpToMBBI);
534 unsigned TemporaryReg = 0;
537 assert(PopFriendly.
any() &&
"No allocatable pop-friendly register?!");
542 GPRsNoLRSP |= PopFriendly;
543 GPRsNoLRSP.
reset(ARM::LR);
544 GPRsNoLRSP.
reset(ARM::SP);
561 if (!DoIt && !PopReg && !TemporaryReg)
564 assert((PopReg || TemporaryReg) &&
"Cannot get LR");
567 assert(!PopReg &&
"Unnecessary MOV is about to be inserted");
574 if (MBBI != MBB.
end() && MBBI->getOpcode() == ARM::tPOP_RET) {
579 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII.
get(ARM::tPOP)));
581 for (
auto MO: MBBI->operands())
582 if (MO.isReg() && (MO.isImplicit() || MO.isDef()) &&
585 if (!MO.isImplicit())
596 assert(PopReg &&
"Do not know how to get LR");
600 emitSPUpdate(MBB, MBBI, TII, dl, *RegInfo, ArgRegsSaveSize);
617 template <
unsigned SetSize>
618 static const unsigned *
621 const unsigned *OrderEnd) {
622 while (CurrentReg != OrderEnd && !EnabledRegs.
count(*CurrentReg))
630 const std::vector<CalleeSavedInfo> &CSI,
646 for (
unsigned i = CSI.size(); i != 0; --
i) {
647 unsigned Reg = CSI[i-1].getReg();
649 if (ARM::tGPRRegClass.
contains(Reg) || Reg == ARM::LR) {
651 }
else if (ARM::hGPRRegClass.
contains(Reg) && Reg != ARM::LR) {
657 if ((ARM::tGPRRegClass.
contains(Reg) || Reg == ARM::LR) &&
664 for (
unsigned ArgReg : {ARM::R0, ARM::R1,
ARM::R2, ARM::R3})
669 if (!LoRegsToSave.
empty()) {
693 static const unsigned AllCopyRegs[] = {ARM::LR, ARM::R7,
ARM::R6,
696 static const unsigned AllHighRegs[] = {ARM::R11, ARM::R10, ARM::R9, ARM::R8};
698 const unsigned *AllCopyRegsEnd =
std::end(AllCopyRegs);
699 const unsigned *AllHighRegsEnd =
std::end(AllHighRegs);
703 std::begin(AllHighRegs), HiRegsToSave, AllHighRegsEnd);
705 while (HiRegToSave != AllHighRegsEnd) {
707 const unsigned *CopyReg =
715 while (HiRegToSave != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) {
716 if (HiRegsToSave.
count(*HiRegToSave)) {
751 const std::vector<CalleeSavedInfo> &CSI,
771 unsigned Reg =
I.getReg();
773 if (ARM::tGPRRegClass.
contains(Reg) || Reg == ARM::LR) {
774 LoRegsToRestore.
insert(Reg);
775 }
else if (ARM::hGPRRegClass.
contains(Reg) && Reg != ARM::LR) {
776 HiRegsToRestore.
insert(Reg);
783 if ((ARM::tGPRRegClass.
contains(Reg)) &&
802 static const unsigned AllCopyRegs[] = {ARM::R0, ARM::R1,
ARM::R2, ARM::R3,
804 static const unsigned AllHighRegs[] = {ARM::R8, ARM::R9, ARM::R10, ARM::R11};
806 const unsigned *AllCopyRegsEnd =
std::end(AllCopyRegs);
807 const unsigned *AllHighRegsEnd =
std::end(AllHighRegs);
811 HiRegsToRestore, AllHighRegsEnd);
813 while (HiRegToRestore != AllHighRegsEnd) {
823 while (HiRegToRestore != AllHighRegsEnd && CopyReg != AllCopyRegsEnd) {
846 bool NeedsPop =
false;
847 for (
unsigned i = CSI.size(); i != 0; --
i) {
848 unsigned Reg = CSI[i-1].getReg();
851 if (!(ARM::tGPRRegClass.
contains(Reg) || Reg == ARM::LR))
854 if (Reg == ARM::LR) {
863 (*MIB).setDesc(TII.get(ARM::tPOP_RET));
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
unsigned succ_size() const
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const_iterator end(StringRef path)
Get end iterator over path.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getBaseRegister() const
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
const_iterator begin(StringRef path)
Get begin iterator over path.
bool any() const
any - Returns true if any bit is set.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
void setGPRCalleeSavedArea2Offset(unsigned o)
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
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...
return AArch64::GPR64RegClass contains(Reg)
unsigned getDPRCalleeSavedAreaSize() const
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
const ARMBaseInstrInfo * getInstrInfo() const override
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
LLVM_NODISCARD bool empty() const
static const MachineInstrBuilder & AddDefaultPred(const MachineInstrBuilder &MIB)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const TargetInstrInfo &TII, const DebugLoc &dl, const ThumbRegisterInfo &MRI, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags)
DILocation * get() const
Get the underlying DILocation.
const HexagonInstrInfo * TII
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
Thumb1FrameLowering(const ARMSubtarget &sti)
unsigned getFrameRegister(const MachineFunction &MF) const override
unsigned getArgRegsSaveSize() const
Reg
All possible values of the reg field in the ModR/M byte.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
void setDPRCalleeSavedAreaOffset(unsigned o)
static const unsigned * findNextOrderedReg(const unsigned *CurrentReg, SmallSet< unsigned, SetSize > &EnabledRegs, const unsigned *OrderEnd)
LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
void setFramePtrSpillOffset(unsigned o)
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
bool isLiveIn(unsigned Reg) const
int getOffsetAdjustment() const
Return the correction for frame offsets.
void setShouldRestoreSPFromFP(bool s)
BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC=nullptr) const
Returns a bitset indexed by register number indicating if a register is allocatable or not...
virtual const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const =0
Return a null-terminated list of all of the callee-saved registers on this target.
unsigned getKillRegState(bool B)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
TargetInstrInfo - Interface to description of machine instruction set.
unsigned getDefRegState(bool B)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isCalleeSavedRegister(unsigned Reg, const MCPhysReg *CSRegs)
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
bool hasStackFrame() const
unsigned const MachineRegisterInfo * MRI
static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, int Offset)
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it...
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void setStackSize(uint64_t Size)
Set the size of the stack.
void addLiveOuts(const MachineBasicBlock &MBB)
Adds all live-out registers of basic block MBB.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const MachineOperand & getOperand(unsigned i) const
bool splitFramePushPop(const MachineFunction &MF) const
Returns true if the frame setup is split into two separate pushes (first r0-r7,lr then r8-r11)...
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
unsigned getFramePtrSpillOffset() const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setGPRCalleeSavedArea2Size(unsigned s)
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required, we reserve argument space for call sites in the function immediately on entry to the current function.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
succ_iterator succ_begin()
void DeleteMachineInstr(MachineInstr *MI)
DeleteMachineInstr - Delete the given MachineInstr.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
void setGPRCalleeSavedArea1Size(unsigned s)
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
bool test(unsigned Idx) const
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call...
static bool isCSRestore(MachineInstr &MI, const MCPhysReg *CSRegs)
Promote Memory to Register
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
bool hasBasePointer(const MachineFunction &MF) const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Representation of each machine instruction.
void setGPRCalleeSavedArea1Offset(unsigned o)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
A set of live physical registers with functions to track liveness when walking backward/forward throu...
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
const ARMBaseRegisterInfo * getRegisterInfo() const override
void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags=0)
emitThumbRegPlusImmediate - Emits a series of instructions to materialize a destreg = basereg + immed...
void setDPRCalleeSavedAreaSize(unsigned s)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getGPRCalleeSavedArea1Size() const
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
static const unsigned FramePtr
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
MachineModuleInfo & getMMI() const
unsigned getGPRCalleeSavedArea2Size() const
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
This class contains meta information specific to a module.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly. ...
bool shouldRestoreSPFromFP() const