Go to the documentation of this file.
35 Register RAReg = STI.getRegisterInfo()->getRARegister();
47 if (!STI.isRegisterReservedByUser(SCSPReg)) {
49 MF.
getFunction(),
"x18 not reserved by user for Shadow Call Stack."});
54 if (RVFI->useSaveRestoreLibCalls(MF)) {
57 "Shadow Call Stack cannot be combined with Save/Restore LibCalls."});
62 bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
63 int64_t SlotSize = STI.getXLen() / 8;
86 Register RAReg = STI.getRegisterInfo()->getRARegister();
97 if (!STI.isRegisterReservedByUser(SCSPReg)) {
99 MF.
getFunction(),
"x18 not reserved by user for Shadow Call Stack."});
104 if (RVFI->useSaveRestoreLibCalls(MF)) {
107 "Shadow Call Stack cannot be combined with Save/Restore LibCalls."});
112 bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
113 int64_t SlotSize = STI.getXLen() / 8;
134 const std::vector<CalleeSavedInfo> &CSI) {
137 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
140 Register MaxReg = RISCV::NoRegister;
144 if (CS.getFrameIdx() < 0)
145 MaxReg =
std::max(MaxReg.
id(), CS.getReg().id());
147 if (MaxReg == RISCV::NoRegister)
153 case RISCV::X27:
return 12;
154 case RISCV::X26:
return 11;
155 case RISCV::X25:
return 10;
156 case RISCV::X24:
return 9;
157 case RISCV::X23:
return 8;
158 case RISCV::X22:
return 7;
159 case RISCV::X21:
return 6;
160 case RISCV::X20:
return 5;
161 case RISCV::X19:
return 4;
162 case RISCV::X18:
return 3;
163 case RISCV::X9:
return 2;
164 case RISCV::X8:
return 1;
165 case RISCV::X1:
return 0;
173 const std::vector<CalleeSavedInfo> &CSI) {
174 static const char *
const SpillLibCalls[] = {
193 return SpillLibCalls[LibCallID];
200 const std::vector<CalleeSavedInfo> &CSI) {
201 static const char *
const RestoreLibCalls[] = {
212 "__riscv_restore_10",
213 "__riscv_restore_11",
220 return RestoreLibCalls[LibCallID];
251 void RISCVFrameLowering::determineFrameLayout(
MachineFunction &MF)
const {
275 if (DestReg == SrcReg && Val == 0)
278 if (isInt<12>(Val)) {
285 bool IsSub = Val < 0;
308 const std::vector<CalleeSavedInfo> &CSI) {
312 for (
auto &CS : CSI) {
313 int FI = CS.getFrameIdx();
315 NonLibcallCSI.push_back(CS);
318 return NonLibcallCSI;
326 assert(Amount != 0 &&
"Did not need to adjust stack pointer for RVV.");
375 determineFrameLayout(MF);
399 RVFI->setLibCallStackSize(LibCallFrameSize);
405 uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize();
406 uint64_t RVVStackSize = RVFI->getRVVStackSize();
409 if (RealStackSize == 0 && !MFI.
adjustsStack() && RVVStackSize == 0)
416 MF.
getFunction(),
"Stack pointer required, but has been reserved."});
420 if (FirstSPAdjustAmount) {
421 StackSize = FirstSPAdjustAmount;
422 RealStackSize = FirstSPAdjustAmount;
447 for (
const auto &Entry : CSI) {
448 int FrameIdx = Entry.getFrameIdx();
453 Offset = FrameIdx * (int64_t)
STI.
getXLen() / 8;
456 RVFI->getLibCallStackSize();
459 nullptr, RI->getDwarfRegNum(
Reg,
true), Offset));
469 MF.
getFunction(),
"Frame pointer required, but has been reserved."});
472 RealStackSize - RVFI->getVarArgsSaveSize(),
477 nullptr, RI->getDwarfRegNum(FPReg,
true), RVFI->getVarArgsSaveSize()));
484 if (FirstSPAdjustAmount) {
486 assert(SecondSPAdjustAmount > 0 &&
487 "SecondSPAdjustAmount should be greater than zero");
488 adjustReg(
MBB,
MBBI,
DL, SPReg, SPReg, -SecondSPAdjustAmount,
504 adjustStackForRVV(MF,
MBB,
MBBI,
DL, -RVVStackSize,
510 if (RI->hasStackRealignment(MF)) {
514 if (isInt<12>(-(
int)MaxAlignment.
value())) {
520 unsigned ShiftAmount =
Log2(MaxAlignment);
582 auto LastFrameDestroy =
MBBI;
584 LastFrameDestroy = std::prev(
MBBI, CSI.
size());
587 uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize();
588 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
589 uint64_t RVVStackSize = RVFI->getRVVStackSize();
595 assert(
hasFP(MF) &&
"frame pointer should not have been eliminated");
596 adjustReg(
MBB, LastFrameDestroy,
DL, SPReg, FPReg, -FPOffset,
600 adjustStackForRVV(MF,
MBB, LastFrameDestroy,
DL, RVVStackSize,
605 if (FirstSPAdjustAmount) {
607 assert(SecondSPAdjustAmount > 0 &&
608 "SecondSPAdjustAmount should be greater than zero");
610 adjustReg(
MBB, LastFrameDestroy,
DL, SPReg, SPReg, SecondSPAdjustAmount,
614 if (FirstSPAdjustAmount)
615 StackSize = FirstSPAdjustAmount;
642 "Unexpected stack ID for the frame object.");
654 MinCSFI = CSI[0].getFrameIdx();
655 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
658 if (FI >= MinCSFI && FI <= MaxCSFI) {
659 FrameReg = RISCV::X2;
661 if (FirstSPAdjustAmount)
699 FrameReg = RISCV::X2;
735 RVFI->getRVVStackSize());
791 RVFI->getLibCallStackSize(),
792 RVFI->getRVVStackSize());
798 RVFI->getCalleeSavedStackSize() -
799 RVFI->getVarArgsSaveSize();
801 alignTo(ScalarLocalVarSize, 8),
802 RVFI->getRVVStackSize());
817 SavedRegs.
set(RISCV::X1);
818 SavedRegs.
set(RISCV::X8);
831 static const MCPhysReg CSRegs[] = { RISCV::X1,
832 RISCV::X5, RISCV::X6, RISCV::X7,
833 RISCV::X10, RISCV::X11,
834 RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15, RISCV::X16, RISCV::X17,
835 RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31, 0
838 for (
unsigned i = 0; CSRegs[
i]; ++
i)
839 SavedRegs.
set(CSRegs[
i]);
846 for (
unsigned i = 0; Regs[
i]; ++
i)
847 if (RISCV::FPR16RegClass.
contains(Regs[
i]) ||
848 RISCV::FPR32RegClass.
contains(Regs[
i]) ||
850 SavedRegs.
set(Regs[
i]);
856 RISCVFrameLowering::assignRVVStackObjectOffsets(
MachineFrameInfo &MFI)
const {
866 ObjectsToAllocate.push_back(
I);
871 for (
int FI : ObjectsToAllocate) {
879 Offset =
alignTo(Offset + ObjectSize, 8);
891 return TII.isRVVSpill(
MI,
true);
904 int64_t RVVStackSize = assignRVVStackObjectOffsets(MFI);
905 RVFI->setRVVStackSize(RVVStackSize);
919 RegInfo->getSpillAlign(*RC),
false);
923 if (RVVStackSize != 0) {
925 RegInfo->getSpillSize(*RC), RegInfo->getSpillAlign(*RC),
false);
931 RVFI->setCalleeSavedStackSize(0);
937 int FrameIdx =
Info.getFrameIdx();
943 RVFI->setCalleeSavedStackSize(Size);
947 if (RVVStackSize && !
hasFP(MF) && Size % 8 != 0) {
995 int64_t Amount =
MI->getOperand(0).getImm();
1001 if (
MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
1026 uint64_t StackSize = MFI.getStackSize();
1031 if (RVFI->getLibCallStackSize())
1036 if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
1058 DL =
MI->getDebugLoc();
1068 for (
auto &CS : CSI)
1074 for (
auto &CS : NonLibcallCSI) {
1095 DL =
MI->getDebugLoc();
1104 for (
auto &CS : NonLibcallCSI) {
1108 assert(
MI !=
MBB.
begin() &&
"loadRegFromStackSlot didn't insert any code!");
1112 if (RestoreLibCall) {
1121 if (
MI !=
MBB.
end() &&
MI->getOpcode() == RISCV::PseudoRET) {
1122 NewMI->copyImplicitOps(*MF, *
MI);
1123 MI->eraseFromParent();
1135 if (!RVFI->useSaveRestoreLibCalls(*MF))
1152 if (!RVFI->useSaveRestoreLibCalls(*MF))
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static const char * getSpillLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
bool isMaxCallFrameSizeComputed() const
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
unsigned succ_size() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
This is an optimization pass for GlobalISel generic memory operations.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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...
@ Define
Register definition.
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Diagnostic information for unsupported feature in backend.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
return AArch64::GPR64RegClass contains(Reg)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isRegisterReservedByUser(Register i) const
bool hasVInstructions() const
Reg
All possible values of the reg field in the ModR/M byte.
int getOffsetAdjustment() const
Return the correction for frame offsets.
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static const char * getRestoreLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
ScalarTy getFixed() const
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
void setStackSize(uint64_t Size)
Set the size of the stack.
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...
int getObjectIndexEnd() const
Return one past the maximum frame object index.
static Register getFPReg(const RISCVSubtarget &STI)
unsigned const TargetRegisterInfo * TRI
unsigned getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
bool empty() const
empty - Check if the array is empty.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
bool isRegUsed(Register Reg, bool includeReserved=true) const
Return if a specific register is currently used.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
TargetInstrInfo - Interface to description of machine instruction set.
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
const RISCVSubtarget & STI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
unsigned Log2(Align A)
Returns the log2 of the alignment.
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
const HexagonInstrInfo * TII
Flag
These should be considered private to the implementation of the MCInstrDesc class.
uint8_t getStackID(int ObjectIdx) const
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
Analysis containing CSE Info
uint64_t getFirstSPAdjustAmount(const MachineFunction &MF) const
const RISCVInstrInfo * getInstrInfo() const override
ScalarTy getScalable() const
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
This struct is a compact representation of a valid (non-zero power of two) alignment.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment.
Representation of each machine instruction.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
Store the specified register of the given register class to the specified stack frame index.
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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...
succ_iterator succ_begin()
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
static MCCFIInstruction cfiDefCfa(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.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
Load the specified register of the given register class from the specified stack frame index.
MachineBasicBlock MachineBasicBlock::iterator MBBI
const RISCVRegisterInfo * getRegisterInfo() const override
static bool hasRVVFrameObject(const MachineFunction &MF)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StackOffset is a class to represent an offset with 2 dimensions, named fixed and scalable,...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
unsigned const MachineRegisterInfo * MRI
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
Wrapper class representing virtual and physical registers.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
void enterBasicBlock(MachineBasicBlock &MBB)
Start tracking liveness from the begin of basic block MBB.
bool hasCalls() const
Return true if the current function has any function calls.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Function & getFunction()
Return the LLVM function that this machine code represents.
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
uint64_t value() const
This is a hole in the type system and should not be abused.
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...
@ ADD
Simple integer binary arithmetic operators.
MachineBasicBlock * getFallThrough()
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
static int getLibCallID(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
TargetStackID::Value getStackIDForScalableVectors() const override
Returns the StackID that scalable vectors should be associated with.
static Register getSPReg(const RISCVSubtarget &STI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Align max(MaybeAlign Lhs, Align Rhs)
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static bool hasRVVSpillWithFIs(MachineFunction &MF, const RISCVInstrInfo &TII)
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool isSupportedStackID(TargetStackID::Value ID) const override
const TargetRegisterClass * getMinimalPhysRegClass(MCRegister Reg, MVT VT=MVT::Other) const
Returns the Register Class of a physical register of the given type, picking the most sub register cl...
bool hasBP(const MachineFunction &MF) const
@ Kill
The last use of a register.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i....
static SmallVector< CalleeSavedInfo, 8 > getNonLibcallCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static StackOffset get(ScalarTy Fixed, ScalarTy Scalable)