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