BPFAsmPrinter.cpp revision 360784
1//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//
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 file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to the BPF assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "BPF.h"
15#include "BPFInstrInfo.h"
16#include "BPFMCInstLower.h"
17#include "BPFTargetMachine.h"
18#include "BTFDebug.h"
19#include "MCTargetDesc/BPFInstPrinter.h"
20#include "TargetInfo/BPFTargetInfo.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"
32using namespace llvm;
33
34#define DEBUG_TYPE "asm-printer"
35
36namespace {
37class BPFAsmPrinter : public AsmPrinter {
38public:
39  explicit BPFAsmPrinter(TargetMachine &TM,
40                         std::unique_ptr<MCStreamer> Streamer)
41      : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {}
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                       const char *ExtraCode, raw_ostream &O) override;
48  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
49                             const char *ExtraCode, raw_ostream &O) override;
50
51  void EmitInstruction(const MachineInstr *MI) override;
52
53private:
54  BTFDebug *BTF;
55};
56} // namespace
57
58bool BPFAsmPrinter::doInitialization(Module &M) {
59  AsmPrinter::doInitialization(M);
60
61  // Only emit BTF when debuginfo available.
62  if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
63    BTF = new BTFDebug(this);
64    Handlers.push_back(HandlerInfo(std::unique_ptr<BTFDebug>(BTF), "emit",
65                                   "Debug Info Emission", "BTF",
66                                   "BTF Emission"));
67  }
68
69  return false;
70}
71
72void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
73                                 raw_ostream &O) {
74  const MachineOperand &MO = MI->getOperand(OpNum);
75
76  switch (MO.getType()) {
77  case MachineOperand::MO_Register:
78    O << BPFInstPrinter::getRegisterName(MO.getReg());
79    break;
80
81  case MachineOperand::MO_Immediate:
82    O << MO.getImm();
83    break;
84
85  case MachineOperand::MO_MachineBasicBlock:
86    O << *MO.getMBB()->getSymbol();
87    break;
88
89  case MachineOperand::MO_GlobalAddress:
90    O << *getSymbol(MO.getGlobal());
91    break;
92
93  case MachineOperand::MO_BlockAddress: {
94    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
95    O << BA->getName();
96    break;
97  }
98
99  case MachineOperand::MO_ExternalSymbol:
100    O << *GetExternalSymbolSymbol(MO.getSymbolName());
101    break;
102
103  case MachineOperand::MO_JumpTableIndex:
104  case MachineOperand::MO_ConstantPoolIndex:
105  default:
106    llvm_unreachable("<unknown operand type>");
107  }
108}
109
110bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
111                                    const char *ExtraCode, raw_ostream &O) {
112  if (ExtraCode && ExtraCode[0])
113    return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
114
115  printOperand(MI, OpNo, O);
116  return false;
117}
118
119bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
120                                          unsigned OpNum, const char *ExtraCode,
121                                          raw_ostream &O) {
122  assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
123  const MachineOperand &BaseMO = MI->getOperand(OpNum);
124  const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
125  assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
126  assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
127  int Offset = OffsetMO.getImm();
128
129  if (ExtraCode)
130    return true; // Unknown modifier.
131
132  if (Offset < 0)
133    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
134  else
135    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
136
137  return false;
138}
139
140void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
141  MCInst TmpInst;
142
143  if (!BTF || !BTF->InstLower(MI, TmpInst)) {
144    BPFMCInstLower MCInstLowering(OutContext, *this);
145    MCInstLowering.Lower(MI, TmpInst);
146  }
147  EmitToStreamer(*OutStreamer, TmpInst);
148}
149
150// Force static initialization.
151extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
152  RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
153  RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
154  RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
155}
156