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 "BPF.h" 15e4c8c807SAlexei Starovoitov #include "BPFInstrInfo.h" 16e4c8c807SAlexei Starovoitov #include "llvm/ADT/SmallVector.h" 17*4282c404SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h" 18*4282c404SEugene Zelenko #include "llvm/CodeGen/MachineInstrBuilder.h" 19*4282c404SEugene Zelenko #include "llvm/IR/DebugLoc.h" 20*4282c404SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 21*4282c404SEugene Zelenko #include <cassert> 22*4282c404SEugene 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)); 39e4c8c807SAlexei Starovoitov else 40e4c8c807SAlexei Starovoitov llvm_unreachable("Impossible reg-to-reg copy"); 41e4c8c807SAlexei Starovoitov } 42e4c8c807SAlexei Starovoitov 43e4c8c807SAlexei Starovoitov void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 44e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 45e4c8c807SAlexei Starovoitov unsigned SrcReg, bool IsKill, int FI, 46e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 47e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 48e4c8c807SAlexei Starovoitov DebugLoc DL; 49e4c8c807SAlexei Starovoitov if (I != MBB.end()) 50e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 51e4c8c807SAlexei Starovoitov 52e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 53e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::STD)) 54e4c8c807SAlexei Starovoitov .addReg(SrcReg, getKillRegState(IsKill)) 55e4c8c807SAlexei Starovoitov .addFrameIndex(FI) 56e4c8c807SAlexei Starovoitov .addImm(0); 57e4c8c807SAlexei Starovoitov else 58e4c8c807SAlexei Starovoitov llvm_unreachable("Can't store this register to stack slot"); 59e4c8c807SAlexei Starovoitov } 60e4c8c807SAlexei Starovoitov 61e4c8c807SAlexei Starovoitov void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 62e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 63e4c8c807SAlexei Starovoitov unsigned DestReg, int FI, 64e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 65e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 66e4c8c807SAlexei Starovoitov DebugLoc DL; 67e4c8c807SAlexei Starovoitov if (I != MBB.end()) 68e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 69e4c8c807SAlexei Starovoitov 70e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 71e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); 72e4c8c807SAlexei Starovoitov else 73e4c8c807SAlexei Starovoitov llvm_unreachable("Can't load this register from stack slot"); 74e4c8c807SAlexei Starovoitov } 75e4c8c807SAlexei Starovoitov 7671c30a14SJacques Pienaar bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 77e4c8c807SAlexei Starovoitov MachineBasicBlock *&TBB, 78e4c8c807SAlexei Starovoitov MachineBasicBlock *&FBB, 79e4c8c807SAlexei Starovoitov SmallVectorImpl<MachineOperand> &Cond, 80e4c8c807SAlexei Starovoitov bool AllowModify) const { 81e4c8c807SAlexei Starovoitov // Start from the bottom of the block and work up, examining the 82e4c8c807SAlexei Starovoitov // terminator instructions. 83e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 84e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 85e4c8c807SAlexei Starovoitov --I; 86e4c8c807SAlexei Starovoitov if (I->isDebugValue()) 87e4c8c807SAlexei Starovoitov continue; 88e4c8c807SAlexei Starovoitov 89e4c8c807SAlexei Starovoitov // Working from the bottom, when we see a non-terminator 90e4c8c807SAlexei Starovoitov // instruction, we're done. 916307eb55SDuncan P. N. Exon Smith if (!isUnpredicatedTerminator(*I)) 92e4c8c807SAlexei Starovoitov break; 93e4c8c807SAlexei Starovoitov 94e4c8c807SAlexei Starovoitov // A terminator that isn't a branch can't easily be handled 95e4c8c807SAlexei Starovoitov // by this analysis. 96e4c8c807SAlexei Starovoitov if (!I->isBranch()) 97e4c8c807SAlexei Starovoitov return true; 98e4c8c807SAlexei Starovoitov 99e4c8c807SAlexei Starovoitov // Handle unconditional branches. 100e4c8c807SAlexei Starovoitov if (I->getOpcode() == BPF::JMP) { 101e4c8c807SAlexei Starovoitov if (!AllowModify) { 102e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 103e4c8c807SAlexei Starovoitov continue; 104e4c8c807SAlexei Starovoitov } 105e4c8c807SAlexei Starovoitov 106e4c8c807SAlexei Starovoitov // If the block has any instructions after a J, delete them. 107e4c8c807SAlexei Starovoitov while (std::next(I) != MBB.end()) 108e4c8c807SAlexei Starovoitov std::next(I)->eraseFromParent(); 109e4c8c807SAlexei Starovoitov Cond.clear(); 110*4282c404SEugene Zelenko FBB = nullptr; 111e4c8c807SAlexei Starovoitov 112e4c8c807SAlexei Starovoitov // Delete the J if it's equivalent to a fall-through. 113e4c8c807SAlexei Starovoitov if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 114*4282c404SEugene Zelenko TBB = nullptr; 115e4c8c807SAlexei Starovoitov I->eraseFromParent(); 116e4c8c807SAlexei Starovoitov I = MBB.end(); 117e4c8c807SAlexei Starovoitov continue; 118e4c8c807SAlexei Starovoitov } 119e4c8c807SAlexei Starovoitov 120e4c8c807SAlexei Starovoitov // TBB is used to indicate the unconditinal destination. 121e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 122e4c8c807SAlexei Starovoitov continue; 123e4c8c807SAlexei Starovoitov } 124e4c8c807SAlexei Starovoitov // Cannot handle conditional branches 125e4c8c807SAlexei Starovoitov return true; 126e4c8c807SAlexei Starovoitov } 127e4c8c807SAlexei Starovoitov 128e4c8c807SAlexei Starovoitov return false; 129e4c8c807SAlexei Starovoitov } 130e4c8c807SAlexei Starovoitov 131e8e0f5caSMatt Arsenault unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB, 132e4c8c807SAlexei Starovoitov MachineBasicBlock *TBB, 133e4c8c807SAlexei Starovoitov MachineBasicBlock *FBB, 134c88bf543SAhmed Bougacha ArrayRef<MachineOperand> Cond, 135a2b036e8SMatt Arsenault const DebugLoc &DL, 136a2b036e8SMatt Arsenault int *BytesAdded) const { 137a2b036e8SMatt Arsenault assert(!BytesAdded && "code size not handled"); 138a2b036e8SMatt Arsenault 139e4c8c807SAlexei Starovoitov // Shouldn't be a fall through. 140e8e0f5caSMatt Arsenault assert(TBB && "insertBranch must not be told to insert a fallthrough"); 141e4c8c807SAlexei Starovoitov 142e4c8c807SAlexei Starovoitov if (Cond.empty()) { 143e4c8c807SAlexei Starovoitov // Unconditional branch 144e4c8c807SAlexei Starovoitov assert(!FBB && "Unconditional branch with multiple successors!"); 145e4c8c807SAlexei Starovoitov BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); 146e4c8c807SAlexei Starovoitov return 1; 147e4c8c807SAlexei Starovoitov } 148e4c8c807SAlexei Starovoitov 149e4c8c807SAlexei Starovoitov llvm_unreachable("Unexpected conditional branch"); 150e4c8c807SAlexei Starovoitov } 151e4c8c807SAlexei Starovoitov 1521b9fc8edSMatt Arsenault unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB, 153a2b036e8SMatt Arsenault int *BytesRemoved) const { 154a2b036e8SMatt Arsenault assert(!BytesRemoved && "code size not handled"); 155a2b036e8SMatt Arsenault 156e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 157e4c8c807SAlexei Starovoitov unsigned Count = 0; 158e4c8c807SAlexei Starovoitov 159e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 160e4c8c807SAlexei Starovoitov --I; 161e4c8c807SAlexei Starovoitov if (I->isDebugValue()) 162e4c8c807SAlexei Starovoitov continue; 163e4c8c807SAlexei Starovoitov if (I->getOpcode() != BPF::JMP) 164e4c8c807SAlexei Starovoitov break; 165e4c8c807SAlexei Starovoitov // Remove the branch. 166e4c8c807SAlexei Starovoitov I->eraseFromParent(); 167e4c8c807SAlexei Starovoitov I = MBB.end(); 168e4c8c807SAlexei Starovoitov ++Count; 169e4c8c807SAlexei Starovoitov } 170e4c8c807SAlexei Starovoitov 171e4c8c807SAlexei Starovoitov return Count; 172e4c8c807SAlexei Starovoitov } 173