146 lines · cpp
1//===-- BPFRegisterInfo.cpp - BPF Register Information ----------*- 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 contains the BPF implementation of the TargetRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "BPFRegisterInfo.h"14#include "BPFSubtarget.h"15#include "llvm/CodeGen/MachineFrameInfo.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineInstrBuilder.h"18#include "llvm/CodeGen/RegisterScavenging.h"19#include "llvm/CodeGen/TargetFrameLowering.h"20#include "llvm/CodeGen/TargetInstrInfo.h"21#include "llvm/IR/DiagnosticInfo.h"22#include "llvm/Support/CommandLine.h"23#include "llvm/Support/ErrorHandling.h"24 25#define GET_REGINFO_TARGET_DESC26#include "BPFGenRegisterInfo.inc"27using namespace llvm;28 29static cl::opt<int>30 BPFStackSizeOption("bpf-stack-size",31 cl::desc("Specify the BPF stack size limit"),32 cl::init(512));33 34BPFRegisterInfo::BPFRegisterInfo()35 : BPFGenRegisterInfo(BPF::R0) {}36 37const MCPhysReg *38BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {39 return CSR_SaveList;40}41 42const uint32_t *43BPFRegisterInfo::getCallPreservedMask(const MachineFunction &MF,44 CallingConv::ID CC) const {45 switch (CC) {46 default:47 return CSR_RegMask;48 case CallingConv::PreserveAll:49 return CSR_PreserveAll_RegMask;50 }51}52 53BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const {54 BitVector Reserved(getNumRegs());55 markSuperRegs(Reserved, BPF::W10); // [W|R]10 is read only frame pointer56 markSuperRegs(Reserved, BPF::W11); // [W|R]11 is pseudo stack pointer57 return Reserved;58}59 60static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL,61 MachineBasicBlock& MBB) {62 if (Offset <= -BPFStackSizeOption) {63 if (!DL)64 /* try harder to get some debug loc */65 for (auto &I : MBB)66 if (I.getDebugLoc()) {67 DL = I.getDebugLoc();68 break;69 }70 71 const Function &F = MF.getFunction();72 F.getContext().diagnose(DiagnosticInfoUnsupported(73 F,74 "Looks like the BPF stack limit is exceeded. "75 "Please move large on stack variables into BPF per-cpu array map. For "76 "non-kernel uses, the stack can be increased using -mllvm "77 "-bpf-stack-size.\n",78 DL));79 }80}81 82bool BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,83 int SPAdj, unsigned FIOperandNum,84 RegScavenger *RS) const {85 assert(SPAdj == 0 && "Unexpected");86 87 unsigned i = 0;88 MachineInstr &MI = *II;89 MachineBasicBlock &MBB = *MI.getParent();90 MachineFunction &MF = *MBB.getParent();91 DebugLoc DL = MI.getDebugLoc();92 93 while (!MI.getOperand(i).isFI()) {94 ++i;95 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");96 }97 98 Register FrameReg = getFrameRegister(MF);99 int FrameIndex = MI.getOperand(i).getIndex();100 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();101 102 if (MI.getOpcode() == BPF::MOV_rr) {103 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);104 105 WarnSize(Offset, MF, DL, MBB);106 MI.getOperand(i).ChangeToRegister(FrameReg, false);107 Register reg = MI.getOperand(i - 1).getReg();108 BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)109 .addReg(reg)110 .addImm(Offset);111 return false;112 }113 114 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +115 MI.getOperand(i + 1).getImm();116 117 if (!isInt<32>(Offset))118 llvm_unreachable("bug in frame offset");119 120 WarnSize(Offset, MF, DL, MBB);121 122 if (MI.getOpcode() == BPF::FI_ri) {123 // architecture does not really support FI_ri, replace it with124 // MOV_rr <target_reg>, frame_reg125 // ADD_ri <target_reg>, imm126 Register reg = MI.getOperand(i - 1).getReg();127 128 BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg)129 .addReg(FrameReg);130 BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg)131 .addReg(reg)132 .addImm(Offset);133 134 // Remove FI_ri instruction135 MI.eraseFromParent();136 } else {137 MI.getOperand(i).ChangeToRegister(FrameReg, false);138 MI.getOperand(i + 1).ChangeToImmediate(Offset);139 }140 return false;141}142 143Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const {144 return BPF::R10;145}146