xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/BPF/BPFAsmPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
26*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
31349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric namespace {
380b57cec5SDimitry Andric class BPFAsmPrinter : public AsmPrinter {
390b57cec5SDimitry Andric public:
400b57cec5SDimitry Andric   explicit BPFAsmPrinter(TargetMachine &TM,
410b57cec5SDimitry Andric                          std::unique_ptr<MCStreamer> Streamer)
420b57cec5SDimitry Andric       : AsmPrinter(TM, std::move(Streamer)), BTF(nullptr) {}
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   StringRef getPassName() const override { return "BPF Assembly Printer"; }
450b57cec5SDimitry Andric   bool doInitialization(Module &M) override;
460b57cec5SDimitry Andric   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
470b57cec5SDimitry Andric   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
480b57cec5SDimitry Andric                        const char *ExtraCode, raw_ostream &O) override;
490b57cec5SDimitry Andric   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
500b57cec5SDimitry Andric                              const char *ExtraCode, raw_ostream &O) override;
510b57cec5SDimitry Andric 
525ffd83dbSDimitry Andric   void emitInstruction(const MachineInstr *MI) override;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric private:
550b57cec5SDimitry Andric   BTFDebug *BTF;
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric } // namespace
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric bool BPFAsmPrinter::doInitialization(Module &M) {
600b57cec5SDimitry Andric   AsmPrinter::doInitialization(M);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   // Only emit BTF when debuginfo available.
638bcb0991SDimitry Andric   if (MAI->doesSupportDebugInformation() && !M.debug_compile_units().empty()) {
640b57cec5SDimitry Andric     BTF = new BTFDebug(this);
65*0fca6ea1SDimitry Andric     DebugHandlers.push_back(std::unique_ptr<BTFDebug>(BTF));
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   return false;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
720b57cec5SDimitry Andric                                  raw_ostream &O) {
730b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   switch (MO.getType()) {
760b57cec5SDimitry Andric   case MachineOperand::MO_Register:
770b57cec5SDimitry Andric     O << BPFInstPrinter::getRegisterName(MO.getReg());
780b57cec5SDimitry Andric     break;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
810b57cec5SDimitry Andric     O << MO.getImm();
820b57cec5SDimitry Andric     break;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
850b57cec5SDimitry Andric     O << *MO.getMBB()->getSymbol();
860b57cec5SDimitry Andric     break;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
890b57cec5SDimitry Andric     O << *getSymbol(MO.getGlobal());
900b57cec5SDimitry Andric     break;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress: {
930b57cec5SDimitry Andric     MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
940b57cec5SDimitry Andric     O << BA->getName();
950b57cec5SDimitry Andric     break;
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
990b57cec5SDimitry Andric     O << *GetExternalSymbolSymbol(MO.getSymbolName());
1000b57cec5SDimitry Andric     break;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
1030b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
1040b57cec5SDimitry Andric   default:
1050b57cec5SDimitry Andric     llvm_unreachable("<unknown operand type>");
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
1100b57cec5SDimitry Andric                                     const char *ExtraCode, raw_ostream &O) {
1110b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0])
1120b57cec5SDimitry Andric     return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   printOperand(MI, OpNo, O);
1150b57cec5SDimitry Andric   return false;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
1190b57cec5SDimitry Andric                                           unsigned OpNum, const char *ExtraCode,
1200b57cec5SDimitry Andric                                           raw_ostream &O) {
1210b57cec5SDimitry Andric   assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
1220b57cec5SDimitry Andric   const MachineOperand &BaseMO = MI->getOperand(OpNum);
1230b57cec5SDimitry Andric   const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
1240b57cec5SDimitry Andric   assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
1250b57cec5SDimitry Andric   assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
1260b57cec5SDimitry Andric   int Offset = OffsetMO.getImm();
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   if (ExtraCode)
1290b57cec5SDimitry Andric     return true; // Unknown modifier.
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   if (Offset < 0)
1320b57cec5SDimitry Andric     O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
1330b57cec5SDimitry Andric   else
1340b57cec5SDimitry Andric     O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   return false;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1395ffd83dbSDimitry Andric void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) {
140753f127fSDimitry Andric   BPF_MC::verifyInstructionPredicates(MI->getOpcode(),
141753f127fSDimitry Andric                                       getSubtargetInfo().getFeatureBits());
142753f127fSDimitry Andric 
1430b57cec5SDimitry Andric   MCInst TmpInst;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   if (!BTF || !BTF->InstLower(MI, TmpInst)) {
1460b57cec5SDimitry Andric     BPFMCInstLower MCInstLowering(OutContext, *this);
1470b57cec5SDimitry Andric     MCInstLowering.Lower(MI, TmpInst);
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, TmpInst);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric // Force static initialization.
153480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmPrinter() {
1540b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> X(getTheBPFleTarget());
1550b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> Y(getTheBPFbeTarget());
1560b57cec5SDimitry Andric   RegisterAsmPrinter<BPFAsmPrinter> Z(getTheBPFTarget());
1570b57cec5SDimitry Andric }
158