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 "InstPrinter/BPFInstPrinter.h" 20 #include "llvm/CodeGen/AsmPrinter.h" 21 #include "llvm/CodeGen/MachineConstantPool.h" 22 #include "llvm/CodeGen/MachineFunctionPass.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineModuleInfo.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/Support/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)) {} 41 42 StringRef getPassName() const override { return "BPF Assembly Printer"; } 43 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 44 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 45 unsigned AsmVariant, const char *ExtraCode, 46 raw_ostream &O) override; 47 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 48 unsigned AsmVariant, const char *ExtraCode, 49 raw_ostream &O) override; 50 51 void EmitInstruction(const MachineInstr *MI) override; 52 }; 53 } // namespace 54 55 void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 56 raw_ostream &O) { 57 const MachineOperand &MO = MI->getOperand(OpNum); 58 59 switch (MO.getType()) { 60 case MachineOperand::MO_Register: 61 O << BPFInstPrinter::getRegisterName(MO.getReg()); 62 break; 63 64 case MachineOperand::MO_Immediate: 65 O << MO.getImm(); 66 break; 67 68 case MachineOperand::MO_MachineBasicBlock: 69 O << *MO.getMBB()->getSymbol(); 70 break; 71 72 case MachineOperand::MO_GlobalAddress: 73 O << *getSymbol(MO.getGlobal()); 74 break; 75 76 case MachineOperand::MO_BlockAddress: { 77 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 78 O << BA->getName(); 79 break; 80 } 81 82 case MachineOperand::MO_ExternalSymbol: 83 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 84 break; 85 86 case MachineOperand::MO_JumpTableIndex: 87 case MachineOperand::MO_ConstantPoolIndex: 88 default: 89 llvm_unreachable("<unknown operand type>"); 90 } 91 } 92 93 bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 94 unsigned /*AsmVariant*/, 95 const char *ExtraCode, raw_ostream &O) { 96 if (ExtraCode && ExtraCode[0]) 97 return true; // BPF does not have special modifiers 98 99 printOperand(MI, OpNo, O); 100 return false; 101 } 102 103 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 104 unsigned OpNum, unsigned AsmVariant, 105 const char *ExtraCode, 106 raw_ostream &O) { 107 assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); 108 const MachineOperand &BaseMO = MI->getOperand(OpNum); 109 const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); 110 assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); 111 assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); 112 int Offset = OffsetMO.getImm(); 113 114 if (ExtraCode) 115 return true; // Unknown modifier. 116 117 if (Offset < 0) 118 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")"; 119 else 120 O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")"; 121 122 return false; 123 } 124 125 void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { 126 127 BPFMCInstLower MCInstLowering(OutContext, *this); 128 129 MCInst TmpInst; 130 MCInstLowering.Lower(MI, TmpInst); 131 EmitToStreamer(*OutStreamer, TmpInst); 132 } 133 134 // Force static initialization. 135 extern "C" void LLVMInitializeBPFAsmPrinter() { 136 RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget()); 137 RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget()); 138 RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget()); 139 } 140