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 SmallString<60> Name;
211 << "BPF.JT." << MF->getFunctionNumber() << '.' << JTI;
212 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
213 if (auto *ES = static_cast<MCSymbolELF *>(S)) {
214 ES->setBinding(ELF::STB_GLOBAL);
215 ES->setType(ELF::STT_OBJECT);
216 }
217 return S;
218}
219
221 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
222 if (!MJTI)
223 return;
224
225 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
226 if (JT.empty())
227 return;
228
230 const Function &F = MF->getFunction();
231
232 MCSection *Sec = OutStreamer->getCurrentSectionOnly();
233 MCSymbol *SecStart = Sec->getBeginSymbol();
234
235 MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);
237 unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
238 OutStreamer->switchSection(JTS);
239 for (unsigned JTI = 0; JTI < JT.size(); JTI++) {
240 ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;
241 if (JTBBs.empty())
242 continue;
243
244 MCSymbol *JTStart = getJTPublicSymbol(JTI);
245 OutStreamer->emitLabel(JTStart);
246 for (const MachineBasicBlock *MBB : JTBBs) {
247 const MCExpr *Diff = MCBinaryExpr::createSub(
250 OutStreamer->emitValue(Diff, EntrySize);
251 }
252 const MCExpr *JTSize =
253 MCConstantExpr::create(JTBBs.size() * EntrySize, OutContext);
254 OutStreamer->emitELFSize(JTStart, JTSize);
255 }
256}
257
258char BPFAsmPrinter::ID = 0;
259
260INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,
261 false)
262
263// Force static initialization.
265LLVMInitializeBPFAsmPrinter() {
269}
270
279
290
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:857
#define LLVM_ABI
Definition Compiler.h:211
#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
std::unique_ptr< MCStreamer > && Streamer
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:95
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:98
SmallVector< std::unique_ptr< AsmPrinterHandler >, 2 > Handlers
Definition AsmPrinter.h:257
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:113
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:105
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:475
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:110
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:101
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.
~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
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
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
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:580
MCSymbol * getBeginSymbol()
Definition MCSection.h:653
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:68
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.
@ STB_GLOBAL
Definition ELF.h:1422
@ STT_OBJECT
Definition ELF.h:1434
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:1755
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:1933
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
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...