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"
15*6bda14b3SChandler 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));
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();
1104282c404SEugene 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())) {
1144282c404SEugene 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