226 lines · c
1//=- RISCVMachineFunctionInfo.h - RISC-V machine function info ----*- C++ -*-=//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file declares RISCV-specific per-machine-function information.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H14#define LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H15 16#include "RISCVSubtarget.h"17#include "llvm/CodeGen/MIRYamlMapping.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20 21namespace llvm {22 23class RISCVMachineFunctionInfo;24 25namespace yaml {26struct RISCVMachineFunctionInfo final : public yaml::MachineFunctionInfo {27 int VarArgsFrameIndex;28 int VarArgsSaveSize;29 30 RISCVMachineFunctionInfo() = default;31 RISCVMachineFunctionInfo(const llvm::RISCVMachineFunctionInfo &MFI);32 33 void mappingImpl(yaml::IO &YamlIO) override;34 ~RISCVMachineFunctionInfo() override = default;35};36 37template <> struct MappingTraits<RISCVMachineFunctionInfo> {38 static void mapping(IO &YamlIO, RISCVMachineFunctionInfo &MFI) {39 YamlIO.mapOptional("varArgsFrameIndex", MFI.VarArgsFrameIndex);40 YamlIO.mapOptional("varArgsSaveSize", MFI.VarArgsSaveSize);41 }42};43} // end namespace yaml44 45/// RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo46/// and contains private RISCV-specific information for each MachineFunction.47class RISCVMachineFunctionInfo : public MachineFunctionInfo {48private:49 /// FrameIndex for start of varargs area50 int VarArgsFrameIndex = 0;51 /// Size of the save area used for varargs52 int VarArgsSaveSize = 0;53 /// FrameIndex used for transferring values between 64-bit FPRs and a pair54 /// of 32-bit GPRs via the stack.55 int MoveF64FrameIndex = -1;56 /// FrameIndex of the spill slot for the scratch register in BranchRelaxation.57 int BranchRelaxationScratchFrameIndex = -1;58 /// Size of any opaque stack adjustment due to save/restore libcalls.59 unsigned LibCallStackSize = 0;60 /// Size of RVV stack.61 uint64_t RVVStackSize = 0;62 /// Alignment of RVV stack.63 Align RVVStackAlign;64 /// Padding required to keep RVV stack aligned within the main stack.65 uint64_t RVVPadding = 0;66 /// Size of stack frame to save callee saved registers67 unsigned CalleeSavedStackSize = 0;68 /// Is there any vector argument or return?69 bool IsVectorCall = false;70 71 /// Registers that have been sign extended from i32.72 SmallVector<Register, 8> SExt32Registers;73 74 /// Size of stack frame for Zcmp PUSH/POP75 unsigned RVPushStackSize = 0;76 unsigned RVPushRegs = 0;77 78 /// Size of any opaque stack adjustment due to QCI Interrupt instructions.79 unsigned QCIInterruptStackSize = 0;80 81 /// Store Frame Indexes for Interrupt-Related CSR Spills.82 SmallVector<int, 2> InterruptCSRFrameIndexes;83 84 int64_t StackProbeSize = 0;85 86 /// Does it probe the stack for a dynamic allocation?87 bool HasDynamicAllocation = false;88 89public:90 RISCVMachineFunctionInfo(const Function &F, const RISCVSubtarget *STI);91 92 MachineFunctionInfo *93 clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,94 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)95 const override;96 97 int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }98 void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }99 100 unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; }101 void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; }102 103 int getMoveF64FrameIndex(MachineFunction &MF) {104 if (MoveF64FrameIndex == -1)105 MoveF64FrameIndex =106 MF.getFrameInfo().CreateStackObject(8, Align(8), false);107 return MoveF64FrameIndex;108 }109 110 int getBranchRelaxationScratchFrameIndex() const {111 return BranchRelaxationScratchFrameIndex;112 }113 void setBranchRelaxationScratchFrameIndex(int Index) {114 BranchRelaxationScratchFrameIndex = Index;115 }116 117 unsigned getReservedSpillsSize() const {118 return LibCallStackSize + RVPushStackSize + QCIInterruptStackSize;119 }120 121 unsigned getLibCallStackSize() const { return LibCallStackSize; }122 void setLibCallStackSize(unsigned Size) { LibCallStackSize = Size; }123 124 bool useSaveRestoreLibCalls(const MachineFunction &MF) const {125 // We cannot use fixed locations for the callee saved spill slots if the126 // function uses a varargs save area, or is an interrupt handler.127 return !isPushable(MF) &&128 MF.getSubtarget<RISCVSubtarget>().enableSaveRestore() &&129 VarArgsSaveSize == 0 && !MF.getFrameInfo().hasTailCall() &&130 !MF.getFunction().hasFnAttribute("interrupt");131 }132 133 uint64_t getRVVStackSize() const { return RVVStackSize; }134 void setRVVStackSize(uint64_t Size) { RVVStackSize = Size; }135 136 Align getRVVStackAlign() const { return RVVStackAlign; }137 void setRVVStackAlign(Align StackAlign) { RVVStackAlign = StackAlign; }138 139 uint64_t getRVVPadding() const { return RVVPadding; }140 void setRVVPadding(uint64_t Padding) { RVVPadding = Padding; }141 142 unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }143 void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }144 145 enum class PushPopKind { None = 0, StdExtZcmp, VendorXqccmp };146 147 PushPopKind getPushPopKind(const MachineFunction &MF) const;148 149 bool isPushable(const MachineFunction &MF) const {150 return getPushPopKind(MF) != PushPopKind::None;151 }152 153 unsigned getRVPushRegs() const { return RVPushRegs; }154 void setRVPushRegs(unsigned Regs) { RVPushRegs = Regs; }155 156 unsigned getRVPushStackSize() const { return RVPushStackSize; }157 void setRVPushStackSize(unsigned Size) { RVPushStackSize = Size; }158 159 enum class InterruptStackKind {160 None = 0,161 QCINest,162 QCINoNest,163 SiFiveCLICPreemptible,164 SiFiveCLICStackSwap,165 SiFiveCLICPreemptibleStackSwap166 };167 168 InterruptStackKind getInterruptStackKind(const MachineFunction &MF) const;169 170 bool useQCIInterrupt(const MachineFunction &MF) const {171 InterruptStackKind Kind = getInterruptStackKind(MF);172 return Kind == InterruptStackKind::QCINest ||173 Kind == InterruptStackKind::QCINoNest;174 }175 176 unsigned getQCIInterruptStackSize() const { return QCIInterruptStackSize; }177 void setQCIInterruptStackSize(unsigned Size) { QCIInterruptStackSize = Size; }178 179 bool useSiFiveInterrupt(const MachineFunction &MF) const {180 InterruptStackKind Kind = getInterruptStackKind(MF);181 return Kind == InterruptStackKind::SiFiveCLICPreemptible ||182 Kind == InterruptStackKind::SiFiveCLICStackSwap ||183 Kind == InterruptStackKind::SiFiveCLICPreemptibleStackSwap;184 }185 186 bool isSiFivePreemptibleInterrupt(const MachineFunction &MF) const {187 InterruptStackKind Kind = getInterruptStackKind(MF);188 return Kind == InterruptStackKind::SiFiveCLICPreemptible ||189 Kind == InterruptStackKind::SiFiveCLICPreemptibleStackSwap;190 }191 192 bool isSiFiveStackSwapInterrupt(const MachineFunction &MF) const {193 InterruptStackKind Kind = getInterruptStackKind(MF);194 return Kind == InterruptStackKind::SiFiveCLICStackSwap ||195 Kind == InterruptStackKind::SiFiveCLICPreemptibleStackSwap;196 }197 198 void pushInterruptCSRFrameIndex(int FI) {199 InterruptCSRFrameIndexes.push_back(FI);200 }201 int getInterruptCSRFrameIndex(size_t Idx) const {202 return InterruptCSRFrameIndexes[Idx];203 }204 205 // Some Stack Management Variants automatically update FP in a frame-pointer206 // convention compatible way - which means we don't need to manually update207 // the FP, but we still need to emit the correct CFI information for208 // calculating the CFA based on FP.209 bool hasImplicitFPUpdates(const MachineFunction &MF) const;210 211 void initializeBaseYamlFields(const yaml::RISCVMachineFunctionInfo &YamlMFI);212 213 void addSExt32Register(Register Reg);214 bool isSExt32Register(Register Reg) const;215 216 bool isVectorCall() const { return IsVectorCall; }217 void setIsVectorCall() { IsVectorCall = true; }218 219 bool hasDynamicAllocation() const { return HasDynamicAllocation; }220 void setDynamicAllocation() { HasDynamicAllocation = true; }221};222 223} // end namespace llvm224 225#endif // LLVM_LIB_TARGET_RISCV_RISCVMACHINEFUNCTIONINFO_H226