1 //===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to the BPF assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "BPF.h" 16 #include "BPFInstrInfo.h" 17 #include "BPFMCInstLower.h" 18 #include "BPFTargetMachine.h" 19 #include "BTFDebug.h" 20 #include "InstPrinter/BPFInstPrinter.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 unsigned AsmVariant, const char *ExtraCode, 48 raw_ostream &O) override; 49 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 50 unsigned AsmVariant, const char *ExtraCode, 51 raw_ostream &O) override; 52 53 void EmitInstruction(const MachineInstr *MI) override; 54 }; 55 } // namespace 56 57 bool BPFAsmPrinter::doInitialization(Module &M) { 58 AsmPrinter::doInitialization(M); 59 60 if (MAI->doesSupportDebugInformation()) { 61 Handlers.push_back(HandlerInfo(new BTFDebug(this), "emit", 62 "Debug Info Emission", "BTF", 63 "BTF Emission")); 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 unsigned /*AsmVariant*/, 109 const char *ExtraCode, raw_ostream &O) { 110 if (ExtraCode && ExtraCode[0]) 111 return true; // BPF does not have special modifiers 112 113 printOperand(MI, OpNo, O); 114 return false; 115 } 116 117 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 118 unsigned OpNum, unsigned AsmVariant, 119 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 141 BPFMCInstLower MCInstLowering(OutContext, *this); 142 143 MCInst TmpInst; 144 MCInstLowering.Lower(MI, TmpInst); 145 EmitToStreamer(*OutStreamer, TmpInst); 146 } 147 148 // Force static initialization. 149 extern "C" void LLVMInitializeBPFAsmPrinter() { 150 RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); 151 RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); 152 RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); 153 } 154