1e4c8c807SAlexei Starovoitov //===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===// 2e4c8c807SAlexei Starovoitov // 3e4c8c807SAlexei Starovoitov // The LLVM Compiler Infrastructure 4e4c8c807SAlexei Starovoitov // 5e4c8c807SAlexei Starovoitov // This file is distributed under the University of Illinois Open Source 6e4c8c807SAlexei Starovoitov // License. See LICENSE.TXT for details. 7e4c8c807SAlexei Starovoitov // 8e4c8c807SAlexei Starovoitov //===----------------------------------------------------------------------===// 9e4c8c807SAlexei Starovoitov // 10e4c8c807SAlexei Starovoitov // This file contains the BPF implementation of the TargetInstrInfo class. 11e4c8c807SAlexei Starovoitov // 12e4c8c807SAlexei Starovoitov //===----------------------------------------------------------------------===// 13e4c8c807SAlexei Starovoitov 14e4c8c807SAlexei Starovoitov #include "BPFInstrInfo.h" 156bda14b3SChandler Carruth #include "BPF.h" 16e4c8c807SAlexei Starovoitov #include "llvm/ADT/SmallVector.h" 174282c404SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h" 184282c404SEugene Zelenko #include "llvm/CodeGen/MachineInstrBuilder.h" 194282c404SEugene Zelenko #include "llvm/IR/DebugLoc.h" 204282c404SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 214282c404SEugene Zelenko #include <cassert> 224282c404SEugene Zelenko #include <iterator> 23e4c8c807SAlexei Starovoitov 24e4c8c807SAlexei Starovoitov #define GET_INSTRINFO_CTOR_DTOR 25e4c8c807SAlexei Starovoitov #include "BPFGenInstrInfo.inc" 26e4c8c807SAlexei Starovoitov 27e4c8c807SAlexei Starovoitov using namespace llvm; 28e4c8c807SAlexei Starovoitov 29e4c8c807SAlexei Starovoitov BPFInstrInfo::BPFInstrInfo() 30e4c8c807SAlexei Starovoitov : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {} 31e4c8c807SAlexei Starovoitov 32e4c8c807SAlexei Starovoitov void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 33bdc4956bSBenjamin Kramer MachineBasicBlock::iterator I, 34bdc4956bSBenjamin Kramer const DebugLoc &DL, unsigned DestReg, 35bdc4956bSBenjamin Kramer unsigned SrcReg, bool KillSrc) const { 36e4c8c807SAlexei Starovoitov if (BPF::GPRRegClass.contains(DestReg, SrcReg)) 37e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg) 38e4c8c807SAlexei Starovoitov .addReg(SrcReg, getKillRegState(KillSrc)); 39fcd1e0f6SYonghong Song else if (BPF::GPR32RegClass.contains(DestReg, SrcReg)) 40fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg) 41fcd1e0f6SYonghong Song .addReg(SrcReg, getKillRegState(KillSrc)); 42e4c8c807SAlexei Starovoitov else 43e4c8c807SAlexei Starovoitov llvm_unreachable("Impossible reg-to-reg copy"); 44e4c8c807SAlexei Starovoitov } 45e4c8c807SAlexei Starovoitov 46e4c8c807SAlexei Starovoitov void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 47e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 48e4c8c807SAlexei Starovoitov unsigned SrcReg, bool IsKill, int FI, 49e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 50e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 51e4c8c807SAlexei Starovoitov DebugLoc DL; 52e4c8c807SAlexei Starovoitov if (I != MBB.end()) 53e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 54e4c8c807SAlexei Starovoitov 55e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 56e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::STD)) 57e4c8c807SAlexei Starovoitov .addReg(SrcReg, getKillRegState(IsKill)) 58e4c8c807SAlexei Starovoitov .addFrameIndex(FI) 59e4c8c807SAlexei Starovoitov .addImm(0); 60fcd1e0f6SYonghong Song else if (RC == &BPF::GPR32RegClass) 61fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::STW32)) 62fcd1e0f6SYonghong Song .addReg(SrcReg, getKillRegState(IsKill)) 63fcd1e0f6SYonghong Song .addFrameIndex(FI) 64fcd1e0f6SYonghong Song .addImm(0); 65e4c8c807SAlexei Starovoitov else 66e4c8c807SAlexei Starovoitov llvm_unreachable("Can't store this register to stack slot"); 67e4c8c807SAlexei Starovoitov } 68e4c8c807SAlexei Starovoitov 69e4c8c807SAlexei Starovoitov void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 70e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 71e4c8c807SAlexei Starovoitov unsigned DestReg, int FI, 72e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 73e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 74e4c8c807SAlexei Starovoitov DebugLoc DL; 75e4c8c807SAlexei Starovoitov if (I != MBB.end()) 76e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 77e4c8c807SAlexei Starovoitov 78e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 79e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); 80fcd1e0f6SYonghong Song else if (RC == &BPF::GPR32RegClass) 81fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0); 82e4c8c807SAlexei Starovoitov else 83e4c8c807SAlexei Starovoitov llvm_unreachable("Can't load this register from stack slot"); 84e4c8c807SAlexei Starovoitov } 85e4c8c807SAlexei Starovoitov 8671c30a14SJacques Pienaar bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 87e4c8c807SAlexei Starovoitov MachineBasicBlock *&TBB, 88e4c8c807SAlexei Starovoitov MachineBasicBlock *&FBB, 89e4c8c807SAlexei Starovoitov SmallVectorImpl<MachineOperand> &Cond, 90e4c8c807SAlexei Starovoitov bool AllowModify) const { 91e4c8c807SAlexei Starovoitov // Start from the bottom of the block and work up, examining the 92e4c8c807SAlexei Starovoitov // terminator instructions. 93e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 94e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 95e4c8c807SAlexei Starovoitov --I; 96*801bf7ebSShiva Chen if (I->isDebugInstr()) 97e4c8c807SAlexei Starovoitov continue; 98e4c8c807SAlexei Starovoitov 99e4c8c807SAlexei Starovoitov // Working from the bottom, when we see a non-terminator 100e4c8c807SAlexei Starovoitov // instruction, we're done. 1016307eb55SDuncan P. N. Exon Smith if (!isUnpredicatedTerminator(*I)) 102e4c8c807SAlexei Starovoitov break; 103e4c8c807SAlexei Starovoitov 104e4c8c807SAlexei Starovoitov // A terminator that isn't a branch can't easily be handled 105e4c8c807SAlexei Starovoitov // by this analysis. 106e4c8c807SAlexei Starovoitov if (!I->isBranch()) 107e4c8c807SAlexei Starovoitov return true; 108e4c8c807SAlexei Starovoitov 109e4c8c807SAlexei Starovoitov // Handle unconditional branches. 110e4c8c807SAlexei Starovoitov if (I->getOpcode() == BPF::JMP) { 111e4c8c807SAlexei Starovoitov if (!AllowModify) { 112e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 113e4c8c807SAlexei Starovoitov continue; 114e4c8c807SAlexei Starovoitov } 115e4c8c807SAlexei Starovoitov 116e4c8c807SAlexei Starovoitov // If the block has any instructions after a J, delete them. 117e4c8c807SAlexei Starovoitov while (std::next(I) != MBB.end()) 118e4c8c807SAlexei Starovoitov std::next(I)->eraseFromParent(); 119e4c8c807SAlexei Starovoitov Cond.clear(); 1204282c404SEugene Zelenko FBB = nullptr; 121e4c8c807SAlexei Starovoitov 122e4c8c807SAlexei Starovoitov // Delete the J if it's equivalent to a fall-through. 123e4c8c807SAlexei Starovoitov if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 1244282c404SEugene Zelenko TBB = nullptr; 125e4c8c807SAlexei Starovoitov I->eraseFromParent(); 126e4c8c807SAlexei Starovoitov I = MBB.end(); 127e4c8c807SAlexei Starovoitov continue; 128e4c8c807SAlexei Starovoitov } 129e4c8c807SAlexei Starovoitov 130e4c8c807SAlexei Starovoitov // TBB is used to indicate the unconditinal destination. 131e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 132e4c8c807SAlexei Starovoitov continue; 133e4c8c807SAlexei Starovoitov } 134e4c8c807SAlexei Starovoitov // Cannot handle conditional branches 135e4c8c807SAlexei Starovoitov return true; 136e4c8c807SAlexei Starovoitov } 137e4c8c807SAlexei Starovoitov 138e4c8c807SAlexei Starovoitov return false; 139e4c8c807SAlexei Starovoitov } 140e4c8c807SAlexei Starovoitov 141e8e0f5caSMatt Arsenault unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB, 142e4c8c807SAlexei Starovoitov MachineBasicBlock *TBB, 143e4c8c807SAlexei Starovoitov MachineBasicBlock *FBB, 144c88bf543SAhmed Bougacha ArrayRef<MachineOperand> Cond, 145a2b036e8SMatt Arsenault const DebugLoc &DL, 146a2b036e8SMatt Arsenault int *BytesAdded) const { 147a2b036e8SMatt Arsenault assert(!BytesAdded && "code size not handled"); 148a2b036e8SMatt Arsenault 149e4c8c807SAlexei Starovoitov // Shouldn't be a fall through. 150e8e0f5caSMatt Arsenault assert(TBB && "insertBranch must not be told to insert a fallthrough"); 151e4c8c807SAlexei Starovoitov 152e4c8c807SAlexei Starovoitov if (Cond.empty()) { 153e4c8c807SAlexei Starovoitov // Unconditional branch 154e4c8c807SAlexei Starovoitov assert(!FBB && "Unconditional branch with multiple successors!"); 155e4c8c807SAlexei Starovoitov BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); 156e4c8c807SAlexei Starovoitov return 1; 157e4c8c807SAlexei Starovoitov } 158e4c8c807SAlexei Starovoitov 159e4c8c807SAlexei Starovoitov llvm_unreachable("Unexpected conditional branch"); 160e4c8c807SAlexei Starovoitov } 161e4c8c807SAlexei Starovoitov 1621b9fc8edSMatt Arsenault unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB, 163a2b036e8SMatt Arsenault int *BytesRemoved) const { 164a2b036e8SMatt Arsenault assert(!BytesRemoved && "code size not handled"); 165a2b036e8SMatt Arsenault 166e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 167e4c8c807SAlexei Starovoitov unsigned Count = 0; 168e4c8c807SAlexei Starovoitov 169e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 170e4c8c807SAlexei Starovoitov --I; 171*801bf7ebSShiva Chen if (I->isDebugInstr()) 172e4c8c807SAlexei Starovoitov continue; 173e4c8c807SAlexei Starovoitov if (I->getOpcode() != BPF::JMP) 174e4c8c807SAlexei Starovoitov break; 175e4c8c807SAlexei Starovoitov // Remove the branch. 176e4c8c807SAlexei Starovoitov I->eraseFromParent(); 177e4c8c807SAlexei Starovoitov I = MBB.end(); 178e4c8c807SAlexei Starovoitov ++Count; 179e4c8c807SAlexei Starovoitov } 180e4c8c807SAlexei Starovoitov 181e4c8c807SAlexei Starovoitov return Count; 182e4c8c807SAlexei Starovoitov } 183