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