1ff0cc061SDimitry Andric //===-- BPFRegisterInfo.cpp - BPF Register Information ----------*- C++ -*-===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric //                     The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // This file contains the BPF implementation of the TargetRegisterInfo class.
11ff0cc061SDimitry Andric //
12ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
13ff0cc061SDimitry Andric 
14ff0cc061SDimitry Andric #include "BPFRegisterInfo.h"
15db17bf38SDimitry Andric #include "BPF.h"
16ff0cc061SDimitry Andric #include "BPFSubtarget.h"
17ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
18ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
19db17bf38SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
20ff0cc061SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
212cab237bSDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
222cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
23db17bf38SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
24ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25ff0cc061SDimitry Andric 
26ff0cc061SDimitry Andric #define GET_REGINFO_TARGET_DESC
27ff0cc061SDimitry Andric #include "BPFGenRegisterInfo.inc"
28ff0cc061SDimitry Andric using namespace llvm;
29ff0cc061SDimitry Andric 
BPFRegisterInfo()30ff0cc061SDimitry Andric BPFRegisterInfo::BPFRegisterInfo()
31ff0cc061SDimitry Andric     : BPFGenRegisterInfo(BPF::R0) {}
32ff0cc061SDimitry Andric 
33ff0cc061SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const34ff0cc061SDimitry Andric BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
35ff0cc061SDimitry Andric   return CSR_SaveList;
36ff0cc061SDimitry Andric }
37ff0cc061SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const38ff0cc061SDimitry Andric BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
39ff0cc061SDimitry Andric   BitVector Reserved(getNumRegs());
40*4ba319b5SDimitry Andric   markSuperRegs(Reserved, BPF::W10); // [W|R]10 is read only frame pointer
41*4ba319b5SDimitry Andric   markSuperRegs(Reserved, BPF::W11); // [W|R]11 is pseudo stack pointer
42ff0cc061SDimitry Andric   return Reserved;
43ff0cc061SDimitry Andric }
44ff0cc061SDimitry Andric 
WarnSize(int Offset,MachineFunction & MF,DebugLoc & DL)457a7e6055SDimitry Andric static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL)
467a7e6055SDimitry Andric {
477a7e6055SDimitry Andric   if (Offset <= -512) {
482cab237bSDimitry Andric       const Function &F = MF.getFunction();
492cab237bSDimitry Andric       DiagnosticInfoUnsupported DiagStackSize(F,
507a7e6055SDimitry Andric           "Looks like the BPF stack limit of 512 bytes is exceeded. "
517a7e6055SDimitry Andric           "Please move large on stack variables into BPF per-cpu array map.\n",
527a7e6055SDimitry Andric           DL);
532cab237bSDimitry Andric       F.getContext().diagnose(DiagStackSize);
547a7e6055SDimitry Andric   }
557a7e6055SDimitry Andric }
567a7e6055SDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const57ff0cc061SDimitry Andric void BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
58ff0cc061SDimitry Andric                                           int SPAdj, unsigned FIOperandNum,
59ff0cc061SDimitry Andric                                           RegScavenger *RS) const {
60ff0cc061SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
61ff0cc061SDimitry Andric 
62ff0cc061SDimitry Andric   unsigned i = 0;
63ff0cc061SDimitry Andric   MachineInstr &MI = *II;
647a7e6055SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
657a7e6055SDimitry Andric   MachineFunction &MF = *MBB.getParent();
66ff0cc061SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
67ff0cc061SDimitry Andric 
687a7e6055SDimitry Andric   if (!DL)
697a7e6055SDimitry Andric     /* try harder to get some debug loc */
707a7e6055SDimitry Andric     for (auto &I : MBB)
717a7e6055SDimitry Andric       if (I.getDebugLoc()) {
727a7e6055SDimitry Andric         DL = I.getDebugLoc();
737a7e6055SDimitry Andric         break;
747a7e6055SDimitry Andric       }
757a7e6055SDimitry Andric 
76ff0cc061SDimitry Andric   while (!MI.getOperand(i).isFI()) {
77ff0cc061SDimitry Andric     ++i;
78ff0cc061SDimitry Andric     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
79ff0cc061SDimitry Andric   }
80ff0cc061SDimitry Andric 
81ff0cc061SDimitry Andric   unsigned FrameReg = getFrameRegister(MF);
82ff0cc061SDimitry Andric   int FrameIndex = MI.getOperand(i).getIndex();
839a4b3118SDimitry Andric   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
84ff0cc061SDimitry Andric 
85ff0cc061SDimitry Andric   if (MI.getOpcode() == BPF::MOV_rr) {
86d88c1a5aSDimitry Andric     int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
87ff0cc061SDimitry Andric 
887a7e6055SDimitry Andric     WarnSize(Offset, MF, DL);
89ff0cc061SDimitry Andric     MI.getOperand(i).ChangeToRegister(FrameReg, false);
90ff0cc061SDimitry Andric     unsigned reg = MI.getOperand(i - 1).getReg();
91ff0cc061SDimitry Andric     BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)
92ff0cc061SDimitry Andric         .addReg(reg)
93ff0cc061SDimitry Andric         .addImm(Offset);
94ff0cc061SDimitry Andric     return;
95ff0cc061SDimitry Andric   }
96ff0cc061SDimitry Andric 
97d88c1a5aSDimitry Andric   int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
98ff0cc061SDimitry Andric                MI.getOperand(i + 1).getImm();
99ff0cc061SDimitry Andric 
100ff0cc061SDimitry Andric   if (!isInt<32>(Offset))
101ff0cc061SDimitry Andric     llvm_unreachable("bug in frame offset");
102ff0cc061SDimitry Andric 
1037a7e6055SDimitry Andric   WarnSize(Offset, MF, DL);
1047a7e6055SDimitry Andric 
1059a4b3118SDimitry Andric   if (MI.getOpcode() == BPF::FI_ri) {
1069a4b3118SDimitry Andric     // architecture does not really support FI_ri, replace it with
1079a4b3118SDimitry Andric     //    MOV_rr <target_reg>, frame_reg
1089a4b3118SDimitry Andric     //    ADD_ri <target_reg>, imm
1099a4b3118SDimitry Andric     unsigned reg = MI.getOperand(i - 1).getReg();
1109a4b3118SDimitry Andric 
1119a4b3118SDimitry Andric     BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg)
1129a4b3118SDimitry Andric         .addReg(FrameReg);
1139a4b3118SDimitry Andric     BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg)
1149a4b3118SDimitry Andric         .addReg(reg)
1159a4b3118SDimitry Andric         .addImm(Offset);
1169a4b3118SDimitry Andric 
1179a4b3118SDimitry Andric     // Remove FI_ri instruction
1189a4b3118SDimitry Andric     MI.eraseFromParent();
1199a4b3118SDimitry Andric   } else {
120ff0cc061SDimitry Andric     MI.getOperand(i).ChangeToRegister(FrameReg, false);
121ff0cc061SDimitry Andric     MI.getOperand(i + 1).ChangeToImmediate(Offset);
122ff0cc061SDimitry Andric   }
1239a4b3118SDimitry Andric }
124ff0cc061SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const125ff0cc061SDimitry Andric unsigned BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
126ff0cc061SDimitry Andric   return BPF::R10;
127ff0cc061SDimitry Andric }
128