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)) {} 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 } // namespace 54 55 bool BPFAsmPrinter::doInitialization(Module &M) { 56 AsmPrinter::doInitialization(M); 57 58 // Only emit BTF when debuginfo available. 59 if (MAI->doesSupportDebugInformation() && !empty(M.debug_compile_units())) { 60 Handlers.emplace_back(llvm::make_unique<BTFDebug>(this), "emit", 61 "Debug Info Emission", "BTF", "BTF Emission"); 62 } 63 64 return false; 65 } 66 67 void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 68 raw_ostream &O) { 69 const MachineOperand &MO = MI->getOperand(OpNum); 70 71 switch (MO.getType()) { 72 case MachineOperand::MO_Register: 73 O << BPFInstPrinter::getRegisterName(MO.getReg()); 74 break; 75 76 case MachineOperand::MO_Immediate: 77 O << MO.getImm(); 78 break; 79 80 case MachineOperand::MO_MachineBasicBlock: 81 O << *MO.getMBB()->getSymbol(); 82 break; 83 84 case MachineOperand::MO_GlobalAddress: 85 O << *getSymbol(MO.getGlobal()); 86 break; 87 88 case MachineOperand::MO_BlockAddress: { 89 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 90 O << BA->getName(); 91 break; 92 } 93 94 case MachineOperand::MO_ExternalSymbol: 95 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 96 break; 97 98 case MachineOperand::MO_JumpTableIndex: 99 case MachineOperand::MO_ConstantPoolIndex: 100 default: 101 llvm_unreachable("<unknown operand type>"); 102 } 103 } 104 105 bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 106 const char *ExtraCode, raw_ostream &O) { 107 if (ExtraCode && ExtraCode[0]) 108 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); 109 110 printOperand(MI, OpNo, O); 111 return false; 112 } 113 114 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 115 unsigned OpNum, const char *ExtraCode, 116 raw_ostream &O) { 117 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); 118 const MachineOperand &BaseMO = MI->getOperand(OpNum); 119 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); 120 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); 121 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); 122 int Offset = OffsetMO.getImm(); 123 124 if (ExtraCode) 125 return true; // Unknown modifier. 126 127 if (Offset < 0) 128 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")"; 129 else 130 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")"; 131 132 return false; 133 } 134 135 void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { 136 137 BPFMCInstLower MCInstLowering(OutContext, *this); 138 139 MCInst TmpInst; 140 MCInstLowering.Lower(MI, TmpInst); 141 EmitToStreamer(*OutStreamer, TmpInst); 142 } 143 144 // Force static initialization. 145 extern "C" void LLVMInitializeBPFAsmPrinter() { 146 RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); 147 RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); 148 RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); 149 } 150