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