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"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
41#include "llvm/MC/MCSymbolELF.h"
46using namespace llvm;
47
48#define DEBUG_TYPE "asm-printer"
49
51 std::unique_ptr<MCStreamer> Streamer)
52 : AsmPrinter(TM, std::move(Streamer), ID), BTF(nullptr), TM(TM) {}
53
55
58
59 // Only emit BTF when debuginfo available.
60 if (MAI.doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
61 BTF = new BTFDebug(this);
62 Handlers.push_back(std::unique_ptr<BTFDebug>(BTF));
63 }
64
65 return false;
66}
67
68const BPFTargetMachine &BPFAsmPrinter::getBTM() const {
69 return static_cast<const BPFTargetMachine &>(TM);
70}
71
73 // Remove unused globals which are previously used for jump table.
74 const BPFSubtarget *Subtarget = getBTM().getSubtargetImpl();
75 if (Subtarget->hasGotox()) {
76 std::vector<GlobalVariable *> Targets;
77 for (GlobalVariable &Global : M.globals()) {
78 if (Global.getLinkage() != GlobalValue::PrivateLinkage)
79 continue;
80 if (!Global.isConstant() || !Global.hasInitializer())
81 continue;
82
83 Constant *CV = dyn_cast<Constant>(Global.getInitializer());
84 if (!CV)
85 continue;
87 if (!CA)
88 continue;
89
90 if (!all_of(CA->operands(),
91 [](const Use &Op) { return isa<BlockAddress>(Op); }))
92 continue;
93 Targets.push_back(&Global);
94 }
95
96 for (GlobalVariable *GV : Targets) {
97 GV->replaceAllUsesWith(PoisonValue::get(GV->getType()));
98 GV->dropAllReferences();
99 GV->eraseFromParent();
100 }
101 }
102
103 for (GlobalObject &GO : M.global_objects()) {
104 if (!GO.hasExternalWeakLinkage())
105 continue;
106
107 if (!SawTrapCall && GO.getName() == BPF_TRAP) {
108 GO.eraseFromParent();
109 break;
110 }
111 }
112
114}
115
117 raw_ostream &O) {
118 const MachineOperand &MO = MI->getOperand(OpNum);
119
120 switch (MO.getType()) {
123 break;
124
126 O << MO.getImm();
127 break;
128
130 O << *MO.getMBB()->getSymbol();
131 break;
132
134 O << *getSymbol(MO.getGlobal());
135 break;
136
139 O << BA->getName();
140 break;
141 }
142
145 break;
146
149 default:
150 llvm_unreachable("<unknown operand type>");
151 }
152}
153
155 const char *ExtraCode, raw_ostream &O) {
156 if (ExtraCode && ExtraCode[0])
157 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
158
159 printOperand(MI, OpNo, O);
160 return false;
161}
162
164 unsigned OpNum, const char *ExtraCode,
165 raw_ostream &O) {
166 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
167 const MachineOperand &BaseMO = MI->getOperand(OpNum);
168 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
169 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
170 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
171 int Offset = OffsetMO.getImm();
172
173 if (ExtraCode)
174 return true; // Unknown modifier.
175
176 if (Offset < 0)
177 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
178 else
179 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
180
181 return false;
182}
183
185 if (MI->isCall()) {
186 for (const MachineOperand &Op : MI->operands()) {
187 if (Op.isGlobal()) {
188 if (const GlobalValue *GV = Op.getGlobal())
189 if (GV->getName() == BPF_TRAP)
190 SawTrapCall = true;
191 }
192 }
193 }
194
195 BPF_MC::verifyInstructionPredicates(MI->getOpcode(),
196 getSubtargetInfo().getFeatureBits());
197
198 MCInst TmpInst;
199
200 if (!BTF || !BTF->InstLower(MI, TmpInst)) {
201 BPFMCInstLower MCInstLowering(OutContext, *this);
202 MCInstLowering.Lower(MI, TmpInst);
203 }
204 EmitToStreamer(*OutStreamer, TmpInst);
205}
206
208 SmallString<60> Name;
210 << "BPF.JT." << MF->getFunctionNumber() << '.' << JTI;
211 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
212 if (auto *ES = static_cast<MCSymbolELF *>(S)) {
213 ES->setBinding(ELF::STB_GLOBAL);
214 ES->setType(ELF::STT_OBJECT);
215 }
216 return S;
217}
218
220 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
221 if (!MJTI)
222 return;
223
224 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
225 if (JT.empty())
226 return;
227
229 const Function &F = MF->getFunction();
230
231 MCSection *Sec = OutStreamer->getCurrentSectionOnly();
232 MCSymbol *SecStart = Sec->getBeginSymbol();
233
234 MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);
236 unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
237 OutStreamer->switchSection(JTS);
238 for (unsigned JTI = 0; JTI < JT.size(); JTI++) {
239 ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;
240 if (JTBBs.empty())
241 continue;
242
243 MCSymbol *JTStart = getJTPublicSymbol(JTI);
244 OutStreamer->emitLabel(JTStart);
245 for (const MachineBasicBlock *MBB : JTBBs) {
246 const MCExpr *Diff = MCBinaryExpr::createSub(
249 OutStreamer->emitValue(Diff, EntrySize);
250 }
251 const MCExpr *JTSize =
252 MCConstantExpr::create(JTBBs.size() * EntrySize, OutContext);
253 OutStreamer->emitELFSize(JTStart, JTSize);
254 }
255}
256
257char BPFAsmPrinter::ID = 0;
258
259INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,
260 false)
261
262// Force static initialization.
264LLVMInitializeBPFAsmPrinter() {
268}
269
278
289
const AArch64Subtarget & Subtarget
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:665
#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:478
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
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:44
@ 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:1230
@ STT_OBJECT
Definition ELF.h:1242
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,...