You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			173 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.4 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 "BPFInstrInfo.h"
 | |
| #include "BPF.h"
 | |
| #include "llvm/ADT/SmallVector.h"
 | |
| #include "llvm/CodeGen/MachineBasicBlock.h"
 | |
| #include "llvm/CodeGen/MachineInstrBuilder.h"
 | |
| #include "llvm/IR/DebugLoc.h"
 | |
| #include "llvm/Support/ErrorHandling.h"
 | |
| #include <cassert>
 | |
| #include <iterator>
 | |
| 
 | |
| #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,
 | |
|                                const 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 = nullptr;
 | |
| 
 | |
|       // Delete the J if it's equivalent to a fall-through.
 | |
|       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
 | |
|         TBB = nullptr;
 | |
|         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,
 | |
|                                     const DebugLoc &DL,
 | |
|                                     int *BytesAdded) const {
 | |
|   assert(!BytesAdded && "code size not handled");
 | |
| 
 | |
|   // 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,
 | |
|                                     int *BytesRemoved) const {
 | |
|   assert(!BytesRemoved && "code size not handled");
 | |
| 
 | |
|   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;
 | |
| }
 |