xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/BPF/BPFRegisterInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- BPFRegisterInfo.cpp - BPF Register Information ----------*- 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 contains the BPF implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "BPFRegisterInfo.h"
140b57cec5SDimitry Andric #include "BPF.h"
150b57cec5SDimitry Andric #include "BPFSubtarget.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
2306c3fb27SDimitry Andric #include "llvm/Support/CommandLine.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
270b57cec5SDimitry Andric #include "BPFGenRegisterInfo.inc"
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
3006c3fb27SDimitry Andric static cl::opt<int>
3106c3fb27SDimitry Andric     BPFStackSizeOption("bpf-stack-size",
3206c3fb27SDimitry Andric                        cl::desc("Specify the BPF stack size limit"),
3306c3fb27SDimitry Andric                        cl::init(512));
3406c3fb27SDimitry Andric 
350b57cec5SDimitry Andric BPFRegisterInfo::BPFRegisterInfo()
360b57cec5SDimitry Andric     : BPFGenRegisterInfo(BPF::R0) {}
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric const MCPhysReg *
390b57cec5SDimitry Andric BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
400b57cec5SDimitry Andric   return CSR_SaveList;
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
440b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
450b57cec5SDimitry Andric   markSuperRegs(Reserved, BPF::W10); // [W|R]10 is read only frame pointer
460b57cec5SDimitry Andric   markSuperRegs(Reserved, BPF::W11); // [W|R]11 is pseudo stack pointer
470b57cec5SDimitry Andric   return Reserved;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
50*0fca6ea1SDimitry Andric static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL,
51*0fca6ea1SDimitry Andric                      MachineBasicBlock& MBB) {
5206c3fb27SDimitry Andric   if (Offset <= -BPFStackSizeOption) {
53*0fca6ea1SDimitry Andric     if (!DL)
54*0fca6ea1SDimitry Andric       /* try harder to get some debug loc */
55*0fca6ea1SDimitry Andric       for (auto &I : MBB)
56*0fca6ea1SDimitry Andric         if (I.getDebugLoc()) {
57*0fca6ea1SDimitry Andric           DL = I.getDebugLoc();
58*0fca6ea1SDimitry Andric           break;
59*0fca6ea1SDimitry Andric         }
60*0fca6ea1SDimitry Andric 
610b57cec5SDimitry Andric     const Function &F = MF.getFunction();
6206c3fb27SDimitry Andric     DiagnosticInfoUnsupported DiagStackSize(
6306c3fb27SDimitry Andric         F,
6406c3fb27SDimitry Andric         "Looks like the BPF stack limit is exceeded. "
6506c3fb27SDimitry Andric         "Please move large on stack variables into BPF per-cpu array map. For "
6606c3fb27SDimitry Andric         "non-kernel uses, the stack can be increased using -mllvm "
6706c3fb27SDimitry Andric         "-bpf-stack-size.\n",
680b57cec5SDimitry Andric         DL);
690b57cec5SDimitry Andric     F.getContext().diagnose(DiagStackSize);
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
73bdd1243dSDimitry Andric bool BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
740b57cec5SDimitry Andric                                           int SPAdj, unsigned FIOperandNum,
750b57cec5SDimitry Andric                                           RegScavenger *RS) const {
760b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   unsigned i = 0;
790b57cec5SDimitry Andric   MachineInstr &MI = *II;
800b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
810b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
820b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   while (!MI.getOperand(i).isFI()) {
850b57cec5SDimitry Andric     ++i;
860b57cec5SDimitry Andric     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric 
898bcb0991SDimitry Andric   Register FrameReg = getFrameRegister(MF);
900b57cec5SDimitry Andric   int FrameIndex = MI.getOperand(i).getIndex();
910b57cec5SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   if (MI.getOpcode() == BPF::MOV_rr) {
940b57cec5SDimitry Andric     int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
950b57cec5SDimitry Andric 
96*0fca6ea1SDimitry Andric     WarnSize(Offset, MF, DL, MBB);
970b57cec5SDimitry Andric     MI.getOperand(i).ChangeToRegister(FrameReg, false);
988bcb0991SDimitry Andric     Register reg = MI.getOperand(i - 1).getReg();
990b57cec5SDimitry Andric     BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)
1000b57cec5SDimitry Andric         .addReg(reg)
1010b57cec5SDimitry Andric         .addImm(Offset);
102bdd1243dSDimitry Andric     return false;
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
1060b57cec5SDimitry Andric                MI.getOperand(i + 1).getImm();
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (!isInt<32>(Offset))
1090b57cec5SDimitry Andric     llvm_unreachable("bug in frame offset");
1100b57cec5SDimitry Andric 
111*0fca6ea1SDimitry Andric   WarnSize(Offset, MF, DL, MBB);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   if (MI.getOpcode() == BPF::FI_ri) {
1140b57cec5SDimitry Andric     // architecture does not really support FI_ri, replace it with
1150b57cec5SDimitry Andric     //    MOV_rr <target_reg>, frame_reg
1160b57cec5SDimitry Andric     //    ADD_ri <target_reg>, imm
1178bcb0991SDimitry Andric     Register reg = MI.getOperand(i - 1).getReg();
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg)
1200b57cec5SDimitry Andric         .addReg(FrameReg);
1210b57cec5SDimitry Andric     BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg)
1220b57cec5SDimitry Andric         .addReg(reg)
1230b57cec5SDimitry Andric         .addImm(Offset);
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     // Remove FI_ri instruction
1260b57cec5SDimitry Andric     MI.eraseFromParent();
1270b57cec5SDimitry Andric   } else {
1280b57cec5SDimitry Andric     MI.getOperand(i).ChangeToRegister(FrameReg, false);
1290b57cec5SDimitry Andric     MI.getOperand(i + 1).ChangeToImmediate(Offset);
1300b57cec5SDimitry Andric   }
131bdd1243dSDimitry Andric   return false;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
1350b57cec5SDimitry Andric   return BPF::R10;
1360b57cec5SDimitry Andric }
137