24 #define DEBUG_TYPE "arc-frame-lowering" 30 cl::desc(
"Use arc callee save/restore functions"),
34 "__st_r13_to_r15",
"__st_r13_to_r16",
"__st_r13_to_r17",
"__st_r13_to_r18",
35 "__st_r13_to_r19",
"__st_r13_to_r20",
"__st_r13_to_r21",
"__st_r13_to_r22",
36 "__st_r13_to_r23",
"__st_r13_to_r24",
"__st_r13_to_r25",
40 "__ld_r13_to_r15",
"__ld_r13_to_r16",
"__ld_r13_to_r17",
"__ld_r13_to_r18",
41 "__ld_r13_to_r19",
"__ld_r13_to_r20",
"__ld_r13_to_r21",
"__ld_r13_to_r22",
42 "__ld_r13_to_r23",
"__ld_r13_to_r24",
"__ld_r13_to_r25",
48 int Amount,
int StackPtr) {
62 LLVM_DEBUG(
dbgs() <<
"Internal: adjust stack by: " << Amount <<
"," 63 << AbsAmount <<
"\n");
65 assert((AbsAmount % 4 == 0) &&
"Stack adjustments must be 4-byte aligned.");
66 if (isUInt<6>(AbsAmount))
67 AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
69 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
71 BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
79 for (
auto Reg : CSI) {
80 assert(
Reg.getReg() >= ARC::R13 &&
Reg.getReg() <= ARC::R25 &&
81 "Unexpected callee saved reg.");
82 if (
Reg.getReg() > Last)
93 SavedRegs.
set(ARC::BLINK);
96 void ARCFrameLowering::adjustStackToMatchRecords(
98 bool Allocate)
const {
105 ScalarAlloc = -ScalarAlloc;
109 ScalarAlloc, ARC::SP);
130 unsigned StackSlotsUsedByFunclet = 0;
131 bool SavedBlink =
false;
132 unsigned AlreadyAdjusted = 0;
136 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
137 BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
144 BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
149 AlreadyAdjusted += 4;
154 StackSlotsUsedByFunclet = Last - ARC::R12;
155 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
156 BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
159 .
addImm(4 * StackSlotsUsedByFunclet);
161 .addExternalSymbol(store_funclet_name[Last - ARC::R15])
163 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
167 if (MFI.
hasCalls() && !SavedBlink) {
169 BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
170 AlreadyAdjusted += 4;
172 if (AFI->MaxCallStackReq > 0)
196 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
197 .addCFIIndex(CFIIndex)
204 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
205 .addCFIIndex(CFIIndex)
213 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
214 .addCFIIndex(CFIIndex)
218 for (
const auto &Entry : CSI) {
219 unsigned Reg = Entry.getReg();
220 int FI = Entry.getFrameIdx();
226 BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
227 .addCFIIndex(CFIIndex)
243 bool SavedBlink =
false;
244 unsigned AmountAboveFunclet = 0;
253 AmountAboveFunclet += 4;
259 unsigned StackSlotsUsedByFunclet = 0;
263 StackSlotsUsedByFunclet = Last - ARC::R12;
264 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
268 if (MFI.
hasCalls() && !SavedBlink) {
269 AmountAboveFunclet += 4;
274 if (StackSize - AmountAboveFunclet) {
278 .
addImm(StackSize - AmountAboveFunclet);
281 if (StackSlotsUsedByFunclet) {
283 .addExternalSymbol(load_funclet_name[Last - ARC::R15])
288 .
addImm(4 * (StackSlotsUsedByFunclet));
307 unsigned VarArgsBytes = MFI.
getObjectSize(AFI->getVarArgsFrameIndex());
315 static std::vector<CalleeSavedInfo>::iterator
317 for (
auto I = V.begin(),
E = V.end();
I !=
E; ++
I) {
318 if (reg ==
I->getReg())
326 std::vector<CalleeSavedInfo> &CSI)
const {
336 LLVM_DEBUG(
dbgs() <<
"Creating fixed object (" << StackObj <<
") for FP at " 337 << CurOffset <<
"\n");
345 <<
") for BLINK at " << CurOffset <<
"\n");
351 for (
unsigned Which = Last; Which > ARC::R12; Which--) {
353 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
357 if (RegI != CSI.end())
358 RegI->setFrameIdx(FI);
363 for (
auto &
I : CSI) {
364 if (
I.getReg() > ARC::R12)
366 if (
I.getFrameIdx() == 0) {
369 <<
") for other register at " << CurOffset <<
"\n");
373 <<
") for other register at " << CurOffset <<
"\n");
382 const std::vector<CalleeSavedInfo> &CSI,
419 LLVM_DEBUG(
dbgs() <<
"Current stack size: " << MFI.getStackSize() <<
"\n");
421 if (MFI.hasStackObjects()) {
422 int RegScavFI = MFI.CreateStackObject(
425 LLVM_DEBUG(
dbgs() <<
"Created scavenging index RegScavFI=" << RegScavFI
432 unsigned Reg,
int NumBytes,
bool IsAdd,
434 unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
450 if (Amt > AFI->MaxCallStackReq && Old.
getOpcode() == ARC::ADJCALLSTACKDOWN)
455 Old.
getOpcode() == ARC::ADJCALLSTACKUP) &&
456 "Unknown Frame Pseudo.");
457 bool IsAdd = (Old.
getOpcode() == ARC::ADJCALLSTACKUP);
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...
This class represents lattice values for constants.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Prologue into the function.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static unsigned determineLastCalleeSave(const std::vector< CalleeSavedInfo > &CSI)
unsigned const TargetRegisterInfo * TRI
MachineModuleInfo & getMMI() const
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
Add explicit callee save registers.
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
static cl::opt< bool > UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden, cl::desc("Use arc callee save/restore functions"), cl::init(true))
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
unsigned getSpillAlignment(const TargetRegisterClass &RC) const
Return the minimum required alignment in bytes for a spill slot for a register of this class...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
const HexagonInstrInfo * TII
MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i...
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
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 ...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst)
static const char * load_funclet_name[]
Context object for machine code objects.
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
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...
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
static const char * store_funclet_name[]
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
const ARCInstrInfo * getInstrInfo() const override
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
initializer< Ty > init(const Ty &Val)
This file declares the machine register scavenger class.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool assignCalleeSavedSpillSlots(llvm::MachineFunction &, const llvm::TargetRegisterInfo *, std::vector< llvm::CalleeSavedInfo > &) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
void setStackSize(uint64_t Size)
Set the size of the stack.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE and DBG_LABEL instructions...
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
static std::vector< CalleeSavedInfo >::iterator getSavedReg(std::vector< CalleeSavedInfo > &V, unsigned reg)
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
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 Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static void generateStackAdjustment(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const ARCInstrInfo &TII, DebugLoc dl, int Amount, int StackPtr)
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Insert Epilogue into the function.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCRegisterInfo * getRegisterInfo() const
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
const MachineOperand & getOperand(unsigned i) const
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
This class contains meta information specific to a module.
bool hasCalls() const
Return true if the current function has any function calls.
static void emitRegUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned Reg, int NumBytes, bool IsAdd, const ARCInstrInfo *TII)