xref: /freebsd/contrib/llvm-project/llvm/lib/Target/BPF/BPFAsmPrinter.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
10b57cec5SDimitry Andric //===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a printer that converts from our internal representation
100b57cec5SDimitry Andric // of machine-dependent LLVM code to the BPF assembly language.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "BPF.h"
150b57cec5SDimitry Andric #include "BPFInstrInfo.h"
160b57cec5SDimitry Andric #include "BPFMCInstLower.h"
170b57cec5SDimitry Andric #include "BPFTargetMachine.h"
180b57cec5SDimitry Andric #include "BTFDebug.h"
190b57cec5SDimitry Andric #include "MCTargetDesc/BPFInstPrinter.h"
200b57cec5SDimitry Andric #include "TargetInfo/BPFTargetInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
300b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric class BPFAsmPrinter : public AsmPrinter {
380b57cec5SDimitry Andric public:
390b57cec5SDimitry Andric   explicit BPFAsmPrinter(TargetMachine &TM,
400b57cec5SDimitry Andric                          std::unique_ptr<MCStreamer> Streamer)
410b57cec5SDimitry Andric       : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {}
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   StringRef getPassName() const override { return "BPF Assembly Printer"; }
440b57cec5SDimitry Andric   bool doInitialization(Module &M) override;
450b57cec5SDimitry Andric   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
460b57cec5SDimitry Andric   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
470b57cec5SDimitry Andric                        const char *ExtraCode, raw_ostream &O) override;
480b57cec5SDimitry Andric   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
490b57cec5SDimitry Andric                              const char *ExtraCode, raw_ostream &O) override;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   void EmitInstruction(const MachineInstr *MI) override;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric private:
540b57cec5SDimitry Andric   BTFDebug *BTF;
550b57cec5SDimitry Andric };
560b57cec5SDimitry Andric } // namespace
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric bool BPFAsmPrinter::doInitialization(Module &M) {
590b57cec5SDimitry Andric   AsmPrinter::doInitialization(M);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   // Only emit BTF when debuginfo available.
628bcb0991SDimitry Andric   if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
630b57cec5SDimitry Andric     BTF = new BTFDebug(this);
640b57cec5SDimitry Andric     Handlers.push_back(HandlerInfo(std::unique_ptr<BTFDebug>(BTF), "emit",
650b57cec5SDimitry Andric                                    "Debug Info Emission", "BTF",
660b57cec5SDimitry Andric                                    "BTF Emission"));
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   return false;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
730b57cec5SDimitry Andric                                  raw_ostream &O) {
740b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   switch (MO.getType()) {
770b57cec5SDimitry Andric   case MachineOperand::MO_Register:
780b57cec5SDimitry Andric     O << BPFInstPrinter::getRegisterName(MO.getReg());
790b57cec5SDimitry Andric     break;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
820b57cec5SDimitry Andric     O << MO.getImm();
830b57cec5SDimitry Andric     break;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
860b57cec5SDimitry Andric     O << *MO.getMBB()->getSymbol();
870b57cec5SDimitry Andric     break;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
900b57cec5SDimitry Andric     O << *getSymbol(MO.getGlobal());
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress: {
940b57cec5SDimitry Andric     MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
950b57cec5SDimitry Andric     O << BA->getName();
960b57cec5SDimitry Andric     break;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
1000b57cec5SDimitry Andric     O << *GetExternalSymbolSymbol(MO.getSymbolName());
1010b57cec5SDimitry Andric     break;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
1040b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
1050b57cec5SDimitry Andric   default:
1060b57cec5SDimitry Andric     llvm_unreachable("<unknown operand type>");
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
1110b57cec5SDimitry Andric                                     const char *ExtraCode, raw_ostream &O) {
1120b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0])
1130b57cec5SDimitry Andric     return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   printOperand(MI, OpNo, O);
1160b57cec5SDimitry Andric   return false;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
1200b57cec5SDimitry Andric                                           unsigned OpNum, const char *ExtraCode,
1210b57cec5SDimitry Andric                                           raw_ostream &O) {
1220b57cec5SDimitry Andric   assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
1230b57cec5SDimitry Andric   const MachineOperand &BaseMO = MI->getOperand(OpNum);
1240b57cec5SDimitry Andric   const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
1250b57cec5SDimitry Andric   assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
1260b57cec5SDimitry Andric   assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
1270b57cec5SDimitry Andric   int Offset = OffsetMO.getImm();
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   if (ExtraCode)
1300b57cec5SDimitry Andric     return true; // Unknown modifier.
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   if (Offset < 0)
1330b57cec5SDimitry Andric     O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
1340b57cec5SDimitry Andric   else
1350b57cec5SDimitry Andric     O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   return false;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1410b57cec5SDimitry Andric   MCInst TmpInst;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   if (!BTF || !BTF->InstLower(MI, TmpInst)) {
1440b57cec5SDimitry Andric     BPFMCInstLower MCInstLowering(OutContext, *this);
1450b57cec5SDimitry Andric     MCInstLowering.Lower(MI, TmpInst);
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, TmpInst);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric // Force static initialization.
151*480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
1520b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
1530b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
1540b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
1550b57cec5SDimitry Andric }
156