1 //===-- BPFMCTargetDesc.cpp - BPF Target Descriptions ---------------------===//
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 provides BPF specific target descriptions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MCTargetDesc/BPFMCTargetDesc.h"
14 #include "MCTargetDesc/BPFInstPrinter.h"
15 #include "MCTargetDesc/BPFMCAsmInfo.h"
16 #include "TargetInfo/BPFTargetInfo.h"
17 #include "llvm/MC/MCInstrAnalysis.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/Host.h"
22 #include "llvm/Support/TargetRegistry.h"
23 
24 #define GET_INSTRINFO_MC_DESC
25 #include "BPFGenInstrInfo.inc"
26 
27 #define GET_SUBTARGETINFO_MC_DESC
28 #include "BPFGenSubtargetInfo.inc"
29 
30 #define GET_REGINFO_MC_DESC
31 #include "BPFGenRegisterInfo.inc"
32 
33 using namespace llvm;
34 
createBPFMCInstrInfo()35 static MCInstrInfo *createBPFMCInstrInfo() {
36   MCInstrInfo *X = new MCInstrInfo();
37   InitBPFMCInstrInfo(X);
38   return X;
39 }
40 
createBPFMCRegisterInfo(const Triple & TT)41 static MCRegisterInfo *createBPFMCRegisterInfo(const Triple &TT) {
42   MCRegisterInfo *X = new MCRegisterInfo();
43   InitBPFMCRegisterInfo(X, BPF::R11 /* RAReg doesn't exist */);
44   return X;
45 }
46 
createBPFMCSubtargetInfo(const Triple & TT,StringRef CPU,StringRef FS)47 static MCSubtargetInfo *createBPFMCSubtargetInfo(const Triple &TT,
48                                                  StringRef CPU, StringRef FS) {
49   return createBPFMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
50 }
51 
createBPFMCStreamer(const Triple & T,MCContext & Ctx,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && Emitter,bool RelaxAll)52 static MCStreamer *createBPFMCStreamer(const Triple &T, MCContext &Ctx,
53                                        std::unique_ptr<MCAsmBackend> &&MAB,
54                                        std::unique_ptr<MCObjectWriter> &&OW,
55                                        std::unique_ptr<MCCodeEmitter> &&Emitter,
56                                        bool RelaxAll) {
57   return createELFStreamer(Ctx, std::move(MAB), std::move(OW), std::move(Emitter),
58                            RelaxAll);
59 }
60 
createBPFMCInstPrinter(const Triple & T,unsigned SyntaxVariant,const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)61 static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,
62                                              unsigned SyntaxVariant,
63                                              const MCAsmInfo &MAI,
64                                              const MCInstrInfo &MII,
65                                              const MCRegisterInfo &MRI) {
66   if (SyntaxVariant == 0)
67     return new BPFInstPrinter(MAI, MII, MRI);
68   return nullptr;
69 }
70 
71 namespace {
72 
73 class BPFMCInstrAnalysis : public MCInstrAnalysis {
74 public:
BPFMCInstrAnalysis(const MCInstrInfo * Info)75   explicit BPFMCInstrAnalysis(const MCInstrInfo *Info)
76       : MCInstrAnalysis(Info) {}
77 
evaluateBranch(const MCInst & Inst,uint64_t Addr,uint64_t Size,uint64_t & Target) const78   bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
79                       uint64_t &Target) const override {
80     // The target is the 3rd operand of cond inst and the 1st of uncond inst.
81     int16_t Imm;
82     if (isConditionalBranch(Inst)) {
83       Imm = Inst.getOperand(2).getImm();
84     } else if (isUnconditionalBranch(Inst))
85       Imm = Inst.getOperand(0).getImm();
86     else
87       return false;
88 
89     Target = Addr + Size + Imm * Size;
90     return true;
91   }
92 };
93 
94 } // end anonymous namespace
95 
createBPFInstrAnalysis(const MCInstrInfo * Info)96 static MCInstrAnalysis *createBPFInstrAnalysis(const MCInstrInfo *Info) {
97   return new BPFMCInstrAnalysis(Info);
98 }
99 
LLVMInitializeBPFTargetMC()100 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFTargetMC() {
101   for (Target *T :
102        {&getTheBPFleTarget(), &getTheBPFbeTarget(), &getTheBPFTarget()}) {
103     // Register the MC asm info.
104     RegisterMCAsmInfo<BPFMCAsmInfo> X(*T);
105 
106     // Register the MC instruction info.
107     TargetRegistry::RegisterMCInstrInfo(*T, createBPFMCInstrInfo);
108 
109     // Register the MC register info.
110     TargetRegistry::RegisterMCRegInfo(*T, createBPFMCRegisterInfo);
111 
112     // Register the MC subtarget info.
113     TargetRegistry::RegisterMCSubtargetInfo(*T,
114                                             createBPFMCSubtargetInfo);
115 
116     // Register the object streamer
117     TargetRegistry::RegisterELFStreamer(*T, createBPFMCStreamer);
118 
119     // Register the MCInstPrinter.
120     TargetRegistry::RegisterMCInstPrinter(*T, createBPFMCInstPrinter);
121 
122     // Register the MC instruction analyzer.
123     TargetRegistry::RegisterMCInstrAnalysis(*T, createBPFInstrAnalysis);
124   }
125 
126   // Register the MC code emitter
127   TargetRegistry::RegisterMCCodeEmitter(getTheBPFleTarget(),
128                                         createBPFMCCodeEmitter);
129   TargetRegistry::RegisterMCCodeEmitter(getTheBPFbeTarget(),
130                                         createBPFbeMCCodeEmitter);
131 
132   // Register the ASM Backend
133   TargetRegistry::RegisterMCAsmBackend(getTheBPFleTarget(),
134                                        createBPFAsmBackend);
135   TargetRegistry::RegisterMCAsmBackend(getTheBPFbeTarget(),
136                                        createBPFbeAsmBackend);
137 
138   if (sys::IsLittleEndianHost) {
139     TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(),
140                                           createBPFMCCodeEmitter);
141     TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(),
142                                          createBPFAsmBackend);
143   } else {
144     TargetRegistry::RegisterMCCodeEmitter(getTheBPFTarget(),
145                                           createBPFbeMCCodeEmitter);
146     TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(),
147                                          createBPFbeAsmBackend);
148   }
149 
150 }
151