1 //===-- BPFInstPrinter.cpp - Convert BPF MCInst to asm syntax -------------===// 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 class prints an BPF MCInst to a .s file. 10 // 11 //===----------------------------------------------------------------------===// 12 13 14 #include "BPF.h" 15 #include "MCTargetDesc/BPFInstPrinter.h" 16 #include "llvm/MC/MCAsmInfo.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCInst.h" 19 #include "llvm/MC/MCRegister.h" 20 #include "llvm/MC/MCSymbol.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/FormattedStream.h" 24 using namespace llvm; 25 26 #define DEBUG_TYPE "asm-printer" 27 28 // Include the auto-generated portion of the assembly writer. 29 #include "BPFGenAsmWriter.inc" 30 31 void BPFInstPrinter::printInst(const MCInst *MI, uint64_t Address, 32 StringRef Annot, const MCSubtargetInfo &STI, 33 raw_ostream &O) { 34 printInstruction(MI, Address, O); 35 printAnnotation(O, Annot); 36 } 37 38 static void printExpr(const MCExpr *Expr, raw_ostream &O) { 39 const MCSymbolRefExpr *SRE; 40 41 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) 42 SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); 43 else 44 SRE = dyn_cast<MCSymbolRefExpr>(Expr); 45 if (!SRE) 46 report_fatal_error("Unexpected MCExpr type."); 47 48 #ifndef NDEBUG 49 MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); 50 51 assert(Kind == MCSymbolRefExpr::VK_None); 52 #endif 53 O << *Expr; 54 } 55 56 void BPFInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 57 raw_ostream &O, const char *Modifier) { 58 assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported"); 59 const MCOperand &Op = MI->getOperand(OpNo); 60 if (Op.isReg()) { 61 O << getRegisterName(Op.getReg()); 62 } else if (Op.isImm()) { 63 O << formatImm((int32_t)Op.getImm()); 64 } else { 65 assert(Op.isExpr() && "Expected an expression"); 66 printExpr(Op.getExpr(), O); 67 } 68 } 69 70 void BPFInstPrinter::printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O, 71 const char *Modifier) { 72 const MCOperand &RegOp = MI->getOperand(OpNo); 73 const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); 74 75 // register 76 assert(RegOp.isReg() && "Register operand not a register"); 77 O << getRegisterName(RegOp.getReg()); 78 79 // offset 80 if (OffsetOp.isImm()) { 81 auto Imm = OffsetOp.getImm(); 82 if (Imm >= 0) 83 O << " + " << formatImm(Imm); 84 else 85 O << " - " << formatImm(-Imm); 86 } else { 87 assert(0 && "Expected an immediate"); 88 } 89 } 90 91 void BPFInstPrinter::printImm64Operand(const MCInst *MI, unsigned OpNo, 92 raw_ostream &O) { 93 const MCOperand &Op = MI->getOperand(OpNo); 94 if (Op.isImm()) 95 O << formatImm(Op.getImm()); 96 else if (Op.isExpr()) 97 printExpr(Op.getExpr(), O); 98 else 99 O << Op; 100 } 101 102 void BPFInstPrinter::printBrTargetOperand(const MCInst *MI, unsigned OpNo, 103 raw_ostream &O) { 104 const MCOperand &Op = MI->getOperand(OpNo); 105 if (Op.isImm()) { 106 if (MI->getOpcode() == BPF::JMPL) { 107 int32_t Imm = Op.getImm(); 108 O << ((Imm >= 0) ? "+" : "") << formatImm(Imm); 109 } else { 110 int16_t Imm = Op.getImm(); 111 O << ((Imm >= 0) ? "+" : "") << formatImm(Imm); 112 } 113 } else if (Op.isExpr()) { 114 printExpr(Op.getExpr(), O); 115 } else { 116 O << Op; 117 } 118 } 119