brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · 095e249 Raw
309 lines · cpp
1//===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the BPF implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "BPFInstrInfo.h"14#include "BPF.h"15#include "BPFSubtarget.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_DTOR25#include "BPFGenInstrInfo.inc"26 27using namespace llvm;28 29BPFInstrInfo::BPFInstrInfo(const BPFSubtarget &STI)30    : BPFGenInstrInfo(STI, RI, BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}31 32void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,33                               MachineBasicBlock::iterator I,34                               const DebugLoc &DL, Register DestReg,35                               Register SrcReg, bool KillSrc,36                               bool RenamableDest, bool RenamableSrc) const {37  if (BPF::GPRRegClass.contains(DestReg, SrcReg))38    BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)39        .addReg(SrcReg, getKillRegState(KillSrc));40  else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))41    BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)42        .addReg(SrcReg, getKillRegState(KillSrc));43  else44    llvm_unreachable("Impossible reg-to-reg copy");45}46 47void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {48  Register DstReg = MI->getOperand(0).getReg();49  Register SrcReg = MI->getOperand(1).getReg();50  uint64_t CopyLen = MI->getOperand(2).getImm();51  uint64_t Alignment = MI->getOperand(3).getImm();52  Register ScratchReg = MI->getOperand(4).getReg();53  MachineBasicBlock *BB = MI->getParent();54  DebugLoc dl = MI->getDebugLoc();55  unsigned LdOpc, StOpc;56 57  switch (Alignment) {58  case 1:59    LdOpc = BPF::LDB;60    StOpc = BPF::STB;61    break;62  case 2:63    LdOpc = BPF::LDH;64    StOpc = BPF::STH;65    break;66  case 4:67    LdOpc = BPF::LDW;68    StOpc = BPF::STW;69    break;70  case 8:71    LdOpc = BPF::LDD;72    StOpc = BPF::STD;73    break;74  default:75    llvm_unreachable("unsupported memcpy alignment");76  }77 78  unsigned IterationNum = CopyLen >> Log2_64(Alignment);79  for(unsigned I = 0; I < IterationNum; ++I) {80    BuildMI(*BB, MI, dl, get(LdOpc))81            .addReg(ScratchReg, RegState::Define).addReg(SrcReg)82            .addImm(I * Alignment);83    BuildMI(*BB, MI, dl, get(StOpc))84            .addReg(ScratchReg, RegState::Kill).addReg(DstReg)85            .addImm(I * Alignment);86  }87 88  unsigned BytesLeft = CopyLen & (Alignment - 1);89  unsigned Offset = IterationNum * Alignment;90  bool Hanging4Byte = BytesLeft & 0x4;91  bool Hanging2Byte = BytesLeft & 0x2;92  bool Hanging1Byte = BytesLeft & 0x1;93  if (Hanging4Byte) {94    BuildMI(*BB, MI, dl, get(BPF::LDW))95            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);96    BuildMI(*BB, MI, dl, get(BPF::STW))97            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);98    Offset += 4;99  }100  if (Hanging2Byte) {101    BuildMI(*BB, MI, dl, get(BPF::LDH))102            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);103    BuildMI(*BB, MI, dl, get(BPF::STH))104            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);105    Offset += 2;106  }107  if (Hanging1Byte) {108    BuildMI(*BB, MI, dl, get(BPF::LDB))109            .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);110    BuildMI(*BB, MI, dl, get(BPF::STB))111            .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);112  }113 114  BB->erase(MI);115}116 117bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {118  if (MI.getOpcode() == BPF::MEMCPY) {119    expandMEMCPY(MI);120    return true;121  }122 123  return false;124}125 126void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,127                                       MachineBasicBlock::iterator I,128                                       Register SrcReg, bool IsKill, int FI,129                                       const TargetRegisterClass *RC,130                                       Register VReg,131                                       MachineInstr::MIFlag Flags) const {132  DebugLoc DL;133  if (I != MBB.end())134    DL = I->getDebugLoc();135 136  if (RC == &BPF::GPRRegClass)137    BuildMI(MBB, I, DL, get(BPF::STD))138        .addReg(SrcReg, getKillRegState(IsKill))139        .addFrameIndex(FI)140        .addImm(0);141  else if (RC == &BPF::GPR32RegClass)142    BuildMI(MBB, I, DL, get(BPF::STW32))143        .addReg(SrcReg, getKillRegState(IsKill))144        .addFrameIndex(FI)145        .addImm(0);146  else147    llvm_unreachable("Can't store this register to stack slot");148}149 150void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,151                                        MachineBasicBlock::iterator I,152                                        Register DestReg, int FI,153                                        const TargetRegisterClass *RC,154                                        Register VReg,155                                        MachineInstr::MIFlag Flags) const {156  DebugLoc DL;157  if (I != MBB.end())158    DL = I->getDebugLoc();159 160  if (RC == &BPF::GPRRegClass)161    BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);162  else if (RC == &BPF::GPR32RegClass)163    BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);164  else165    llvm_unreachable("Can't load this register from stack slot");166}167 168bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,169                                 MachineBasicBlock *&TBB,170                                 MachineBasicBlock *&FBB,171                                 SmallVectorImpl<MachineOperand> &Cond,172                                 bool AllowModify) const {173  // Start from the bottom of the block and work up, examining the174  // terminator instructions.175  MachineBasicBlock::iterator I = MBB.end();176  while (I != MBB.begin()) {177    --I;178    if (I->isDebugInstr())179      continue;180 181    // Working from the bottom, when we see a non-terminator182    // instruction, we're done.183    if (!isUnpredicatedTerminator(*I))184      break;185 186    // From base method doc: ... returning true if it cannot be understood ...187    // Indirect branch has multiple destinations and no true/false concepts.188    if (I->isIndirectBranch())189      return true;190 191    // A terminator that isn't a branch can't easily be handled192    // by this analysis.193    if (!I->isBranch())194      return true;195 196    // Handle unconditional branches.197    if (I->getOpcode() == BPF::JMP) {198      if (!AllowModify) {199        TBB = I->getOperand(0).getMBB();200        continue;201      }202 203      // If the block has any instructions after a J, delete them.204      MBB.erase(std::next(I), MBB.end());205      Cond.clear();206      FBB = nullptr;207 208      // Delete the J if it's equivalent to a fall-through.209      if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {210        TBB = nullptr;211        I->eraseFromParent();212        I = MBB.end();213        continue;214      }215 216      // TBB is used to indicate the unconditinal destination.217      TBB = I->getOperand(0).getMBB();218      continue;219    }220    // Cannot handle conditional branches221    return true;222  }223 224  return false;225}226 227unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,228                                    MachineBasicBlock *TBB,229                                    MachineBasicBlock *FBB,230                                    ArrayRef<MachineOperand> Cond,231                                    const DebugLoc &DL,232                                    int *BytesAdded) const {233  assert(!BytesAdded && "code size not handled");234 235  // Shouldn't be a fall through.236  assert(TBB && "insertBranch must not be told to insert a fallthrough");237 238  if (Cond.empty()) {239    // Unconditional branch240    assert(!FBB && "Unconditional branch with multiple successors!");241    BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);242    return 1;243  }244 245  llvm_unreachable("Unexpected conditional branch");246}247 248unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,249                                    int *BytesRemoved) const {250  assert(!BytesRemoved && "code size not handled");251 252  MachineBasicBlock::iterator I = MBB.end();253  unsigned Count = 0;254 255  while (I != MBB.begin()) {256    --I;257    if (I->isDebugInstr())258      continue;259    if (I->getOpcode() != BPF::JMP)260      break;261    // Remove the branch.262    I->eraseFromParent();263    I = MBB.end();264    ++Count;265  }266 267  return Count;268}269 270int BPFInstrInfo::getJumpTableIndex(const MachineInstr &MI) const {271  if (MI.getOpcode() != BPF::JX)272    return -1;273 274  // The pattern looks like:275  // %0 = LD_imm64 %jump-table.0   ; load jump-table address276  // %1 = ADD_rr %0, $another_reg  ; address + offset277  // %2 = LDD %1, 0                ; load the actual label278  // JX %2279  const MachineFunction &MF = *MI.getParent()->getParent();280  const MachineRegisterInfo &MRI = MF.getRegInfo();281 282  Register Reg = MI.getOperand(0).getReg();283  if (!Reg.isVirtual())284    return -1;285  MachineInstr *Ldd = MRI.getUniqueVRegDef(Reg);286  if (Ldd == nullptr || Ldd->getOpcode() != BPF::LDD)287    return -1;288 289  Reg = Ldd->getOperand(1).getReg();290  if (!Reg.isVirtual())291    return -1;292  MachineInstr *Add = MRI.getUniqueVRegDef(Reg);293  if (Add == nullptr || Add->getOpcode() != BPF::ADD_rr)294    return -1;295 296  Reg = Add->getOperand(1).getReg();297  if (!Reg.isVirtual())298    return -1;299  MachineInstr *LDimm64 = MRI.getUniqueVRegDef(Reg);300  if (LDimm64 == nullptr || LDimm64->getOpcode() != BPF::LD_imm64)301    return -1;302 303  const MachineOperand &MO = LDimm64->getOperand(1);304  if (!MO.isJTI())305    return -1;306 307  return MO.getIndex();308}309