BPFMCCodeEmitter.cpp revision 284236
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" 15283625Sdim#include "llvm/MC/MCCodeEmitter.h" 16283625Sdim#include "llvm/MC/MCFixup.h" 17283625Sdim#include "llvm/MC/MCInst.h" 18283625Sdim#include "llvm/MC/MCInstrInfo.h" 19283625Sdim#include "llvm/MC/MCRegisterInfo.h" 20283625Sdim#include "llvm/MC/MCSubtargetInfo.h" 21283625Sdim#include "llvm/MC/MCSymbol.h" 22283625Sdim#include "llvm/ADT/Statistic.h" 23283625Sdim#include "llvm/Support/raw_ostream.h" 24283625Sdimusing namespace llvm; 25283625Sdim 26283625Sdim#define DEBUG_TYPE "mccodeemitter" 27283625Sdim 28283625Sdimnamespace { 29283625Sdimclass BPFMCCodeEmitter : public MCCodeEmitter { 30283625Sdim BPFMCCodeEmitter(const BPFMCCodeEmitter &) = delete; 31283625Sdim void operator=(const BPFMCCodeEmitter &) = delete; 32283625Sdim const MCRegisterInfo &MRI; 33284236Sdim bool IsLittleEndian; 34283625Sdim 35283625Sdimpublic: 36284236Sdim BPFMCCodeEmitter(const MCRegisterInfo &mri, bool IsLittleEndian) 37284236Sdim : MRI(mri), IsLittleEndian(IsLittleEndian) {} 38283625Sdim 39283625Sdim ~BPFMCCodeEmitter() {} 40283625Sdim 41283625Sdim // getBinaryCodeForInstr - TableGen'erated function for getting the 42283625Sdim // binary encoding for an instruction. 43283625Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 44283625Sdim SmallVectorImpl<MCFixup> &Fixups, 45283625Sdim const MCSubtargetInfo &STI) const; 46283625Sdim 47283625Sdim // getMachineOpValue - Return binary encoding of operand. If the machin 48283625Sdim // operand requires relocation, record the relocation and return zero. 49283625Sdim unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 50283625Sdim SmallVectorImpl<MCFixup> &Fixups, 51283625Sdim const MCSubtargetInfo &STI) const; 52283625Sdim 53283625Sdim uint64_t getMemoryOpValue(const MCInst &MI, unsigned Op, 54283625Sdim SmallVectorImpl<MCFixup> &Fixups, 55283625Sdim const MCSubtargetInfo &STI) const; 56283625Sdim 57283625Sdim void encodeInstruction(const MCInst &MI, raw_ostream &OS, 58283625Sdim SmallVectorImpl<MCFixup> &Fixups, 59283625Sdim const MCSubtargetInfo &STI) const override; 60283625Sdim}; 61283625Sdim} 62283625Sdim 63283625SdimMCCodeEmitter *llvm::createBPFMCCodeEmitter(const MCInstrInfo &MCII, 64283625Sdim const MCRegisterInfo &MRI, 65283625Sdim MCContext &Ctx) { 66284236Sdim return new BPFMCCodeEmitter(MRI, true); 67283625Sdim} 68283625Sdim 69284236SdimMCCodeEmitter *llvm::createBPFbeMCCodeEmitter(const MCInstrInfo &MCII, 70284236Sdim const MCRegisterInfo &MRI, 71284236Sdim MCContext &Ctx) { 72284236Sdim return new BPFMCCodeEmitter(MRI, false); 73284236Sdim} 74284236Sdim 75283625Sdimunsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI, 76283625Sdim const MCOperand &MO, 77283625Sdim SmallVectorImpl<MCFixup> &Fixups, 78283625Sdim const MCSubtargetInfo &STI) const { 79283625Sdim if (MO.isReg()) 80283625Sdim return MRI.getEncodingValue(MO.getReg()); 81283625Sdim if (MO.isImm()) 82283625Sdim return static_cast<unsigned>(MO.getImm()); 83283625Sdim 84283625Sdim assert(MO.isExpr()); 85283625Sdim 86283625Sdim const MCExpr *Expr = MO.getExpr(); 87283625Sdim 88283625Sdim assert(Expr->getKind() == MCExpr::SymbolRef); 89283625Sdim 90283625Sdim if (MI.getOpcode() == BPF::JAL) 91283625Sdim // func call name 92283625Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_4)); 93283625Sdim else if (MI.getOpcode() == BPF::LD_imm64) 94283625Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8)); 95283625Sdim else 96283625Sdim // bb label 97283625Sdim Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_2)); 98283625Sdim 99283625Sdim return 0; 100283625Sdim} 101283625Sdim 102284236Sdimstatic uint8_t SwapBits(uint8_t Val) 103284236Sdim{ 104284236Sdim return (Val & 0x0F) << 4 | (Val & 0xF0) >> 4; 105283625Sdim} 106283625Sdim 107283625Sdimvoid BPFMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 108283625Sdim SmallVectorImpl<MCFixup> &Fixups, 109283625Sdim const MCSubtargetInfo &STI) const { 110283625Sdim unsigned Opcode = MI.getOpcode(); 111284236Sdim support::endian::Writer<support::little> LE(OS); 112284236Sdim support::endian::Writer<support::big> BE(OS); 113283625Sdim 114283625Sdim if (Opcode == BPF::LD_imm64 || Opcode == BPF::LD_pseudo) { 115283625Sdim uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI); 116284236Sdim LE.write<uint8_t>(Value >> 56); 117284236Sdim if (IsLittleEndian) 118284236Sdim LE.write<uint8_t>((Value >> 48) & 0xff); 119284236Sdim else 120284236Sdim LE.write<uint8_t>(SwapBits((Value >> 48) & 0xff)); 121284236Sdim LE.write<uint16_t>(0); 122284236Sdim if (IsLittleEndian) 123284236Sdim LE.write<uint32_t>(Value & 0xffffFFFF); 124284236Sdim else 125284236Sdim BE.write<uint32_t>(Value & 0xffffFFFF); 126283625Sdim 127283625Sdim const MCOperand &MO = MI.getOperand(1); 128283625Sdim uint64_t Imm = MO.isImm() ? MO.getImm() : 0; 129284236Sdim LE.write<uint8_t>(0); 130284236Sdim LE.write<uint8_t>(0); 131284236Sdim LE.write<uint16_t>(0); 132284236Sdim if (IsLittleEndian) 133284236Sdim LE.write<uint32_t>(Imm >> 32); 134284236Sdim else 135284236Sdim BE.write<uint32_t>(Imm >> 32); 136283625Sdim } else { 137283625Sdim // Get instruction encoding and emit it 138283625Sdim uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI); 139284236Sdim LE.write<uint8_t>(Value >> 56); 140284236Sdim if (IsLittleEndian) { 141284236Sdim LE.write<uint8_t>((Value >> 48) & 0xff); 142284236Sdim LE.write<uint16_t>((Value >> 32) & 0xffff); 143284236Sdim LE.write<uint32_t>(Value & 0xffffFFFF); 144284236Sdim } else { 145284236Sdim LE.write<uint8_t>(SwapBits((Value >> 48) & 0xff)); 146284236Sdim BE.write<uint16_t>((Value >> 32) & 0xffff); 147284236Sdim BE.write<uint32_t>(Value & 0xffffFFFF); 148284236Sdim } 149283625Sdim } 150283625Sdim} 151283625Sdim 152283625Sdim// Encode BPF Memory Operand 153283625Sdimuint64_t BPFMCCodeEmitter::getMemoryOpValue(const MCInst &MI, unsigned Op, 154283625Sdim SmallVectorImpl<MCFixup> &Fixups, 155283625Sdim const MCSubtargetInfo &STI) const { 156283625Sdim uint64_t Encoding; 157283625Sdim const MCOperand Op1 = MI.getOperand(1); 158283625Sdim assert(Op1.isReg() && "First operand is not register."); 159283625Sdim Encoding = MRI.getEncodingValue(Op1.getReg()); 160283625Sdim Encoding <<= 16; 161283625Sdim MCOperand Op2 = MI.getOperand(2); 162283625Sdim assert(Op2.isImm() && "Second operand is not immediate."); 163283625Sdim Encoding |= Op2.getImm() & 0xffff; 164283625Sdim return Encoding; 165283625Sdim} 166283625Sdim 167283625Sdim#include "BPFGenMCCodeEmitter.inc" 168