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