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/Support/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 *ExtraCode, raw_ostream &O) override; 48 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 49 const char *ExtraCode, 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(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(OpNum); 75 76 switch (MO.getType()) { 77 case MachineOperand::MO_Register: 78 O << BPFInstPrinter::getRegisterName(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(MO.getGlobal()); 91 break; 92 93 case MachineOperand::MO_BlockAddress: { 94 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 95 O << BA->getName(); 96 break; 97 } 98 99 case MachineOperand::MO_ExternalSymbol: 100 O << *GetExternalSymbolSymbol(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 *ExtraCode, raw_ostream &O) { 112 if (ExtraCode && ExtraCode[0]) 113 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); 114 115 printOperand(MI, OpNo, O); 116 return false; 117 } 118 119 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 120 unsigned OpNum, const char *ExtraCode, 121 raw_ostream &O) { 122 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); 123 const MachineOperand &BaseMO = MI->getOperand(OpNum); 124 const MachineOperand &OffsetMO = MI->getOperand(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(BaseMO.getReg()) << " - " << -Offset << ")"; 134 else 135 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")"; 136 137 return false; 138 } 139 140 void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { 141 MCInst TmpInst; 142 143 if (!BTF || !BTF->InstLower(MI, TmpInst)) { 144 BPFMCInstLower MCInstLowering(OutContext, *this); 145 MCInstLowering.Lower(MI, TmpInst); 146 } 147 EmitToStreamer(*OutStreamer, TmpInst); 148 } 149 150 // Force static initialization. 151 extern "C" void LLVMInitializeBPFAsmPrinter() { 152 RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); 153 RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); 154 RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); 155 } 156