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