| //===-- BPFInstPrinter.cpp - Convert BPF MCInst to asm syntax -------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This class prints an BPF MCInst to a .s file. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/BPFInstPrinter.h" |
| #include "llvm/MC/MCAsmInfo.h" |
| #include "llvm/MC/MCExpr.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCSymbol.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/FormattedStream.h" |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "asm-printer" |
| |
| // Include the auto-generated portion of the assembly writer. |
| #include "BPFGenAsmWriter.inc" |
| |
| void BPFInstPrinter::printInst(const MCInst *MI, uint64_t Address, |
| StringRef Annot, const MCSubtargetInfo &STI, |
| raw_ostream &O) { |
| printInstruction(MI, Address, O); |
| printAnnotation(O, Annot); |
| } |
| |
| static void printExpr(const MCExpr *Expr, raw_ostream &O) { |
| #ifndef NDEBUG |
| const MCSymbolRefExpr *SRE; |
| |
| if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) |
| SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); |
| else |
| SRE = dyn_cast<MCSymbolRefExpr>(Expr); |
| assert(SRE && "Unexpected MCExpr type."); |
| |
| MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); |
| |
| assert(Kind == MCSymbolRefExpr::VK_None); |
| #endif |
| O << *Expr; |
| } |
| |
| void BPFInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O, const char *Modifier) { |
| assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); |
| const MCOperand &Op = MI->getOperand(OpNo); |
| if (Op.isReg()) { |
| O << getRegisterName(Op.getReg()); |
| } else if (Op.isImm()) { |
| O << formatImm((int32_t)Op.getImm()); |
| } else { |
| assert(Op.isExpr() && "Expected an expression"); |
| printExpr(Op.getExpr(), O); |
| } |
| } |
| |
| void BPFInstPrinter::printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O, |
| const char *Modifier) { |
| const MCOperand &RegOp = MI->getOperand(OpNo); |
| const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); |
| |
| // register |
| assert(RegOp.isReg() && "Register operand not a register"); |
| O << getRegisterName(RegOp.getReg()); |
| |
| // offset |
| if (OffsetOp.isImm()) { |
| auto Imm = OffsetOp.getImm(); |
| if (Imm >= 0) |
| O << " + " << formatImm(Imm); |
| else |
| O << " - " << formatImm(-Imm); |
| } else { |
| assert(0 && "Expected an immediate"); |
| } |
| } |
| |
| void BPFInstPrinter::printImm64Operand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) { |
| const MCOperand &Op = MI->getOperand(OpNo); |
| if (Op.isImm()) |
| O << formatImm(Op.getImm()); |
| else if (Op.isExpr()) |
| printExpr(Op.getExpr(), O); |
| else |
| O << Op; |
| } |
| |
| void BPFInstPrinter::printBrTargetOperand(const MCInst *MI, unsigned OpNo, |
| raw_ostream &O) { |
| const MCOperand &Op = MI->getOperand(OpNo); |
| if (Op.isImm()) { |
| int16_t Imm = Op.getImm(); |
| O << ((Imm >= 0) ? "+" : "") << formatImm(Imm); |
| } else if (Op.isExpr()) { |
| printExpr(Op.getExpr(), O); |
| } else { |
| O << Op; |
| } |
| } |