xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //=- RISCVMachineFunctionInfo.h - RISC-V machine function info ----*- C++ -*-=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares RISCV-specific per-machine-function information.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H
150b57cec5SDimitry Andric 
165ffd83dbSDimitry Andric #include "RISCVSubtarget.h"
173a9a9c0cSDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace llvm {
220b57cec5SDimitry Andric 
233a9a9c0cSDimitry Andric class RISCVMachineFunctionInfo;
243a9a9c0cSDimitry Andric 
253a9a9c0cSDimitry Andric namespace yaml {
263a9a9c0cSDimitry Andric struct RISCVMachineFunctionInfo final : public yaml::MachineFunctionInfo {
273a9a9c0cSDimitry Andric   int VarArgsFrameIndex;
283a9a9c0cSDimitry Andric   int VarArgsSaveSize;
293a9a9c0cSDimitry Andric 
303a9a9c0cSDimitry Andric   RISCVMachineFunctionInfo() = default;
313a9a9c0cSDimitry Andric   RISCVMachineFunctionInfo(const llvm::RISCVMachineFunctionInfo &MFI);
323a9a9c0cSDimitry Andric 
333a9a9c0cSDimitry Andric   void mappingImpl(yaml::IO &YamlIO) override;
343a9a9c0cSDimitry Andric   ~RISCVMachineFunctionInfo() = default;
353a9a9c0cSDimitry Andric };
363a9a9c0cSDimitry Andric 
373a9a9c0cSDimitry Andric template <> struct MappingTraits<RISCVMachineFunctionInfo> {
383a9a9c0cSDimitry Andric   static void mapping(IO &YamlIO, RISCVMachineFunctionInfo &MFI) {
393a9a9c0cSDimitry Andric     YamlIO.mapOptional("varArgsFrameIndex", MFI.VarArgsFrameIndex);
403a9a9c0cSDimitry Andric     YamlIO.mapOptional("varArgsSaveSize", MFI.VarArgsSaveSize);
413a9a9c0cSDimitry Andric   }
423a9a9c0cSDimitry Andric };
433a9a9c0cSDimitry Andric } // end namespace yaml
443a9a9c0cSDimitry Andric 
450b57cec5SDimitry Andric /// RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo
460b57cec5SDimitry Andric /// and contains private RISCV-specific information for each MachineFunction.
470b57cec5SDimitry Andric class RISCVMachineFunctionInfo : public MachineFunctionInfo {
480b57cec5SDimitry Andric private:
490b57cec5SDimitry Andric   /// FrameIndex for start of varargs area
500b57cec5SDimitry Andric   int VarArgsFrameIndex = 0;
510b57cec5SDimitry Andric   /// Size of the save area used for varargs
520b57cec5SDimitry Andric   int VarArgsSaveSize = 0;
530b57cec5SDimitry Andric   /// FrameIndex used for transferring values between 64-bit FPRs and a pair
540b57cec5SDimitry Andric   /// of 32-bit GPRs via the stack.
550b57cec5SDimitry Andric   int MoveF64FrameIndex = -1;
56bdd1243dSDimitry Andric   /// FrameIndex of the spill slot for the scratch register in BranchRelaxation.
57bdd1243dSDimitry Andric   int BranchRelaxationScratchFrameIndex = -1;
585ffd83dbSDimitry Andric   /// Size of any opaque stack adjustment due to save/restore libcalls.
595ffd83dbSDimitry Andric   unsigned LibCallStackSize = 0;
60fe6060f1SDimitry Andric   /// Size of RVV stack.
61fe6060f1SDimitry Andric   uint64_t RVVStackSize = 0;
6281ad6265SDimitry Andric   /// Alignment of RVV stack.
6381ad6265SDimitry Andric   Align RVVStackAlign;
64fe6060f1SDimitry Andric   /// Padding required to keep RVV stack aligned within the main stack.
65fe6060f1SDimitry Andric   uint64_t RVVPadding = 0;
66fe6060f1SDimitry Andric   /// Size of stack frame to save callee saved registers
67fe6060f1SDimitry Andric   unsigned CalleeSavedStackSize = 0;
68bdd1243dSDimitry Andric   /// Is there any vector argument or return?
69bdd1243dSDimitry Andric   bool IsVectorCall = false;
70bdd1243dSDimitry Andric 
71bdd1243dSDimitry Andric   /// Registers that have been sign extended from i32.
72bdd1243dSDimitry Andric   SmallVector<Register, 8> SExt32Registers;
730b57cec5SDimitry Andric 
7406c3fb27SDimitry Andric   /// Size of stack frame for Zcmp PUSH/POP
7506c3fb27SDimitry Andric   unsigned RVPushStackSize = 0;
7606c3fb27SDimitry Andric   unsigned RVPushRegs = 0;
7706c3fb27SDimitry Andric   int RVPushRlist = llvm::RISCVZC::RLISTENCODE::INVALID_RLIST;
7806c3fb27SDimitry Andric 
790b57cec5SDimitry Andric public:
80bdd1243dSDimitry Andric   RISCVMachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {}
810b57cec5SDimitry Andric 
8281ad6265SDimitry Andric   MachineFunctionInfo *
8381ad6265SDimitry Andric   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
8481ad6265SDimitry Andric         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
8581ad6265SDimitry Andric       const override;
8681ad6265SDimitry Andric 
870b57cec5SDimitry Andric   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
880b57cec5SDimitry Andric   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; }
910b57cec5SDimitry Andric   void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; }
920b57cec5SDimitry Andric 
935ffd83dbSDimitry Andric   int getMoveF64FrameIndex(MachineFunction &MF) {
940b57cec5SDimitry Andric     if (MoveF64FrameIndex == -1)
955ffd83dbSDimitry Andric       MoveF64FrameIndex =
965ffd83dbSDimitry Andric           MF.getFrameInfo().CreateStackObject(8, Align(8), false);
970b57cec5SDimitry Andric     return MoveF64FrameIndex;
980b57cec5SDimitry Andric   }
995ffd83dbSDimitry Andric 
100bdd1243dSDimitry Andric   int getBranchRelaxationScratchFrameIndex() const {
101bdd1243dSDimitry Andric     return BranchRelaxationScratchFrameIndex;
102bdd1243dSDimitry Andric   }
103bdd1243dSDimitry Andric   void setBranchRelaxationScratchFrameIndex(int Index) {
104bdd1243dSDimitry Andric     BranchRelaxationScratchFrameIndex = Index;
105bdd1243dSDimitry Andric   }
106bdd1243dSDimitry Andric 
1075f757f3fSDimitry Andric   unsigned getReservedSpillsSize() const {
1085f757f3fSDimitry Andric     return LibCallStackSize + RVPushStackSize;
1095f757f3fSDimitry Andric   }
1105f757f3fSDimitry Andric 
1115ffd83dbSDimitry Andric   unsigned getLibCallStackSize() const { return LibCallStackSize; }
1125ffd83dbSDimitry Andric   void setLibCallStackSize(unsigned Size) { LibCallStackSize = Size; }
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   bool useSaveRestoreLibCalls(const MachineFunction &MF) const {
1155ffd83dbSDimitry Andric     // We cannot use fixed locations for the callee saved spill slots if the
116fe6060f1SDimitry Andric     // function uses a varargs save area, or is an interrupt handler.
1175f757f3fSDimitry Andric     return !isPushable(MF) &&
1185f757f3fSDimitry Andric            MF.getSubtarget<RISCVSubtarget>().enableSaveRestore() &&
119fe6060f1SDimitry Andric            VarArgsSaveSize == 0 && !MF.getFrameInfo().hasTailCall() &&
120fe6060f1SDimitry Andric            !MF.getFunction().hasFnAttribute("interrupt");
1215ffd83dbSDimitry Andric   }
122fe6060f1SDimitry Andric 
123fe6060f1SDimitry Andric   uint64_t getRVVStackSize() const { return RVVStackSize; }
124fe6060f1SDimitry Andric   void setRVVStackSize(uint64_t Size) { RVVStackSize = Size; }
125fe6060f1SDimitry Andric 
12681ad6265SDimitry Andric   Align getRVVStackAlign() const { return RVVStackAlign; }
12781ad6265SDimitry Andric   void setRVVStackAlign(Align StackAlign) { RVVStackAlign = StackAlign; }
12881ad6265SDimitry Andric 
129fe6060f1SDimitry Andric   uint64_t getRVVPadding() const { return RVVPadding; }
130fe6060f1SDimitry Andric   void setRVVPadding(uint64_t Padding) { RVVPadding = Padding; }
131fe6060f1SDimitry Andric 
132fe6060f1SDimitry Andric   unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }
133fe6060f1SDimitry Andric   void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }
1343a9a9c0cSDimitry Andric 
1355f757f3fSDimitry Andric   bool isPushable(const MachineFunction &MF) const {
1365f757f3fSDimitry Andric     // We cannot use fixed locations for the callee saved spill slots if the
1375f757f3fSDimitry Andric     // function uses a varargs save area.
138*0fca6ea1SDimitry Andric     // TODO: Use a separate placement for vararg registers to enable Zcmp.
1395f757f3fSDimitry Andric     return MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() &&
1405f757f3fSDimitry Andric            !MF.getTarget().Options.DisableFramePointerElim(MF) &&
1415f757f3fSDimitry Andric            VarArgsSaveSize == 0;
14206c3fb27SDimitry Andric   }
14306c3fb27SDimitry Andric 
14406c3fb27SDimitry Andric   int getRVPushRlist() const { return RVPushRlist; }
14506c3fb27SDimitry Andric   void setRVPushRlist(int Rlist) { RVPushRlist = Rlist; }
14606c3fb27SDimitry Andric 
14706c3fb27SDimitry Andric   unsigned getRVPushRegs() const { return RVPushRegs; }
14806c3fb27SDimitry Andric   void setRVPushRegs(unsigned Regs) { RVPushRegs = Regs; }
14906c3fb27SDimitry Andric 
15006c3fb27SDimitry Andric   unsigned getRVPushStackSize() const { return RVPushStackSize; }
15106c3fb27SDimitry Andric   void setRVPushStackSize(unsigned Size) { RVPushStackSize = Size; }
15206c3fb27SDimitry Andric 
1533a9a9c0cSDimitry Andric   void initializeBaseYamlFields(const yaml::RISCVMachineFunctionInfo &YamlMFI);
154bdd1243dSDimitry Andric 
155bdd1243dSDimitry Andric   void addSExt32Register(Register Reg);
156bdd1243dSDimitry Andric   bool isSExt32Register(Register Reg) const;
157bdd1243dSDimitry Andric 
158bdd1243dSDimitry Andric   bool isVectorCall() const { return IsVectorCall; }
159bdd1243dSDimitry Andric   void setIsVectorCall() { IsVectorCall = true; }
1600b57cec5SDimitry Andric };
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric } // end namespace llvm
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H
165