1 //===-- BPFInstrInfo.cpp - BPF Instruction 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 TargetInstrInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "BPFInstrInfo.h" 14 #include "BPF.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/CodeGen/MachineBasicBlock.h" 17 #include "llvm/CodeGen/MachineInstrBuilder.h" 18 #include "llvm/IR/DebugLoc.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include <cassert> 21 #include <iterator> 22 23 #define GET_INSTRINFO_CTOR_DTOR 24 #include "BPFGenInstrInfo.inc" 25 26 using namespace llvm; 27 28 BPFInstrInfo::BPFInstrInfo() 29 : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {} 30 31 void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 32 MachineBasicBlock::iterator I, 33 const DebugLoc &DL, MCRegister DestReg, 34 MCRegister SrcReg, bool KillSrc) const { 35 if (BPF::GPRRegClass.contains(DestReg, SrcReg)) 36 BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg) 37 .addReg(SrcReg, getKillRegState(KillSrc)); 38 else if (BPF::GPR32RegClass.contains(DestReg, SrcReg)) 39 BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg) 40 .addReg(SrcReg, getKillRegState(KillSrc)); 41 else 42 llvm_unreachable("Impossible reg-to-reg copy"); 43 } 44 45 void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { 46 Register DstReg = MI->getOperand(0).getReg(); 47 Register SrcReg = MI->getOperand(1).getReg(); 48 uint64_t CopyLen = MI->getOperand(2).getImm(); 49 uint64_t Alignment = MI->getOperand(3).getImm(); 50 Register ScratchReg = MI->getOperand(4).getReg(); 51 MachineBasicBlock *BB = MI->getParent(); 52 DebugLoc dl = MI->getDebugLoc(); 53 unsigned LdOpc, StOpc; 54 55 switch (Alignment) { 56 case 1: 57 LdOpc = BPF::LDB; 58 StOpc = BPF::STB; 59 break; 60 case 2: 61 LdOpc = BPF::LDH; 62 StOpc = BPF::STH; 63 break; 64 case 4: 65 LdOpc = BPF::LDW; 66 StOpc = BPF::STW; 67 break; 68 case 8: 69 LdOpc = BPF::LDD; 70 StOpc = BPF::STD; 71 break; 72 default: 73 llvm_unreachable("unsupported memcpy alignment"); 74 } 75 76 unsigned IterationNum = CopyLen >> Log2_64(Alignment); 77 for(unsigned I = 0; I < IterationNum; ++I) { 78 BuildMI(*BB, MI, dl, get(LdOpc)) 79 .addReg(ScratchReg, RegState::Define).addReg(SrcReg) 80 .addImm(I * Alignment); 81 BuildMI(*BB, MI, dl, get(StOpc)) 82 .addReg(ScratchReg, RegState::Kill).addReg(DstReg) 83 .addImm(I * Alignment); 84 } 85 86 unsigned BytesLeft = CopyLen & (Alignment - 1); 87 unsigned Offset = IterationNum * Alignment; 88 bool Hanging4Byte = BytesLeft & 0x4; 89 bool Hanging2Byte = BytesLeft & 0x2; 90 bool Hanging1Byte = BytesLeft & 0x1; 91 if (Hanging4Byte) { 92 BuildMI(*BB, MI, dl, get(BPF::LDW)) 93 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset); 94 BuildMI(*BB, MI, dl, get(BPF::STW)) 95 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset); 96 Offset += 4; 97 } 98 if (Hanging2Byte) { 99 BuildMI(*BB, MI, dl, get(BPF::LDH)) 100 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset); 101 BuildMI(*BB, MI, dl, get(BPF::STH)) 102 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset); 103 Offset += 2; 104 } 105 if (Hanging1Byte) { 106 BuildMI(*BB, MI, dl, get(BPF::LDB)) 107 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset); 108 BuildMI(*BB, MI, dl, get(BPF::STB)) 109 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset); 110 } 111 112 BB->erase(MI); 113 } 114 115 bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 116 if (MI.getOpcode() == BPF::MEMCPY) { 117 expandMEMCPY(MI); 118 return true; 119 } 120 121 return false; 122 } 123 124 void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 125 MachineBasicBlock::iterator I, 126 Register SrcReg, bool IsKill, int FI, 127 const TargetRegisterClass *RC, 128 const TargetRegisterInfo *TRI, 129 Register VReg) const { 130 DebugLoc DL; 131 if (I != MBB.end()) 132 DL = I->getDebugLoc(); 133 134 if (RC == &BPF::GPRRegClass) 135 BuildMI(MBB, I, DL, get(BPF::STD)) 136 .addReg(SrcReg, getKillRegState(IsKill)) 137 .addFrameIndex(FI) 138 .addImm(0); 139 else if (RC == &BPF::GPR32RegClass) 140 BuildMI(MBB, I, DL, get(BPF::STW32)) 141 .addReg(SrcReg, getKillRegState(IsKill)) 142 .addFrameIndex(FI) 143 .addImm(0); 144 else 145 llvm_unreachable("Can't store this register to stack slot"); 146 } 147 148 void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 149 MachineBasicBlock::iterator I, 150 Register DestReg, int FI, 151 const TargetRegisterClass *RC, 152 const TargetRegisterInfo *TRI, 153 Register VReg) const { 154 DebugLoc DL; 155 if (I != MBB.end()) 156 DL = I->getDebugLoc(); 157 158 if (RC == &BPF::GPRRegClass) 159 BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); 160 else if (RC == &BPF::GPR32RegClass) 161 BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0); 162 else 163 llvm_unreachable("Can't load this register from stack slot"); 164 } 165 166 bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 167 MachineBasicBlock *&TBB, 168 MachineBasicBlock *&FBB, 169 SmallVectorImpl<MachineOperand> &Cond, 170 bool AllowModify) const { 171 // Start from the bottom of the block and work up, examining the 172 // terminator instructions. 173 MachineBasicBlock::iterator I = MBB.end(); 174 while (I != MBB.begin()) { 175 --I; 176 if (I->isDebugInstr()) 177 continue; 178 179 // Working from the bottom, when we see a non-terminator 180 // instruction, we're done. 181 if (!isUnpredicatedTerminator(*I)) 182 break; 183 184 // A terminator that isn't a branch can't easily be handled 185 // by this analysis. 186 if (!I->isBranch()) 187 return true; 188 189 // Handle unconditional branches. 190 if (I->getOpcode() == BPF::JMP) { 191 if (!AllowModify) { 192 TBB = I->getOperand(0).getMBB(); 193 continue; 194 } 195 196 // If the block has any instructions after a J, delete them. 197 MBB.erase(std::next(I), MBB.end()); 198 Cond.clear(); 199 FBB = nullptr; 200 201 // Delete the J if it's equivalent to a fall-through. 202 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 203 TBB = nullptr; 204 I->eraseFromParent(); 205 I = MBB.end(); 206 continue; 207 } 208 209 // TBB is used to indicate the unconditinal destination. 210 TBB = I->getOperand(0).getMBB(); 211 continue; 212 } 213 // Cannot handle conditional branches 214 return true; 215 } 216 217 return false; 218 } 219 220 unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB, 221 MachineBasicBlock *TBB, 222 MachineBasicBlock *FBB, 223 ArrayRef<MachineOperand> Cond, 224 const DebugLoc &DL, 225 int *BytesAdded) const { 226 assert(!BytesAdded && "code size not handled"); 227 228 // Shouldn't be a fall through. 229 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 230 231 if (Cond.empty()) { 232 // Unconditional branch 233 assert(!FBB && "Unconditional branch with multiple successors!"); 234 BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); 235 return 1; 236 } 237 238 llvm_unreachable("Unexpected conditional branch"); 239 } 240 241 unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB, 242 int *BytesRemoved) const { 243 assert(!BytesRemoved && "code size not handled"); 244 245 MachineBasicBlock::iterator I = MBB.end(); 246 unsigned Count = 0; 247 248 while (I != MBB.begin()) { 249 --I; 250 if (I->isDebugInstr()) 251 continue; 252 if (I->getOpcode() != BPF::JMP) 253 break; 254 // Remove the branch. 255 I->eraseFromParent(); 256 I = MBB.end(); 257 ++Count; 258 } 259 260 return Count; 261 } 262