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 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & O)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 
printExpr(const MCExpr * Expr,raw_ostream & O)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 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)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 
printMemOperand(const MCInst * MI,int OpNo,raw_ostream & O,const char * Modifier)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 
printImm64Operand(const MCInst * MI,unsigned OpNo,raw_ostream & O)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 
printBrTargetOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)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