23#define DEBUG_TYPE "arc-frame-lowering"
28 "__st_r13_to_r15",
"__st_r13_to_r16",
"__st_r13_to_r17",
"__st_r13_to_r18",
29 "__st_r13_to_r19",
"__st_r13_to_r20",
"__st_r13_to_r21",
"__st_r13_to_r22",
30 "__st_r13_to_r23",
"__st_r13_to_r24",
"__st_r13_to_r25",
34 "__ld_r13_to_r15",
"__ld_r13_to_r16",
"__ld_r13_to_r17",
"__ld_r13_to_r18",
35 "__ld_r13_to_r19",
"__ld_r13_to_r20",
"__ld_r13_to_r21",
"__ld_r13_to_r22",
36 "__ld_r13_to_r23",
"__ld_r13_to_r24",
"__ld_r13_to_r25",
42 int Amount,
int StackPtr) {
56 LLVM_DEBUG(
dbgs() <<
"Internal: adjust stack by: " << Amount <<
","
57 << AbsAmount <<
"\n");
59 assert((AbsAmount % 4 == 0) &&
"Stack adjustments must be 4-byte aligned.");
61 AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
63 AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12;
65 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
74 for (
auto Reg : CSI) {
75 assert(
Reg.getReg() >= ARC::R13 &&
Reg.getReg() <= ARC::R25 &&
76 "Unexpected callee saved reg.");
88 SavedRegs.
set(ARC::BLINK);
91void ARCFrameLowering::adjustStackToMatchRecords(
93 bool Allocate)
const {
100 ScalarAlloc = -ScalarAlloc;
104 ScalarAlloc, ARC::SP);
124 unsigned StackSlotsUsedByFunclet = 0;
125 bool SavedBlink =
false;
126 unsigned AlreadyAdjusted = 0;
130 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
131 unsigned Opc = ARC::SUB_rrlimm;
135 Opc = ARC::SUB_rrs12;
147 AlreadyAdjusted += 4;
149 if (ST.getCLOpts().save_restore_funclet &&
Last > ARC::R14) {
152 StackSlotsUsedByFunclet =
Last - ARC::R12;
157 .
addImm(4 * StackSlotsUsedByFunclet);
161 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
165 if (MFI.
hasCalls() && !SavedBlink) {
168 AlreadyAdjusted += 4;
170 if (AFI->MaxCallStackReq > 0)
201 nullptr,
MRI->getDwarfRegNum(ARC::FP,
true), CurOffset));
210 nullptr,
MRI->getDwarfRegNum(ARC::BLINK,
true), CurOffset));
216 for (
const auto &Entry : CSI) {
218 int FI = Entry.getFrameIdx();
220 if ((
hasFP(MF) && Reg == ARC::FP) || (MFI.
hasCalls() && Reg == ARC::BLINK))
241 bool SavedBlink =
false;
242 unsigned AmountAboveFunclet = 0;
248 unsigned Opc = ARC::SUB_rrlimm;
254 AmountAboveFunclet += 4;
260 unsigned StackSlotsUsedByFunclet = 0;
262 if (ST.getCLOpts().save_restore_funclet &&
Last > ARC::R14) {
264 StackSlotsUsedByFunclet =
Last - ARC::R12;
265 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
269 if (MFI.
hasCalls() && !SavedBlink) {
270 AmountAboveFunclet += 4;
275 if (
unsigned MoveAmount = StackSize - AmountAboveFunclet) {
276 unsigned Opc = ARC::ADD_rrlimm;
280 Opc = ARC::ADD_rrs12;
283 .
addImm(StackSize - AmountAboveFunclet);
286 if (StackSlotsUsedByFunclet) {
291 unsigned Opc = ARC::ADD_rrlimm;
292 if (
isUInt<6>(4 * StackSlotsUsedByFunclet))
294 else if (
isInt<12>(4 * StackSlotsUsedByFunclet))
295 Opc = ARC::ADD_rrs12;
298 .
addImm(4 * (StackSlotsUsedByFunclet));
317 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
318 unsigned Opc = ARC::ADD_rrlimm;
322 Opc = ARC::ADD_rrs12;
330static std::vector<CalleeSavedInfo>::iterator
332 for (
auto I =
V.begin(),
E =
V.end();
I !=
E; ++
I) {
333 if (reg ==
I->getReg())
341 std::vector<CalleeSavedInfo> &CSI)
const {
351 LLVM_DEBUG(
dbgs() <<
"Creating fixed object (" << StackObj <<
") for FP at "
352 << CurOffset <<
"\n");
357 (ST.getCLOpts().save_restore_funclet &&
Last > ARC::R14)) {
361 <<
") for BLINK at " << CurOffset <<
"\n");
367 for (
unsigned Which =
Last; Which > ARC::R12; Which--) {
369 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
373 if (RegI != CSI.end())
374 RegI->setFrameIdx(FI);
379 for (
auto &
I : CSI) {
380 if (
I.getReg() > ARC::R12)
382 if (
I.getFrameIdx() == 0) {
385 <<
") for other register at " << CurOffset <<
"\n");
389 <<
") for other register at " << CurOffset <<
"\n");
400 <<
MBB.getParent()->getName() <<
"\n");
403 if (ST.getCLOpts().save_restore_funclet &&
Last > ARC::R14) {
417 <<
MBB.getParent()->getName() <<
"\n");
420 if (ST.getCLOpts().save_restore_funclet &&
Last > ARC::R14) {
438 RegInfo->getSpillAlign(*RC));
439 RS->addScavengingFrameIndex(RegScavFI);
440 LLVM_DEBUG(
dbgs() <<
"Created scavenging index RegScavFI=" << RegScavFI
447 unsigned Reg,
int NumBytes,
bool IsAdd,
451 Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
453 Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12;
455 Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
472 if (Amt > AFI->MaxCallStackReq && Old.
getOpcode() == ARC::ADJCALLSTACKDOWN)
473 AFI->MaxCallStackReq = Amt;
477 Old.
getOpcode() == ARC::ADJCALLSTACKUP) &&
478 "Unknown Frame Pseudo.");
479 bool IsAdd = (Old.
getOpcode() == ARC::ADJCALLSTACKUP);
491 RegInfo->hasStackRealignment(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const char * load_funclet_name[]
static void emitRegUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned Reg, int NumBytes, bool IsAdd, const ARCInstrInfo *TII)
static const char * store_funclet_name[]
static void generateStackAdjustment(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const ARCInstrInfo &TII, DebugLoc dl, int Amount, int StackPtr)
static std::vector< CalleeSavedInfo >::iterator getSavedReg(std::vector< CalleeSavedInfo > &V, unsigned reg)
static unsigned determineLastCalleeSave(ArrayRef< CalleeSavedInfo > CSI)
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
MachineRegisterInfo & MRI
This file declares the machine register scavenger class.
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...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool hasFPImpl(const MachineFunction &MF) const override
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
Add explicit callee save registers.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Prologue into the function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Epilogue into the function.
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...
bool assignCalleeSavedSpillSlots(llvm::MachineFunction &, const llvm::TargetRegisterInfo *, std::vector< llvm::CalleeSavedInfo > &) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...
const ARCInstrInfo * getInstrInfo() const override
Represent a constant reference to an array (0 or more elements consecutively in memory),...
BitVector & set()
Set all bits in the bitvector.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
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 cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Context object for machine code objects.
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.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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 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...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
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 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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
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...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
This is an optimization pass for GlobalISel generic memory operations.
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.
@ Define
Register definition.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
MCRegisterClass TargetRegisterClass