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