LLVM 24.0.0git
BPFAsmPrinter.cpp
Go to the documentation of this file.
1//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//
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 contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to the BPF assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "BPFAsmPrinter.h"
15#include "BPF.h"
16#include "BPFInstrInfo.h"
17#include "BPFMCInstLower.h"
18#include "BTFDebug.h"
32#include "llvm/IR/Analysis.h"
34#include "llvm/IR/Module.h"
35#include "llvm/IR/PassManager.h"
36#include "llvm/MC/MCAsmInfo.h"
37#include "llvm/MC/MCExpr.h"
38#include "llvm/MC/MCInst.h"
40#include "llvm/MC/MCStreamer.h"
41#include "llvm/MC/MCSymbol.h"
42#include "llvm/MC/MCSymbolELF.h"
47using namespace llvm;
48
49#define DEBUG_TYPE "asm-printer"
50
52 std::unique_ptr<MCStreamer> Streamer)
53 : AsmPrinter(TM, std::move(Streamer), ID), BTF(nullptr), TM(TM) {}
54
56
59
60 // Only emit BTF when debuginfo available.
61 if (MAI.doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
62 BTF = new BTFDebug(this);
63 Handlers.push_back(std::unique_ptr<BTFDebug>(BTF));
64 }
65
66 return false;
67}
68
69const BPFTargetMachine &BPFAsmPrinter::getBTM() const {
70 return static_cast<const BPFTargetMachine &>(TM);
71}
72
74 // Remove unused globals which are previously used for jump table.
75 const BPFSubtarget *Subtarget = getBTM().getSubtargetImpl();
76 if (Subtarget->hasGotox()) {
77 std::vector<GlobalVariable *> Targets;
78 for (GlobalVariable &Global : M.globals()) {
79 if (Global.getLinkage() != GlobalValue::PrivateLinkage)
80 continue;
81 if (!Global.isConstant() || !Global.hasInitializer())
82 continue;
83
84 Constant *CV = dyn_cast<Constant>(Global.getInitializer());
85 if (!CV)
86 continue;
88 if (!CA)
89 continue;
90
91 if (!all_of(CA->operands(),
92 [](const Use &Op) { return isa<BlockAddress>(Op); }))
93 continue;
94 Targets.push_back(&Global);
95 }
96
97 for (GlobalVariable *GV : Targets) {
98 GV->replaceAllUsesWith(PoisonValue::get(GV->getType()));
99 GV->dropAllReferences();
100 GV->eraseFromParent();
101 }
102 }
103
104 for (GlobalObject &GO : M.global_objects()) {
105 if (!GO.hasExternalWeakLinkage())
106 continue;
107
108 if (!SawTrapCall && GO.getName() == BPF_TRAP) {
109 GO.eraseFromParent();
110 break;
111 }
112 }
113
115}
116
118 raw_ostream &O) {
119 const MachineOperand &MO = MI->getOperand(OpNum);
120
121 switch (MO.getType()) {
124 break;
125
127 O << MO.getImm();
128 break;
129
131 O << *MO.getMBB()->getSymbol();
132 break;
133
135 O << *getSymbol(MO.getGlobal());
136 break;
137
140 O << BA->getName();
141 break;
142 }
143
146 break;
147
150 default:
151 llvm_unreachable("<unknown operand type>");
152 }
153}
154
156 const char *ExtraCode, raw_ostream &O) {
157 if (ExtraCode && ExtraCode[0])
158 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
159
160 printOperand(MI, OpNo, O);
161 return false;
162}
163
165 unsigned OpNum, const char *ExtraCode,
166 raw_ostream &O) {
167 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
168 const MachineOperand &BaseMO = MI->getOperand(OpNum);
169 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
170 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
171 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
172 int Offset = OffsetMO.getImm();
173
174 if (ExtraCode)
175 return true; // Unknown modifier.
176
177 if (Offset < 0)
178 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
179 else
180 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
181
182 return false;
183}
184
186 if (MI->isCall()) {
187 for (const MachineOperand &Op : MI->operands()) {
188 if (Op.isGlobal()) {
189 if (const GlobalValue *GV = Op.getGlobal())
190 if (GV->getName() == BPF_TRAP)
191 SawTrapCall = true;
192 }
193 }
194 }
195
196 BPF_MC::verifyInstructionPredicates(MI->getOpcode(),
197 getSubtargetInfo().getFeatureBits());
198
199 MCInst TmpInst;
200
201 if (!BTF || !BTF->InstLower(MI, TmpInst)) {
202 BPFMCInstLower MCInstLowering(OutContext, *this);
203 MCInstLowering.Lower(MI, TmpInst);
204 }
205 EmitToStreamer(*OutStreamer, TmpInst);
206}
207
209 // Emit .bpf_cleanup section with a flat table of
210 // (call_site, landing_pad) pairs.
211 const std::vector<LandingPadInfo> &LandingPads = MF->getLandingPads();
212 if (LandingPads.empty())
213 return;
214
215 MCContext &Ctx = OutContext;
216 auto *CleanupSec =
217 Ctx.getELFSection(".bpf_cleanup", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
218 OutStreamer->switchSection(CleanupSec);
219
220 const auto &TypeInfos = MF->getTypeInfos();
221 const Function &F = MF->getFunction();
222 LLVMContext &LLVMCtx = F.getContext();
223
224 // Each landing pad has BeginLabels/EndLabels marking the invoke
225 // call sites that unwind to it.
226 for (const LandingPadInfo &LP : LandingPads) {
227 // BPF treats all landing pads as catch-all: the kernel redirects to
228 // the landing pad regardless of exception type. Reject type-specific
229 // catches and filters which would silently misbehave.
230 for (int TId : LP.TypeIds) {
231 if (TId > 0 && TypeInfos[TId - 1] != nullptr) {
233 F, "BPF does not support type-specific exception catches yet"));
234 return;
235 }
236 if (TId < 0) {
238 F, "BPF does not support exception filters yet"));
239 return;
240 }
241 }
242
243 MCSymbol *LPLabel = LP.LandingPadLabel;
244 if (!LPLabel)
245 continue;
246 for (unsigned i = 0, e = LP.BeginLabels.size(); i != e; ++i) {
247 MCSymbol *Begin = LP.BeginLabels[i];
248 MCSymbol *End = LP.EndLabels[i];
249
250 // Each entry is 3 x 4 bytes: begin, end, landing_pad.
251 // The invoke region [begin, end) may include argument setup
252 // before the call. The runtime checks begin <= PC < end.
253 OutStreamer->emitSymbolValue(Begin, 4);
254 OutStreamer->emitSymbolValue(End, 4);
255 OutStreamer->emitSymbolValue(LPLabel, 4);
256 }
257 }
258
259 // Switch back to the function's section.
260 OutStreamer->switchSection(MF->getSection());
261}
262
264 SmallString<60> Name;
266 << "BPF.JT." << MF->getFunctionNumber() << '.' << JTI;
267 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
268 if (auto *ES = static_cast<MCSymbolELF *>(S)) {
269 ES->setBinding(ELF::STB_GLOBAL);
270 ES->setType(ELF::STT_OBJECT);
271 }
272 return S;
273}
274
276 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
277 if (!MJTI)
278 return;
279
280 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
281 if (JT.empty())
282 return;
283
285 const Function &F = MF->getFunction();
286
287 MCSection *Sec = OutStreamer->getCurrentSectionOnly();
288 MCSymbol *SecStart = Sec->getBeginSymbol();
289
290 MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);
292 unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
293 OutStreamer->switchSection(JTS);
294 for (unsigned JTI = 0; JTI < JT.size(); JTI++) {
295 ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;
296 if (JTBBs.empty())
297 continue;
298
299 MCSymbol *JTStart = getJTPublicSymbol(JTI);
300 OutStreamer->emitLabel(JTStart);
301 for (const MachineBasicBlock *MBB : JTBBs) {
302 const MCExpr *Diff = MCBinaryExpr::createSub(
305 OutStreamer->emitValue(Diff, EntrySize);
306 }
307 const MCExpr *JTSize =
308 MCConstantExpr::create(JTBBs.size() * EntrySize, OutContext);
309 OutStreamer->emitELFSize(JTStart, JTSize);
310 }
311}
312
313char BPFAsmPrinter::ID = 0;
314
315INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,
316 false)
317
318// Force static initialization.
320LLVMInitializeBPFAsmPrinter() {
324}
325
334
345
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
#define BPF_TRAP
Definition BPF.h:29
This file contains support for writing BTF debug info.
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
SmallVector< std::unique_ptr< AsmPrinterHandler >, 2 > Handlers
Definition AsmPrinter.h:244
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:453
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const DataLayout & getDataLayout() const
Return information about data layout.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
MCSymbol * getJTPublicSymbol(unsigned JTI)
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O)
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
BPFAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
~BPFAsmPrinter() override
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void emitJumpTableInfo() override
Print assembly representations of the jump tables used by the current function to the current output ...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
static const char * getRegisterName(MCRegister Reg)
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool hasGotox() const
Collect and emit BTF information.
Definition BTFDebug.h:297
ConstantArray - Constant Array Declarations.
Definition Constants.h:590
This is an important base class in LLVM.
Definition Constant.h:43
Diagnostic information for unsupported feature in backend.
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:573
MCSymbol * getBeginSymbol()
Definition MCSection.h:646
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
LLVM_ABI unsigned getEntrySize(const DataLayout &TD) const
getEntrySize - Return the size of each entry in the jump table.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
Primary interface to the complete machine description for the target machine.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
op_range operands()
Definition User.h:267
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SHF_ALLOC
Definition ELF.h:1256
@ SHT_PROGBITS
Definition ELF.h:1155
@ STB_GLOBAL
Definition ELF.h:1413
@ STT_OBJECT
Definition ELF.h:1425
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Target & getTheBPFleTarget()
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
Target & getTheBPFbeTarget()
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
Target & getTheBPFTarget()
@ Global
Append to llvm.global_dtors.
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
This structure is used to retain landing pad info for the current function.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...