xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- BPFMCTargetDesc.cpp - BPF Target Descriptions ---------------------===//
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 provides BPF specific target descriptions.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCTargetDesc.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/BPFInstPrinter.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCAsmInfo.h"
160b57cec5SDimitry Andric #include "TargetInfo/BPFTargetInfo.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
2206c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #define GET_INSTRINFO_MC_DESC
25753f127fSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER
260b57cec5SDimitry Andric #include "BPFGenInstrInfo.inc"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define GET_SUBTARGETINFO_MC_DESC
290b57cec5SDimitry Andric #include "BPFGenSubtargetInfo.inc"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define GET_REGINFO_MC_DESC
320b57cec5SDimitry Andric #include "BPFGenRegisterInfo.inc"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace llvm;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric static MCInstrInfo *createBPFMCInstrInfo() {
370b57cec5SDimitry Andric   MCInstrInfo *X = new MCInstrInfo();
380b57cec5SDimitry Andric   InitBPFMCInstrInfo(X);
390b57cec5SDimitry Andric   return X;
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric static MCRegisterInfo *createBPFMCRegisterInfo(const Triple &TT) {
430b57cec5SDimitry Andric   MCRegisterInfo *X = new MCRegisterInfo();
440b57cec5SDimitry Andric   InitBPFMCRegisterInfo(X, BPF::R11 /* RAReg doesn't exist */);
450b57cec5SDimitry Andric   return X;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric static MCSubtargetInfo *createBPFMCSubtargetInfo(const Triple &TT,
490b57cec5SDimitry Andric                                                  StringRef CPU, StringRef FS) {
50e8d8bef9SDimitry Andric   return createBPFMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
53*0fca6ea1SDimitry Andric static MCStreamer *
54*0fca6ea1SDimitry Andric createBPFMCStreamer(const Triple &T, MCContext &Ctx,
550b57cec5SDimitry Andric                     std::unique_ptr<MCAsmBackend> &&MAB,
560b57cec5SDimitry Andric                     std::unique_ptr<MCObjectWriter> &&OW,
57*0fca6ea1SDimitry Andric                     std::unique_ptr<MCCodeEmitter> &&Emitter) {
58*0fca6ea1SDimitry Andric   return createELFStreamer(Ctx, std::move(MAB), std::move(OW),
59*0fca6ea1SDimitry Andric                            std::move(Emitter));
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,
630b57cec5SDimitry Andric                                              unsigned SyntaxVariant,
640b57cec5SDimitry Andric                                              const MCAsmInfo &MAI,
650b57cec5SDimitry Andric                                              const MCInstrInfo &MII,
660b57cec5SDimitry Andric                                              const MCRegisterInfo &MRI) {
670b57cec5SDimitry Andric   if (SyntaxVariant == 0)
680b57cec5SDimitry Andric     return new BPFInstPrinter(MAI, MII, MRI);
690b57cec5SDimitry Andric   return nullptr;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric namespace {
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric class BPFMCInstrAnalysis : public MCInstrAnalysis {
750b57cec5SDimitry Andric public:
760b57cec5SDimitry Andric   explicit BPFMCInstrAnalysis(const MCInstrInfo *Info)
770b57cec5SDimitry Andric       : MCInstrAnalysis(Info) {}
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
800b57cec5SDimitry Andric                       uint64_t &Target) const override {
810b57cec5SDimitry Andric     // The target is the 3rd operand of cond inst and the 1st of uncond inst.
825f757f3fSDimitry Andric     int32_t Imm;
830b57cec5SDimitry Andric     if (isConditionalBranch(Inst)) {
84*0fca6ea1SDimitry Andric       if (Inst.getOpcode() == BPF::JCOND)
85*0fca6ea1SDimitry Andric         Imm = (short)Inst.getOperand(0).getImm();
86*0fca6ea1SDimitry Andric       else
875f757f3fSDimitry Andric         Imm = (short)Inst.getOperand(2).getImm();
885f757f3fSDimitry Andric     } else if (isUnconditionalBranch(Inst)) {
895f757f3fSDimitry Andric       if (Inst.getOpcode() == BPF::JMP)
905f757f3fSDimitry Andric         Imm = (short)Inst.getOperand(0).getImm();
910b57cec5SDimitry Andric       else
925f757f3fSDimitry Andric         Imm = (int)Inst.getOperand(0).getImm();
935f757f3fSDimitry Andric     } else
940b57cec5SDimitry Andric       return false;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     Target = Addr + Size + Imm * Size;
970b57cec5SDimitry Andric     return true;
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric };
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric } // end anonymous namespace
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric static MCInstrAnalysis *createBPFInstrAnalysis(const MCInstrInfo *Info) {
1040b57cec5SDimitry Andric   return new BPFMCInstrAnalysis(Info);
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
107480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetMC() {
1080b57cec5SDimitry Andric   for (Target *T :
1090b57cec5SDimitry Andric        {&getTheBPFleTarget(), &getTheBPFbeTarget(), &getTheBPFTarget()}) {
1100b57cec5SDimitry Andric     // Register the MC asm info.
1110b57cec5SDimitry Andric     RegisterMCAsmInfo<BPFMCAsmInfo> X(*T);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     // Register the MC instruction info.
1140b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstrInfo(*T, createBPFMCInstrInfo);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric     // Register the MC register info.
1170b57cec5SDimitry Andric     TargetRegistry::RegisterMCRegInfo(*T, createBPFMCRegisterInfo);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     // Register the MC subtarget info.
1200b57cec5SDimitry Andric     TargetRegistry::RegisterMCSubtargetInfo(*T,
1210b57cec5SDimitry Andric                                             createBPFMCSubtargetInfo);
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric     // Register the object streamer
1240b57cec5SDimitry Andric     TargetRegistry::RegisterELFStreamer(*T, createBPFMCStreamer);
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     // Register the MCInstPrinter.
1270b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstPrinter(*T, createBPFMCInstPrinter);
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric     // Register the MC instruction analyzer.
1300b57cec5SDimitry Andric     TargetRegistry::RegisterMCInstrAnalysis(*T, createBPFInstrAnalysis);
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // Register the MC code emitter
1340b57cec5SDimitry Andric   TargetRegistry::RegisterMCCodeEmitter(getTheBPFleTarget(),
1350b57cec5SDimitry Andric                                         createBPFMCCodeEmitter);
1360b57cec5SDimitry Andric   TargetRegistry::RegisterMCCodeEmitter(getTheBPFbeTarget(),
1370b57cec5SDimitry Andric                                         createBPFbeMCCodeEmitter);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // Register the ASM Backend
1400b57cec5SDimitry Andric   TargetRegistry::RegisterMCAsmBackend(getTheBPFleTarget(),
1410b57cec5SDimitry Andric                                        createBPFAsmBackend);
1420b57cec5SDimitry Andric   TargetRegistry::RegisterMCAsmBackend(getTheBPFbeTarget(),
1430b57cec5SDimitry Andric                                        createBPFbeAsmBackend);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   if (sys::IsLittleEndianHost) {
1460b57cec5SDimitry Andric     TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(),
1470b57cec5SDimitry Andric                                           createBPFMCCodeEmitter);
1480b57cec5SDimitry Andric     TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(),
1490b57cec5SDimitry Andric                                          createBPFAsmBackend);
1500b57cec5SDimitry Andric   } else {
1510b57cec5SDimitry Andric     TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(),
1520b57cec5SDimitry Andric                                           createBPFbeMCCodeEmitter);
1530b57cec5SDimitry Andric     TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(),
1540b57cec5SDimitry Andric                                          createBPFbeAsmBackend);
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric }
158