LLVM 22.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"
28#include "llvm/IR/Module.h"
29#include "llvm/MC/MCAsmInfo.h"
30#include "llvm/MC/MCExpr.h"
31#include "llvm/MC/MCInst.h"
32#include "llvm/MC/MCStreamer.h"
33#include "llvm/MC/MCSymbol.h"
34#include "llvm/MC/MCSymbolELF.h"
39using namespace llvm;
40
41#define DEBUG_TYPE "asm-printer"
42
45
46 // Only emit BTF when debuginfo available.
47 if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
48 BTF = new BTFDebug(this);
49 Handlers.push_back(std::unique_ptr<BTFDebug>(BTF));
50 }
51
52 return false;
53}
54
55const BPFTargetMachine &BPFAsmPrinter::getBTM() const {
56 return static_cast<const BPFTargetMachine &>(TM);
57}
58
60 // Remove unused globals which are previously used for jump table.
61 const BPFSubtarget *Subtarget = getBTM().getSubtargetImpl();
62 if (Subtarget->hasGotox()) {
63 std::vector<GlobalVariable *> Targets;
64 for (GlobalVariable &Global : M.globals()) {
65 if (Global.getLinkage() != GlobalValue::PrivateLinkage)
66 continue;
67 if (!Global.isConstant() || !Global.hasInitializer())
68 continue;
69
70 Constant *CV = dyn_cast<Constant>(Global.getInitializer());
71 if (!CV)
72 continue;
74 if (!CA)
75 continue;
76
77 for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {
79 continue;
80 }
81 Targets.push_back(&Global);
82 }
83
84 for (GlobalVariable *GV : Targets) {
85 GV->replaceAllUsesWith(PoisonValue::get(GV->getType()));
86 GV->dropAllReferences();
87 GV->eraseFromParent();
88 }
89 }
90
91 for (GlobalObject &GO : M.global_objects()) {
92 if (!GO.hasExternalWeakLinkage())
93 continue;
94
95 if (!SawTrapCall && GO.getName() == BPF_TRAP) {
96 GO.eraseFromParent();
97 break;
98 }
99 }
100
102}
103
105 raw_ostream &O) {
106 const MachineOperand &MO = MI->getOperand(OpNum);
107
108 switch (MO.getType()) {
111 break;
112
114 O << MO.getImm();
115 break;
116
118 O << *MO.getMBB()->getSymbol();
119 break;
120
122 O << *getSymbol(MO.getGlobal());
123 break;
124
127 O << BA->getName();
128 break;
129 }
130
133 break;
134
137 default:
138 llvm_unreachable("<unknown operand type>");
139 }
140}
141
143 const char *ExtraCode, raw_ostream &O) {
144 if (ExtraCode && ExtraCode[0])
145 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
146
147 printOperand(MI, OpNo, O);
148 return false;
149}
150
152 unsigned OpNum, const char *ExtraCode,
153 raw_ostream &O) {
154 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
155 const MachineOperand &BaseMO = MI->getOperand(OpNum);
156 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
157 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
158 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
159 int Offset = OffsetMO.getImm();
160
161 if (ExtraCode)
162 return true; // Unknown modifier.
163
164 if (Offset < 0)
165 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
166 else
167 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
168
169 return false;
170}
171
173 if (MI->isCall()) {
174 for (const MachineOperand &Op : MI->operands()) {
175 if (Op.isGlobal()) {
176 if (const GlobalValue *GV = Op.getGlobal())
177 if (GV->getName() == BPF_TRAP)
178 SawTrapCall = true;
179 }
180 }
181 }
182
183 BPF_MC::verifyInstructionPredicates(MI->getOpcode(),
184 getSubtargetInfo().getFeatureBits());
185
186 MCInst TmpInst;
187
188 if (!BTF || !BTF->InstLower(MI, TmpInst)) {
189 BPFMCInstLower MCInstLowering(OutContext, *this);
190 MCInstLowering.Lower(MI, TmpInst);
191 }
192 EmitToStreamer(*OutStreamer, TmpInst);
193}
194
196 SmallString<60> Name;
198 << "BPF.JT." << MF->getFunctionNumber() << '.' << JTI;
199 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
200 if (auto *ES = static_cast<MCSymbolELF *>(S)) {
201 ES->setBinding(ELF::STB_GLOBAL);
202 ES->setType(ELF::STT_OBJECT);
203 }
204 return S;
205}
206
208 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
209 if (!MJTI)
210 return;
211
212 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
213 if (JT.empty())
214 return;
215
217 const Function &F = MF->getFunction();
218
219 MCSection *Sec = OutStreamer->getCurrentSectionOnly();
220 MCSymbol *SecStart = Sec->getBeginSymbol();
221
222 MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);
224 unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
225 OutStreamer->switchSection(JTS);
226 for (unsigned JTI = 0; JTI < JT.size(); JTI++) {
227 ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;
228 if (JTBBs.empty())
229 continue;
230
231 MCSymbol *JTStart = getJTPublicSymbol(JTI);
232 OutStreamer->emitLabel(JTStart);
233 for (const MachineBasicBlock *MBB : JTBBs) {
234 const MCExpr *Diff = MCBinaryExpr::createSub(
237 OutStreamer->emitValue(Diff, EntrySize);
238 }
239 const MCExpr *JTSize =
240 MCConstantExpr::create(JTBBs.size() * EntrySize, OutContext);
241 OutStreamer->emitELFSize(JTStart, JTSize);
242 }
243}
244
245char BPFAsmPrinter::ID = 0;
246
247INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,
248 false)
249
250// Force static initialization.
252LLVMInitializeBPFAsmPrinter() {
256}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
#define BPF_TRAP
Definition BPF.h:25
This file contains support for writing BTF debug info.
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:55
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#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")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition ArrayRef.h:143
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:138
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:99
const MCAsmInfo * MAI
Target Asm Printer information.
Definition AsmPrinter.h:102
SmallVector< std::unique_ptr< AsmPrinterHandler >, 2 > Handlers
Definition AsmPrinter.h:241
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:117
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:106
bool doFinalization(Module &M) override
Shut down the asmprinter.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:111
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.
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...
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.
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:289
ConstantArray - Constant Array Declarations.
Definition Constants.h:433
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:428
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:521
MCSymbol * getBeginSymbol()
Definition MCSection.h:593
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
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.
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.
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
Value * getOperand(unsigned i) const
Definition User.h:232
unsigned getNumOperands() const
Definition User.h:254
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ STB_GLOBAL
Definition ELF.h:1405
@ STT_OBJECT
Definition ELF.h:1417
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
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()
Target & getTheBPFbeTarget()
Target & getTheBPFTarget()
@ Global
Append to llvm.global_dtors.
DWARFExpression::Operation Op
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...