forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			169 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file contains the BPF implementation of the TargetInstrInfo class.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "BPF.h"
 | 
						|
#include "BPFInstrInfo.h"
 | 
						|
#include "BPFSubtarget.h"
 | 
						|
#include "BPFTargetMachine.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionPass.h"
 | 
						|
#include "llvm/CodeGen/MachineInstrBuilder.h"
 | 
						|
#include "llvm/CodeGen/MachineRegisterInfo.h"
 | 
						|
#include "llvm/Support/ErrorHandling.h"
 | 
						|
#include "llvm/Support/TargetRegistry.h"
 | 
						|
#include "llvm/ADT/STLExtras.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
 | 
						|
#define GET_INSTRINFO_CTOR_DTOR
 | 
						|
#include "BPFGenInstrInfo.inc"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
BPFInstrInfo::BPFInstrInfo()
 | 
						|
    : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
 | 
						|
 | 
						|
void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 | 
						|
                               MachineBasicBlock::iterator I, DebugLoc DL,
 | 
						|
                               unsigned DestReg, unsigned SrcReg,
 | 
						|
                               bool KillSrc) const {
 | 
						|
  if (BPF::GPRRegClass.contains(DestReg, SrcReg))
 | 
						|
    BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
 | 
						|
        .addReg(SrcReg, getKillRegState(KillSrc));
 | 
						|
  else
 | 
						|
    llvm_unreachable("Impossible reg-to-reg copy");
 | 
						|
}
 | 
						|
 | 
						|
void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
 | 
						|
                                       MachineBasicBlock::iterator I,
 | 
						|
                                       unsigned SrcReg, bool IsKill, int FI,
 | 
						|
                                       const TargetRegisterClass *RC,
 | 
						|
                                       const TargetRegisterInfo *TRI) const {
 | 
						|
  DebugLoc DL;
 | 
						|
  if (I != MBB.end())
 | 
						|
    DL = I->getDebugLoc();
 | 
						|
 | 
						|
  if (RC == &BPF::GPRRegClass)
 | 
						|
    BuildMI(MBB, I, DL, get(BPF::STD))
 | 
						|
        .addReg(SrcReg, getKillRegState(IsKill))
 | 
						|
        .addFrameIndex(FI)
 | 
						|
        .addImm(0);
 | 
						|
  else
 | 
						|
    llvm_unreachable("Can't store this register to stack slot");
 | 
						|
}
 | 
						|
 | 
						|
void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
 | 
						|
                                        MachineBasicBlock::iterator I,
 | 
						|
                                        unsigned DestReg, int FI,
 | 
						|
                                        const TargetRegisterClass *RC,
 | 
						|
                                        const TargetRegisterInfo *TRI) const {
 | 
						|
  DebugLoc DL;
 | 
						|
  if (I != MBB.end())
 | 
						|
    DL = I->getDebugLoc();
 | 
						|
 | 
						|
  if (RC == &BPF::GPRRegClass)
 | 
						|
    BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
 | 
						|
  else
 | 
						|
    llvm_unreachable("Can't load this register from stack slot");
 | 
						|
}
 | 
						|
 | 
						|
bool BPFInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
 | 
						|
                                 MachineBasicBlock *&TBB,
 | 
						|
                                 MachineBasicBlock *&FBB,
 | 
						|
                                 SmallVectorImpl<MachineOperand> &Cond,
 | 
						|
                                 bool AllowModify) const {
 | 
						|
  // Start from the bottom of the block and work up, examining the
 | 
						|
  // terminator instructions.
 | 
						|
  MachineBasicBlock::iterator I = MBB.end();
 | 
						|
  while (I != MBB.begin()) {
 | 
						|
    --I;
 | 
						|
    if (I->isDebugValue())
 | 
						|
      continue;
 | 
						|
 | 
						|
    // Working from the bottom, when we see a non-terminator
 | 
						|
    // instruction, we're done.
 | 
						|
    if (!isUnpredicatedTerminator(I))
 | 
						|
      break;
 | 
						|
 | 
						|
    // A terminator that isn't a branch can't easily be handled
 | 
						|
    // by this analysis.
 | 
						|
    if (!I->isBranch())
 | 
						|
      return true;
 | 
						|
 | 
						|
    // Handle unconditional branches.
 | 
						|
    if (I->getOpcode() == BPF::JMP) {
 | 
						|
      if (!AllowModify) {
 | 
						|
        TBB = I->getOperand(0).getMBB();
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // If the block has any instructions after a J, delete them.
 | 
						|
      while (std::next(I) != MBB.end())
 | 
						|
        std::next(I)->eraseFromParent();
 | 
						|
      Cond.clear();
 | 
						|
      FBB = 0;
 | 
						|
 | 
						|
      // Delete the J if it's equivalent to a fall-through.
 | 
						|
      if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
 | 
						|
        TBB = 0;
 | 
						|
        I->eraseFromParent();
 | 
						|
        I = MBB.end();
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // TBB is used to indicate the unconditinal destination.
 | 
						|
      TBB = I->getOperand(0).getMBB();
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    // Cannot handle conditional branches
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
unsigned BPFInstrInfo::InsertBranch(MachineBasicBlock &MBB,
 | 
						|
                                    MachineBasicBlock *TBB,
 | 
						|
                                    MachineBasicBlock *FBB,
 | 
						|
                                    ArrayRef<MachineOperand> Cond,
 | 
						|
                                    DebugLoc DL) const {
 | 
						|
  // Shouldn't be a fall through.
 | 
						|
  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
 | 
						|
 | 
						|
  if (Cond.empty()) {
 | 
						|
    // Unconditional branch
 | 
						|
    assert(!FBB && "Unconditional branch with multiple successors!");
 | 
						|
    BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  llvm_unreachable("Unexpected conditional branch");
 | 
						|
}
 | 
						|
 | 
						|
unsigned BPFInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
 | 
						|
  MachineBasicBlock::iterator I = MBB.end();
 | 
						|
  unsigned Count = 0;
 | 
						|
 | 
						|
  while (I != MBB.begin()) {
 | 
						|
    --I;
 | 
						|
    if (I->isDebugValue())
 | 
						|
      continue;
 | 
						|
    if (I->getOpcode() != BPF::JMP)
 | 
						|
      break;
 | 
						|
    // Remove the branch.
 | 
						|
    I->eraseFromParent();
 | 
						|
    I = MBB.end();
 | 
						|
    ++Count;
 | 
						|
  }
 | 
						|
 | 
						|
  return Count;
 | 
						|
}
 |