LLVM 22.0.0git
BPFMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- BPFMCCodeEmitter.cpp - Convert BPF code to machine code -----------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the BPFMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCFixup.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstrInfo.h"
25#include <cassert>
26#include <cstdint>
27
28using namespace llvm;
29
30#define DEBUG_TYPE "mccodeemitter"
31
32namespace {
33
34class BPFMCCodeEmitter : public MCCodeEmitter {
35 const MCRegisterInfo &MRI;
36 bool IsLittleEndian;
37 MCContext &Ctx;
38
39public:
40 BPFMCCodeEmitter(const MCInstrInfo &, const MCRegisterInfo &mri,
41 bool IsLittleEndian, MCContext &ctx)
42 : MRI(mri), IsLittleEndian(IsLittleEndian), Ctx(ctx) {}
43 BPFMCCodeEmitter(const BPFMCCodeEmitter &) = delete;
44 void operator=(const BPFMCCodeEmitter &) = delete;
45 ~BPFMCCodeEmitter() override = default;
46
47 // getBinaryCodeForInstr - TableGen'erated function for getting the
48 // binary encoding for an instruction.
49 uint64_t getBinaryCodeForInstr(const MCInst &MI,
51 const MCSubtargetInfo &STI) const;
52
53 // getMachineOpValue - Return binary encoding of operand. If the machin
54 // operand requires relocation, record the relocation and return zero.
55 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
57 const MCSubtargetInfo &STI) const;
58
59 uint64_t getMemoryOpValue(const MCInst &MI, unsigned Op,
61 const MCSubtargetInfo &STI) const;
62
63 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
65 const MCSubtargetInfo &STI) const override;
66};
67
68} // end anonymous namespace
69
71 MCContext &Ctx) {
72 return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), true, Ctx);
73}
74
76 MCContext &Ctx) {
77 return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), false, Ctx);
78}
79
81 const MCExpr *Value, uint16_t Kind, bool PCRel = false) {
82 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
83}
84
85unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
86 const MCOperand &MO,
88 const MCSubtargetInfo &STI) const {
89 if (MO.isReg())
90 return MRI.getEncodingValue(MO.getReg());
91 if (MO.isImm()) {
92 uint64_t Imm = MO.getImm();
93 uint64_t High32Bits = Imm >> 32, High33Bits = Imm >> 31;
94 if (MI.getOpcode() != BPF::LD_imm64 && High32Bits != 0 &&
95 High33Bits != 0x1FFFFFFFFULL) {
96 Ctx.reportWarning(MI.getLoc(),
97 "immediate out of range, shall fit in 32 bits");
98 }
99 return static_cast<unsigned>(Imm);
100 }
101
102 assert(MO.isExpr());
103
104 const MCExpr *Expr = MO.getExpr();
105
106 assert(Expr->getKind() == MCExpr::SymbolRef);
107
108 if (MI.getOpcode() == BPF::JAL)
109 // func call name
110 addFixup(Fixups, 0, Expr, FK_Data_4, true);
111 else if (MI.getOpcode() == BPF::LD_imm64)
112 addFixup(Fixups, 0, Expr, FK_SecRel_8);
113 else if (MI.getOpcode() == BPF::JMPL)
114 addFixup(Fixups, 0, Expr, BPF::FK_BPF_PCRel_4, true);
115 else
116 // bb label
117 addFixup(Fixups, 0, Expr, FK_Data_2, true);
118
119 return 0;
120}
121
123{
124 return (Val & 0x0F) << 4 | (Val & 0xF0) >> 4;
125}
126
127void BPFMCCodeEmitter::encodeInstruction(const MCInst &MI,
128 SmallVectorImpl<char> &CB,
129 SmallVectorImpl<MCFixup> &Fixups,
130 const MCSubtargetInfo &STI) const {
131 unsigned Opcode = MI.getOpcode();
132 raw_svector_ostream OS(CB);
133 support::endian::Writer OSE(OS, IsLittleEndian ? llvm::endianness::little
135
136 if (Opcode == BPF::LD_imm64 || Opcode == BPF::LD_pseudo) {
137 uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI);
138 CB.push_back(Value >> 56);
139 if (IsLittleEndian)
140 CB.push_back((Value >> 48) & 0xff);
141 else
142 CB.push_back(SwapBits((Value >> 48) & 0xff));
143 OSE.write<uint16_t>(0);
144 OSE.write<uint32_t>(Value & 0xffffFFFF);
145
146 const MCOperand &MO = MI.getOperand(1);
147 uint64_t Imm = MO.isImm() ? MO.getImm() : 0;
148 OSE.write<uint8_t>(0);
149 OSE.write<uint8_t>(0);
150 OSE.write<uint16_t>(0);
151 OSE.write<uint32_t>(Imm >> 32);
152 } else {
153 // Get instruction encoding and emit it
154 uint64_t Value = getBinaryCodeForInstr(MI, Fixups, STI);
155 CB.push_back(Value >> 56);
156 if (IsLittleEndian)
157 CB.push_back(char((Value >> 48) & 0xff));
158 else
159 CB.push_back(SwapBits((Value >> 48) & 0xff));
160 OSE.write<uint16_t>((Value >> 32) & 0xffff);
161 OSE.write<uint32_t>(Value & 0xffffFFFF);
162 }
163}
164
165// Encode BPF Memory Operand
166uint64_t BPFMCCodeEmitter::getMemoryOpValue(const MCInst &MI, unsigned Op,
167 SmallVectorImpl<MCFixup> &Fixups,
168 const MCSubtargetInfo &STI) const {
169 // For CMPXCHG instructions, output is implicitly in R0/W0,
170 // so memory operand starts from operand 0.
171 int MemOpStartIndex = 1, Opcode = MI.getOpcode();
172 if (Opcode == BPF::CMPXCHGW32 || Opcode == BPF::CMPXCHGD)
173 MemOpStartIndex = 0;
174
175 uint64_t Encoding;
176 const MCOperand Op1 = MI.getOperand(MemOpStartIndex);
177 assert(Op1.isReg() && "First operand is not register.");
178 Encoding = MRI.getEncodingValue(Op1.getReg());
179 Encoding <<= 16;
180 MCOperand Op2 = MI.getOperand(MemOpStartIndex + 1);
181 assert(Op2.isImm() && "Second operand is not immediate.");
182 Encoding |= Op2.getImm() & 0xffff;
183 return Encoding;
184}
185
186#include "BPFGenMCCodeEmitter.inc"
unsigned const MachineRegisterInfo * MRI
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint8_t SwapBits(uint8_t Val)
IRTranslator LLVM IR MI
This file defines the SmallVector class.
MCCodeEmitter - Generic instruction encoding interface.
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI void reportWarning(SMLoc L, const Twine &Msg)
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
@ SymbolRef
References to labels and assigned expressions.
Definition MCExpr.h:43
ExprKind getKind() const
Definition MCExpr.h:85
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
LLVM Value Representation.
Definition Value.h:75
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
@ FK_Data_4
A four-byte fixup.
Definition MCFixup.h:36
@ FK_SecRel_8
A eight-byte section relative fixup.
Definition MCFixup.h:42
@ FK_Data_2
A two-byte fixup.
Definition MCFixup.h:35
DWARFExpression::Operation Op
MCCodeEmitter * createBPFbeMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
MCCodeEmitter * createBPFMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)