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 "BPF.h" |
15 | #include "BPFInstrInfo.h" |
16 | #include "BPFMCInstLower.h" |
17 | #include "BPFTargetMachine.h" |
18 | #include "BTFDebug.h" |
19 | #include "MCTargetDesc/BPFInstPrinter.h" |
20 | #include "TargetInfo/BPFTargetInfo.h" |
21 | #include "llvm/CodeGen/AsmPrinter.h" |
22 | #include "llvm/CodeGen/MachineConstantPool.h" |
23 | #include "llvm/CodeGen/MachineFunctionPass.h" |
24 | #include "llvm/CodeGen/MachineInstr.h" |
25 | #include "llvm/CodeGen/MachineModuleInfo.h" |
26 | #include "llvm/MC/MCAsmInfo.h" |
27 | #include "llvm/MC/MCInst.h" |
28 | #include "llvm/MC/MCStreamer.h" |
29 | #include "llvm/MC/MCSymbol.h" |
30 | #include "llvm/MC/TargetRegistry.h" |
31 | #include "llvm/Support/raw_ostream.h" |
32 | using namespace llvm; |
33 | |
34 | #define DEBUG_TYPE "asm-printer" |
35 | |
36 | namespace { |
37 | class BPFAsmPrinter : public AsmPrinter { |
38 | public: |
39 | explicit BPFAsmPrinter(TargetMachine &TM, |
40 | std::unique_ptr<MCStreamer> Streamer) |
41 | : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {} |
42 | |
43 | StringRef getPassName() const override { return "BPF Assembly Printer" ; } |
44 | bool doInitialization(Module &M) override; |
45 | void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); |
46 | bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, |
47 | const char *, raw_ostream &O) override; |
48 | bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, |
49 | const char *, raw_ostream &O) override; |
50 | |
51 | void emitInstruction(const MachineInstr *MI) override; |
52 | |
53 | private: |
54 | BTFDebug *BTF; |
55 | }; |
56 | } // namespace |
57 | |
58 | bool BPFAsmPrinter::doInitialization(Module &M) { |
59 | AsmPrinter::doInitialization(M); |
60 | |
61 | // Only emit BTF when debuginfo available. |
62 | if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) { |
63 | BTF = new BTFDebug(this); |
64 | Handlers.push_back(x: HandlerInfo(std::unique_ptr<BTFDebug>(BTF), "emit" , |
65 | "Debug Info Emission" , "BTF" , |
66 | "BTF Emission" )); |
67 | } |
68 | |
69 | return false; |
70 | } |
71 | |
72 | void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, |
73 | raw_ostream &O) { |
74 | const MachineOperand &MO = MI->getOperand(i: OpNum); |
75 | |
76 | switch (MO.getType()) { |
77 | case MachineOperand::MO_Register: |
78 | O << BPFInstPrinter::getRegisterName(Reg: MO.getReg()); |
79 | break; |
80 | |
81 | case MachineOperand::MO_Immediate: |
82 | O << MO.getImm(); |
83 | break; |
84 | |
85 | case MachineOperand::MO_MachineBasicBlock: |
86 | O << *MO.getMBB()->getSymbol(); |
87 | break; |
88 | |
89 | case MachineOperand::MO_GlobalAddress: |
90 | O << *getSymbol(GV: MO.getGlobal()); |
91 | break; |
92 | |
93 | case MachineOperand::MO_BlockAddress: { |
94 | MCSymbol *BA = GetBlockAddressSymbol(BA: MO.getBlockAddress()); |
95 | O << BA->getName(); |
96 | break; |
97 | } |
98 | |
99 | case MachineOperand::MO_ExternalSymbol: |
100 | O << *GetExternalSymbolSymbol(Sym: MO.getSymbolName()); |
101 | break; |
102 | |
103 | case MachineOperand::MO_JumpTableIndex: |
104 | case MachineOperand::MO_ConstantPoolIndex: |
105 | default: |
106 | llvm_unreachable("<unknown operand type>" ); |
107 | } |
108 | } |
109 | |
110 | bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, |
111 | const char *, raw_ostream &O) { |
112 | if (ExtraCode && ExtraCode[0]) |
113 | return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS&: O); |
114 | |
115 | printOperand(MI, OpNum: OpNo, O); |
116 | return false; |
117 | } |
118 | |
119 | bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, |
120 | unsigned OpNum, const char *, |
121 | raw_ostream &O) { |
122 | assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands" ); |
123 | const MachineOperand &BaseMO = MI->getOperand(i: OpNum); |
124 | const MachineOperand &OffsetMO = MI->getOperand(i: OpNum + 1); |
125 | assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand." ); |
126 | assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand." ); |
127 | int Offset = OffsetMO.getImm(); |
128 | |
129 | if (ExtraCode) |
130 | return true; // Unknown modifier. |
131 | |
132 | if (Offset < 0) |
133 | O << "(" << BPFInstPrinter::getRegisterName(Reg: BaseMO.getReg()) << " - " << -Offset << ")" ; |
134 | else |
135 | O << "(" << BPFInstPrinter::getRegisterName(Reg: BaseMO.getReg()) << " + " << Offset << ")" ; |
136 | |
137 | return false; |
138 | } |
139 | |
140 | void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) { |
141 | BPF_MC::verifyInstructionPredicates(MI->getOpcode(), |
142 | getSubtargetInfo().getFeatureBits()); |
143 | |
144 | MCInst TmpInst; |
145 | |
146 | if (!BTF || !BTF->InstLower(MI, OutMI&: TmpInst)) { |
147 | BPFMCInstLower MCInstLowering(OutContext, *this); |
148 | MCInstLowering.Lower(MI, OutMI&: TmpInst); |
149 | } |
150 | EmitToStreamer(S&: *OutStreamer, Inst: TmpInst); |
151 | } |
152 | |
153 | // Force static initialization. |
154 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() { |
155 | RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); |
156 | RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); |
157 | RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); |
158 | } |
159 | |