1283625Sdim//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//
2283625Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6283625Sdim//
7283625Sdim//===----------------------------------------------------------------------===//
8283625Sdim//
9283625Sdim// This file contains a printer that converts from our internal representation
10283625Sdim// of machine-dependent LLVM code to the BPF assembly language.
11283625Sdim//
12283625Sdim//===----------------------------------------------------------------------===//
13283625Sdim
14283625Sdim#include "BPF.h"
15283625Sdim#include "BPFInstrInfo.h"
16283625Sdim#include "BPFMCInstLower.h"
17283625Sdim#include "BPFTargetMachine.h"
18344779Sdim#include "BTFDebug.h"
19353358Sdim#include "MCTargetDesc/BPFInstPrinter.h"
20353358Sdim#include "TargetInfo/BPFTargetInfo.h"
21283625Sdim#include "llvm/CodeGen/AsmPrinter.h"
22321369Sdim#include "llvm/CodeGen/MachineConstantPool.h"
23283625Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
24283625Sdim#include "llvm/CodeGen/MachineInstr.h"
25321369Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
26283625Sdim#include "llvm/MC/MCAsmInfo.h"
27283625Sdim#include "llvm/MC/MCInst.h"
28283625Sdim#include "llvm/MC/MCStreamer.h"
29283625Sdim#include "llvm/MC/MCSymbol.h"
30283625Sdim#include "llvm/Support/TargetRegistry.h"
31283625Sdim#include "llvm/Support/raw_ostream.h"
32283625Sdimusing namespace llvm;
33283625Sdim
34283625Sdim#define DEBUG_TYPE "asm-printer"
35283625Sdim
36283625Sdimnamespace {
37283625Sdimclass BPFAsmPrinter : public AsmPrinter {
38283625Sdimpublic:
39321369Sdim  explicit BPFAsmPrinter(TargetMachine &TM,
40321369Sdim                         std::unique_ptr<MCStreamer> Streamer)
41353358Sdim      : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {}
42283625Sdim
43314564Sdim  StringRef getPassName() const override { return "BPF Assembly Printer"; }
44344779Sdim  bool doInitialization(Module &M) override;
45327952Sdim  void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
46327952Sdim  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
47353358Sdim                       const char *ExtraCode, raw_ostream &O) override;
48327952Sdim  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
49353358Sdim                             const char *ExtraCode, raw_ostream &O) override;
50283625Sdim
51283625Sdim  void EmitInstruction(const MachineInstr *MI) override;
52353358Sdim
53353358Sdimprivate:
54353358Sdim  BTFDebug *BTF;
55283625Sdim};
56321369Sdim} // namespace
57283625Sdim
58344779Sdimbool BPFAsmPrinter::doInitialization(Module &M) {
59344779Sdim  AsmPrinter::doInitialization(M);
60344779Sdim
61353358Sdim  // Only emit BTF when debuginfo available.
62360784Sdim  if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
63353358Sdim    BTF = new BTFDebug(this);
64353358Sdim    Handlers.push_back(HandlerInfo(std::unique_ptr<BTFDebug>(BTF), "emit",
65344779Sdim                                   "Debug Info Emission", "BTF",
66344779Sdim                                   "BTF Emission"));
67344779Sdim  }
68344779Sdim
69344779Sdim  return false;
70344779Sdim}
71344779Sdim
72327952Sdimvoid BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
73327952Sdim                                 raw_ostream &O) {
74327952Sdim  const MachineOperand &MO = MI->getOperand(OpNum);
75327952Sdim
76327952Sdim  switch (MO.getType()) {
77327952Sdim  case MachineOperand::MO_Register:
78327952Sdim    O << BPFInstPrinter::getRegisterName(MO.getReg());
79327952Sdim    break;
80327952Sdim
81327952Sdim  case MachineOperand::MO_Immediate:
82327952Sdim    O << MO.getImm();
83327952Sdim    break;
84327952Sdim
85327952Sdim  case MachineOperand::MO_MachineBasicBlock:
86327952Sdim    O << *MO.getMBB()->getSymbol();
87327952Sdim    break;
88327952Sdim
89327952Sdim  case MachineOperand::MO_GlobalAddress:
90327952Sdim    O << *getSymbol(MO.getGlobal());
91327952Sdim    break;
92327952Sdim
93327952Sdim  case MachineOperand::MO_BlockAddress: {
94327952Sdim    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
95327952Sdim    O << BA->getName();
96327952Sdim    break;
97327952Sdim  }
98327952Sdim
99327952Sdim  case MachineOperand::MO_ExternalSymbol:
100327952Sdim    O << *GetExternalSymbolSymbol(MO.getSymbolName());
101327952Sdim    break;
102327952Sdim
103327952Sdim  case MachineOperand::MO_JumpTableIndex:
104327952Sdim  case MachineOperand::MO_ConstantPoolIndex:
105327952Sdim  default:
106327952Sdim    llvm_unreachable("<unknown operand type>");
107327952Sdim  }
108327952Sdim}
109327952Sdim
110327952Sdimbool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
111327952Sdim                                    const char *ExtraCode, raw_ostream &O) {
112327952Sdim  if (ExtraCode && ExtraCode[0])
113353358Sdim    return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
114327952Sdim
115327952Sdim  printOperand(MI, OpNo, O);
116327952Sdim  return false;
117327952Sdim}
118327952Sdim
119327952Sdimbool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
120353358Sdim                                          unsigned OpNum, const char *ExtraCode,
121327952Sdim                                          raw_ostream &O) {
122327952Sdim  assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
123327952Sdim  const MachineOperand &BaseMO = MI->getOperand(OpNum);
124327952Sdim  const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
125327952Sdim  assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
126327952Sdim  assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
127327952Sdim  int Offset = OffsetMO.getImm();
128327952Sdim
129327952Sdim  if (ExtraCode)
130327952Sdim    return true; // Unknown modifier.
131327952Sdim
132327952Sdim  if (Offset < 0)
133327952Sdim    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
134327952Sdim  else
135327952Sdim    O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
136327952Sdim
137327952Sdim  return false;
138327952Sdim}
139327952Sdim
140283625Sdimvoid BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
141353358Sdim  MCInst TmpInst;
142283625Sdim
143353358Sdim  if (!BTF || !BTF->InstLower(MI, TmpInst)) {
144353358Sdim    BPFMCInstLower MCInstLowering(OutContext, *this);
145353358Sdim    MCInstLowering.Lower(MI, TmpInst);
146353358Sdim  }
147283625Sdim  EmitToStreamer(*OutStreamer, TmpInst);
148283625Sdim}
149283625Sdim
150283625Sdim// Force static initialization.
151360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
152314564Sdim  RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
153314564Sdim  RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
154314564Sdim  RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
155283625Sdim}
156