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-exception 6 // 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_DESC 26 #include "BPFGenRegisterInfo.inc" 27 using namespace llvm; 28 29 static cl::opt<int> 30 BPFStackSizeOption("bpf-stack-size", 31 cl::desc("Specify the BPF stack size limit"), 32 cl::init(512)); 33 34 BPFRegisterInfo::BPFRegisterInfo() 35 : BPFGenRegisterInfo(BPF::R0) {} 36 37 const MCPhysReg * 38 BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 39 return CSR_SaveList; 40 } 41 42 const uint32_t * 43 BPFRegisterInfo::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 53 BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const { 54 BitVector Reserved(getNumRegs()); 55 markSuperRegs(Reserved, BPF::W10); // [W|R]10 is read only frame pointer 56 markSuperRegs(Reserved, BPF::W11); // [W|R]11 is pseudo stack pointer 57 return Reserved; 58 } 59 60 static 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 82 bool 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 with 124 // MOV_rr <target_reg>, frame_reg 125 // ADD_ri <target_reg>, imm 126 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 instruction 135 MI.eraseFromParent(); 136 } else { 137 MI.getOperand(i).ChangeToRegister(FrameReg, false); 138 MI.getOperand(i + 1).ChangeToImmediate(Offset); 139 } 140 return false; 141 } 142 143 Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 144 return BPF::R10; 145 } 146