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) const { 129 DebugLoc DL; 130 if (I != MBB.end()) 131 DL = I->getDebugLoc(); 132 133 if (RC == &BPF::GPRRegClass) 134 BuildMI(MBB, I, DL, get(BPF::STD)) 135 .addReg(SrcReg, getKillRegState(IsKill)) 136 .addFrameIndex(FI) 137 .addImm(0); 138 else if (RC == &BPF::GPR32RegClass) 139 BuildMI(MBB, I, DL, get(BPF::STW32)) 140 .addReg(SrcReg, getKillRegState(IsKill)) 141 .addFrameIndex(FI) 142 .addImm(0); 143 else 144 llvm_unreachable("Can't store this register to stack slot"); 145 } 146 147 void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 148 MachineBasicBlock::iterator I, 149 Register DestReg, int FI, 150 const TargetRegisterClass *RC, 151 const TargetRegisterInfo *TRI) const { 152 DebugLoc DL; 153 if (I != MBB.end()) 154 DL = I->getDebugLoc(); 155 156 if (RC == &BPF::GPRRegClass) 157 BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); 158 else if (RC == &BPF::GPR32RegClass) 159 BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0); 160 else 161 llvm_unreachable("Can't load this register from stack slot"); 162 } 163 164 bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 165 MachineBasicBlock *&TBB, 166 MachineBasicBlock *&FBB, 167 SmallVectorImpl<MachineOperand> &Cond, 168 bool AllowModify) const { 169 // Start from the bottom of the block and work up, examining the 170 // terminator instructions. 171 MachineBasicBlock::iterator I = MBB.end(); 172 while (I != MBB.begin()) { 173 --I; 174 if (I->isDebugInstr()) 175 continue; 176 177 // Working from the bottom, when we see a non-terminator 178 // instruction, we're done. 179 if (!isUnpredicatedTerminator(*I)) 180 break; 181 182 // A terminator that isn't a branch can't easily be handled 183 // by this analysis. 184 if (!I->isBranch()) 185 return true; 186 187 // Handle unconditional branches. 188 if (I->getOpcode() == BPF::JMP) { 189 if (!AllowModify) { 190 TBB = I->getOperand(0).getMBB(); 191 continue; 192 } 193 194 // If the block has any instructions after a J, delete them. 195 MBB.erase(std::next(I), MBB.end()); 196 Cond.clear(); 197 FBB = nullptr; 198 199 // Delete the J if it's equivalent to a fall-through. 200 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 201 TBB = nullptr; 202 I->eraseFromParent(); 203 I = MBB.end(); 204 continue; 205 } 206 207 // TBB is used to indicate the unconditinal destination. 208 TBB = I->getOperand(0).getMBB(); 209 continue; 210 } 211 // Cannot handle conditional branches 212 return true; 213 } 214 215 return false; 216 } 217 218 unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB, 219 MachineBasicBlock *TBB, 220 MachineBasicBlock *FBB, 221 ArrayRef<MachineOperand> Cond, 222 const DebugLoc &DL, 223 int *BytesAdded) const { 224 assert(!BytesAdded && "code size not handled"); 225 226 // Shouldn't be a fall through. 227 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 228 229 if (Cond.empty()) { 230 // Unconditional branch 231 assert(!FBB && "Unconditional branch with multiple successors!"); 232 BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); 233 return 1; 234 } 235 236 llvm_unreachable("Unexpected conditional branch"); 237 } 238 239 unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB, 240 int *BytesRemoved) const { 241 assert(!BytesRemoved && "code size not handled"); 242 243 MachineBasicBlock::iterator I = MBB.end(); 244 unsigned Count = 0; 245 246 while (I != MBB.begin()) { 247 --I; 248 if (I->isDebugInstr()) 249 continue; 250 if (I->getOpcode() != BPF::JMP) 251 break; 252 // Remove the branch. 253 I->eraseFromParent(); 254 I = MBB.end(); 255 ++Count; 256 } 257 258 return Count; 259 } 260