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 DiagnosticInfoUnsupported DiagStackSize( 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 F.getContext().diagnose(DiagStackSize); 80 } 81 } 82 83 bool BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 84 int SPAdj, unsigned FIOperandNum, 85 RegScavenger *RS) const { 86 assert(SPAdj == 0 && "Unexpected"); 87 88 unsigned i = 0; 89 MachineInstr &MI = *II; 90 MachineBasicBlock &MBB = *MI.getParent(); 91 MachineFunction &MF = *MBB.getParent(); 92 DebugLoc DL = MI.getDebugLoc(); 93 94 while (!MI.getOperand(i).isFI()) { 95 ++i; 96 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); 97 } 98 99 Register FrameReg = getFrameRegister(MF); 100 int FrameIndex = MI.getOperand(i).getIndex(); 101 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 102 103 if (MI.getOpcode() == BPF::MOV_rr) { 104 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); 105 106 WarnSize(Offset, MF, DL, MBB); 107 MI.getOperand(i).ChangeToRegister(FrameReg, false); 108 Register reg = MI.getOperand(i - 1).getReg(); 109 BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg) 110 .addReg(reg) 111 .addImm(Offset); 112 return false; 113 } 114 115 int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) + 116 MI.getOperand(i + 1).getImm(); 117 118 if (!isInt<32>(Offset)) 119 llvm_unreachable("bug in frame offset"); 120 121 WarnSize(Offset, MF, DL, MBB); 122 123 if (MI.getOpcode() == BPF::FI_ri) { 124 // architecture does not really support FI_ri, replace it with 125 // MOV_rr <target_reg>, frame_reg 126 // ADD_ri <target_reg>, imm 127 Register reg = MI.getOperand(i - 1).getReg(); 128 129 BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg) 130 .addReg(FrameReg); 131 BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg) 132 .addReg(reg) 133 .addImm(Offset); 134 135 // Remove FI_ri instruction 136 MI.eraseFromParent(); 137 } else { 138 MI.getOperand(i).ChangeToRegister(FrameReg, false); 139 MI.getOperand(i + 1).ChangeToImmediate(Offset); 140 } 141 return false; 142 } 143 144 Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { 145 return BPF::R10; 146 } 147