BPFMCCodeEmitter.cpp revision 341825
1283625Sdim//===-- BPFMCCodeEmitter.cpp - Convert BPF code to machine code -----------===// 2283625Sdim// 3283625Sdim// The LLVM Compiler Infrastructure 4283625Sdim// 5283625Sdim// This file is distributed under the University of Illinois Open Source 6283625Sdim// License. See LICENSE.TXT for details. 7283625Sdim// 8283625Sdim//===----------------------------------------------------------------------===// 9283625Sdim// 10283625Sdim// This file implements the BPFMCCodeEmitter class. 11283625Sdim// 12283625Sdim//===----------------------------------------------------------------------===// 13283625Sdim 14283625Sdim#include "MCTargetDesc/BPFMCTargetDesc.h" 15314564Sdim#include "llvm/ADT/SmallVector.h" 16283625Sdim#include "llvm/MC/MCCodeEmitter.h" 17283625Sdim#include "llvm/MC/MCFixup.h" 18283625Sdim#include "llvm/MC/MCInst.h" 19283625Sdim#include "llvm/MC/MCInstrInfo.h" 20283625Sdim#include "llvm/MC/MCRegisterInfo.h" 21283625Sdim#include "llvm/MC/MCSubtargetInfo.h" 22314564Sdim#include "llvm/Support/Endian.h" 23309124Sdim#include "llvm/Support/EndianStream.h" 24314564Sdim#include <cassert> 25314564Sdim#include <cstdint> 26314564Sdim 27283625Sdimusing namespace llvm; 28283625Sdim 29283625Sdim#define DEBUG_TYPE "mccodeemitter" 30283625Sdim 31283625Sdimnamespace { 32314564Sdim 33283625Sdimclass BPFMCCodeEmitter : public MCCodeEmitter { 34314564Sdim const MCInstrInfo &MCII; 35283625Sdim const MCRegisterInfo &MRI; 36284236Sdim bool IsLittleEndian; 37283625Sdim 38283625Sdimpublic: 39314564Sdim BPFMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri, 40314564Sdim bool IsLittleEndian) 41314564Sdim : MCII(mcii), MRI(mri), IsLittleEndian(IsLittleEndian) {} 42314564Sdim BPFMCCodeEmitter(const BPFMCCodeEmitter &) = delete; 43314564Sdim void operator=(const BPFMCCodeEmitter &) = delete; 44314564Sdim ~BPFMCCodeEmitter() override = default; 45283625Sdim 46283625Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 47283625Sdim // binary encoding for an instruction. 48283625Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 49283625Sdim SmallVectorImpl<MCFixup> &Fixups, 50283625Sdim const MCSubtargetInfo &STI) const; 51283625Sdim 52283625Sdim // getMachineOpValue - Return binary encoding of operand. If the machin 53283625Sdim // operand requires relocation, record the relocation and return zero. 54283625Sdim unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 55283625Sdim SmallVectorImpl<MCFixup> &Fixups, 56283625Sdim const MCSubtargetInfo &STI) const; 57283625Sdim 58283625Sdim uint64_t getMemoryOpValue(const MCInst &MI, unsigned Op, 59283625Sdim SmallVectorImpl<MCFixup> &Fixups, 60283625Sdim const MCSubtargetInfo &STI) const; 61283625Sdim 62283625Sdim void encodeInstruction(const MCInst &MI, raw_ostream &OS, 63283625Sdim SmallVectorImpl<MCFixup> &Fixups, 64283625Sdim const MCSubtargetInfo &STI) const override; 65314564Sdim 66314564Sdimprivate: 67314564Sdim uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; 68314564Sdim void verifyInstructionPredicates(const MCInst &MI, 69314564Sdim uint64_t AvailableFeatures) const; 70283625Sdim}; 71283625Sdim 72314564Sdim} // end anonymous namespace 73314564Sdim 74283625SdimMCCodeEmitter *llvm::createBPFMCCodeEmitter(const MCInstrInfo &MCII, 75283625Sdim const MCRegisterInfo &MRI, 76283625Sdim MCContext &Ctx) { 77314564Sdim return new BPFMCCodeEmitter(MCII, MRI, true); 78283625Sdim} 79283625Sdim 80284236SdimMCCodeEmitter *llvm::createBPFbeMCCodeEmitter(const MCInstrInfo &MCII, 81284236Sdim const MCRegisterInfo &MRI, 82284236Sdim MCContext &Ctx) { 83314564Sdim return new BPFMCCodeEmitter(MCII, MRI, false); 84284236Sdim} 85284236Sdim 86283625Sdimunsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI, 87283625Sdim const MCOperand &MO, 88283625Sdim SmallVectorImpl<MCFixup> &Fixups, 89283625Sdim const MCSubtargetInfo &STI) const { 90283625Sdim if (MO.isReg()) 91283625Sdim return MRI.getEncodingValue(MO.getReg()); 92283625Sdim if (MO.isImm()) 93283625Sdim return static_cast<unsigned>(MO.getImm()); 94283625Sdim 95283625Sdim assert(MO.isExpr()); 96283625Sdim 97283625Sdim const MCExpr *Expr = MO.getExpr(); 98283625Sdim 99283625Sdim assert(Expr->getKind() == MCExpr::SymbolRef); 100283625Sdim 101283625Sdim if (MI.getOpcode() == BPF::JAL) 102283625Sdim // func call name 103327952Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_4)); 104283625Sdim else if (MI.getOpcode() == BPF::LD_imm64) 105283625Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8)); 106283625Sdim else 107283625Sdim // bb label 108283625Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_2)); 109283625Sdim 110283625Sdim return 0; 111283625Sdim} 112283625Sdim 113284236Sdimstatic uint8_t SwapBits(uint8_t Val) 114284236Sdim{ 115284236Sdim return (Val & 0x0F) << 4 | (Val & 0xF0) >> 4; 116283625Sdim} 117283625Sdim 118283625Sdimvoid BPFMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 119283625Sdim SmallVectorImpl<MCFixup> &Fixups, 120283625Sdim const MCSubtargetInfo &STI) const { 121314564Sdim verifyInstructionPredicates(MI, 122314564Sdim computeAvailableFeatures(STI.getFeatureBits())); 123314564Sdim 124283625Sdim unsigned Opcode = MI.getOpcode(); 125341825Sdim support::endian::Writer OSE(OS, 126341825Sdim IsLittleEndian ? support::little : support::big); 127283625Sdim 128283625Sdim if (Opcode == BPF::LD_imm64 || Opcode == BPF::LD_pseudo) { 129283625Sdim uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI); 130341825Sdim OS << char(Value >> 56); 131284236Sdim if (IsLittleEndian) 132341825Sdim OS << char((Value >> 48) & 0xff); 133284236Sdim else 134341825Sdim OS << char(SwapBits((Value >> 48) & 0xff)); 135341825Sdim OSE.write<uint16_t>(0); 136341825Sdim OSE.write<uint32_t>(Value & 0xffffFFFF); 137283625Sdim 138283625Sdim const MCOperand &MO = MI.getOperand(1); 139283625Sdim uint64_t Imm = MO.isImm() ? MO.getImm() : 0; 140341825Sdim OSE.write<uint8_t>(0); 141341825Sdim OSE.write<uint8_t>(0); 142341825Sdim OSE.write<uint16_t>(0); 143341825Sdim OSE.write<uint32_t>(Imm >> 32); 144283625Sdim } else { 145283625Sdim // Get instruction encoding and emit it 146283625Sdim uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI); 147341825Sdim OS << char(Value >> 56); 148341825Sdim if (IsLittleEndian) 149341825Sdim OS << char((Value >> 48) & 0xff); 150341825Sdim else 151341825Sdim OS << char(SwapBits((Value >> 48) & 0xff)); 152341825Sdim OSE.write<uint16_t>((Value >> 32) & 0xffff); 153341825Sdim OSE.write<uint32_t>(Value & 0xffffFFFF); 154283625Sdim } 155283625Sdim} 156283625Sdim 157283625Sdim// Encode BPF Memory Operand 158283625Sdimuint64_t BPFMCCodeEmitter::getMemoryOpValue(const MCInst &MI, unsigned Op, 159283625Sdim SmallVectorImpl<MCFixup> &Fixups, 160283625Sdim const MCSubtargetInfo &STI) const { 161283625Sdim uint64_t Encoding; 162283625Sdim const MCOperand Op1 = MI.getOperand(1); 163283625Sdim assert(Op1.isReg() && "First operand is not register."); 164283625Sdim Encoding = MRI.getEncodingValue(Op1.getReg()); 165283625Sdim Encoding <<= 16; 166283625Sdim MCOperand Op2 = MI.getOperand(2); 167283625Sdim assert(Op2.isImm() && "Second operand is not immediate."); 168283625Sdim Encoding |= Op2.getImm() & 0xffff; 169283625Sdim return Encoding; 170283625Sdim} 171283625Sdim 172314564Sdim#define ENABLE_INSTR_PREDICATE_VERIFIER 173283625Sdim#include "BPFGenMCCodeEmitter.inc" 174