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 "BTFDebug.h" 18 #include "MCTargetDesc/BPFInstPrinter.h" 19 #include "TargetInfo/BPFTargetInfo.h" 20 #include "llvm/CodeGen/AsmPrinter.h" 21 #include "llvm/CodeGen/MachineConstantPool.h" 22 #include "llvm/CodeGen/MachineInstr.h" 23 #include "llvm/CodeGen/MachineModuleInfo.h" 24 #include "llvm/IR/Module.h" 25 #include "llvm/MC/MCAsmInfo.h" 26 #include "llvm/MC/MCInst.h" 27 #include "llvm/MC/MCStreamer.h" 28 #include "llvm/MC/MCSymbol.h" 29 #include "llvm/MC/TargetRegistry.h" 30 #include "llvm/Support/raw_ostream.h" 31 using namespace llvm; 32 33 #define DEBUG_TYPE "asm-printer" 34 35 namespace { 36 class BPFAsmPrinter : public AsmPrinter { 37 public: 38 explicit BPFAsmPrinter(TargetMachine &TM, 39 std::unique_ptr<MCStreamer> Streamer) 40 : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {} 41 42 StringRef getPassName() const override { return "BPF Assembly Printer"; } 43 bool doInitialization(Module &M) override; 44 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 45 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 46 const char *ExtraCode, raw_ostream &O) override; 47 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 48 const char *ExtraCode, raw_ostream &O) override; 49 50 void emitInstruction(const MachineInstr *MI) override; 51 52 private: 53 BTFDebug *BTF; 54 }; 55 } // namespace 56 57 bool BPFAsmPrinter::doInitialization(Module &M) { 58 AsmPrinter::doInitialization(M); 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 69 void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 70 raw_ostream &O) { 71 const MachineOperand &MO = MI->getOperand(OpNum); 72 73 switch (MO.getType()) { 74 case MachineOperand::MO_Register: 75 O << BPFInstPrinter::getRegisterName(MO.getReg()); 76 break; 77 78 case MachineOperand::MO_Immediate: 79 O << MO.getImm(); 80 break; 81 82 case MachineOperand::MO_MachineBasicBlock: 83 O << *MO.getMBB()->getSymbol(); 84 break; 85 86 case MachineOperand::MO_GlobalAddress: 87 O << *getSymbol(MO.getGlobal()); 88 break; 89 90 case MachineOperand::MO_BlockAddress: { 91 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 92 O << BA->getName(); 93 break; 94 } 95 96 case MachineOperand::MO_ExternalSymbol: 97 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 98 break; 99 100 case MachineOperand::MO_JumpTableIndex: 101 case MachineOperand::MO_ConstantPoolIndex: 102 default: 103 llvm_unreachable("<unknown operand type>"); 104 } 105 } 106 107 bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 108 const char *ExtraCode, raw_ostream &O) { 109 if (ExtraCode && ExtraCode[0]) 110 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); 111 112 printOperand(MI, OpNo, O); 113 return false; 114 } 115 116 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 117 unsigned OpNum, const char *ExtraCode, 118 raw_ostream &O) { 119 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); 120 const MachineOperand &BaseMO = MI->getOperand(OpNum); 121 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); 122 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); 123 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); 124 int Offset = OffsetMO.getImm(); 125 126 if (ExtraCode) 127 return true; // Unknown modifier. 128 129 if (Offset < 0) 130 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")"; 131 else 132 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")"; 133 134 return false; 135 } 136 137 void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) { 138 BPF_MC::verifyInstructionPredicates(MI->getOpcode(), 139 getSubtargetInfo().getFeatureBits()); 140 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" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() { 152 RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); 153 RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); 154 RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); 155 } 156