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