1//===-- LoongArchMCTargetDesc.cpp - LoongArch 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 LoongArch specific target descriptions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LoongArchMCTargetDesc.h"
14#include "LoongArchELFStreamer.h"
15#include "LoongArchInstPrinter.h"
16#include "LoongArchMCAsmInfo.h"
17#include "TargetInfo/LoongArchTargetInfo.h"
18#include "llvm/MC/MCAsmBackend.h"
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCCodeEmitter.h"
21#include "llvm/MC/MCDwarf.h"
22#include "llvm/MC/MCInstrAnalysis.h"
23#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/MC/MCObjectWriter.h"
25#include "llvm/MC/MCRegisterInfo.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/TargetRegistry.h"
28#include "llvm/Support/Compiler.h"
29
30#define GET_INSTRINFO_MC_DESC
31#define ENABLE_INSTR_PREDICATE_VERIFIER
32#include "LoongArchGenInstrInfo.inc"
33
34#define GET_REGINFO_MC_DESC
35#include "LoongArchGenRegisterInfo.inc"
36
37#define GET_SUBTARGETINFO_MC_DESC
38#include "LoongArchGenSubtargetInfo.inc"
39
40using namespace llvm;
41
42static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) {
43 MCRegisterInfo *X = new MCRegisterInfo();
44 InitLoongArchMCRegisterInfo(RI: X, RA: LoongArch::R1);
45 return X;
46}
47
48static MCInstrInfo *createLoongArchMCInstrInfo() {
49 MCInstrInfo *X = new MCInstrInfo();
50 InitLoongArchMCInstrInfo(II: X);
51 return X;
52}
53
54static MCSubtargetInfo *
55createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
56 if (CPU.empty() || CPU == "generic")
57 CPU = TT.isArch64Bit() ? "generic-la64" : "generic-la32";
58 return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
59}
60
61static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI,
62 const Triple &TT,
63 const MCTargetOptions &Options) {
64 MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT);
65
66 // Initial state of the frame pointer is sp(r3).
67 unsigned SP = MRI.getDwarfRegNum(RegNum: LoongArch::R3, isEH: true);
68 MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(L: nullptr, Register: SP, Offset: 0);
69 MAI->addInitialFrameState(Inst);
70
71 return MAI;
72}
73
74static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T,
75 unsigned SyntaxVariant,
76 const MCAsmInfo &MAI,
77 const MCInstrInfo &MII,
78 const MCRegisterInfo &MRI) {
79 return new LoongArchInstPrinter(MAI, MII, MRI);
80}
81
82static MCTargetStreamer *
83createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
84 return STI.getTargetTriple().isOSBinFormatELF()
85 ? new LoongArchTargetELFStreamer(S, STI)
86 : nullptr;
87}
88
89static MCTargetStreamer *
90createLoongArchAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
91 MCInstPrinter *InstPrint) {
92 return new LoongArchTargetAsmStreamer(S, OS);
93}
94
95namespace {
96
97class LoongArchMCInstrAnalysis : public MCInstrAnalysis {
98public:
99 explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info)
100 : MCInstrAnalysis(Info) {}
101
102 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
103 uint64_t &Target) const override {
104 unsigned NumOps = Inst.getNumOperands();
105 if ((isBranch(Inst) && !isIndirectBranch(Inst)) ||
106 Inst.getOpcode() == LoongArch::BL) {
107 Target = Addr + Inst.getOperand(i: NumOps - 1).getImm();
108 return true;
109 }
110
111 return false;
112 }
113
114 bool isTerminator(const MCInst &Inst) const override {
115 if (MCInstrAnalysis::isTerminator(Inst))
116 return true;
117
118 switch (Inst.getOpcode()) {
119 default:
120 return false;
121 case LoongArch::JIRL:
122 return Inst.getOperand(i: 0).getReg() == LoongArch::R0;
123 }
124 }
125
126 bool isCall(const MCInst &Inst) const override {
127 if (MCInstrAnalysis::isCall(Inst))
128 return true;
129
130 switch (Inst.getOpcode()) {
131 default:
132 return false;
133 case LoongArch::JIRL:
134 return Inst.getOperand(i: 0).getReg() != LoongArch::R0;
135 }
136 }
137
138 bool isReturn(const MCInst &Inst) const override {
139 if (MCInstrAnalysis::isReturn(Inst))
140 return true;
141
142 switch (Inst.getOpcode()) {
143 default:
144 return false;
145 case LoongArch::JIRL:
146 return Inst.getOperand(i: 0).getReg() == LoongArch::R0 &&
147 Inst.getOperand(i: 1).getReg() == LoongArch::R1;
148 }
149 }
150
151 bool isBranch(const MCInst &Inst) const override {
152 if (MCInstrAnalysis::isBranch(Inst))
153 return true;
154
155 switch (Inst.getOpcode()) {
156 default:
157 return false;
158 case LoongArch::JIRL:
159 return Inst.getOperand(i: 0).getReg() == LoongArch::R0 &&
160 Inst.getOperand(i: 1).getReg() != LoongArch::R1;
161 }
162 }
163
164 bool isUnconditionalBranch(const MCInst &Inst) const override {
165 if (MCInstrAnalysis::isUnconditionalBranch(Inst))
166 return true;
167
168 switch (Inst.getOpcode()) {
169 default:
170 return false;
171 case LoongArch::JIRL:
172 return Inst.getOperand(i: 0).getReg() == LoongArch::R0 &&
173 Inst.getOperand(i: 1).getReg() != LoongArch::R1;
174 }
175 }
176
177 bool isIndirectBranch(const MCInst &Inst) const override {
178 if (MCInstrAnalysis::isIndirectBranch(Inst))
179 return true;
180
181 switch (Inst.getOpcode()) {
182 default:
183 return false;
184 case LoongArch::JIRL:
185 return Inst.getOperand(i: 0).getReg() == LoongArch::R0 &&
186 Inst.getOperand(i: 1).getReg() != LoongArch::R1;
187 }
188 }
189};
190
191} // end namespace
192
193static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) {
194 return new LoongArchMCInstrAnalysis(Info);
195}
196
197namespace {
198MCStreamer *createLoongArchELFStreamer(const Triple &T, MCContext &Context,
199 std::unique_ptr<MCAsmBackend> &&MAB,
200 std::unique_ptr<MCObjectWriter> &&MOW,
201 std::unique_ptr<MCCodeEmitter> &&MCE) {
202 return createLoongArchELFStreamer(C&: Context, MAB: std::move(MAB), MOW: std::move(MOW),
203 MCE: std::move(MCE));
204}
205} // end namespace
206
207extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
208LLVMInitializeLoongArchTargetMC() {
209 for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) {
210 TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createLoongArchMCRegisterInfo);
211 TargetRegistry::RegisterMCInstrInfo(T&: *T, Fn: createLoongArchMCInstrInfo);
212 TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createLoongArchMCSubtargetInfo);
213 TargetRegistry::RegisterMCAsmInfo(T&: *T, Fn: createLoongArchMCAsmInfo);
214 TargetRegistry::RegisterMCCodeEmitter(T&: *T, Fn: createLoongArchMCCodeEmitter);
215 TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createLoongArchAsmBackend);
216 TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createLoongArchMCInstPrinter);
217 TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createLoongArchInstrAnalysis);
218 TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createLoongArchELFStreamer);
219 TargetRegistry::RegisterObjectTargetStreamer(
220 T&: *T, Fn: createLoongArchObjectTargetStreamer);
221 TargetRegistry::RegisterAsmTargetStreamer(T&: *T,
222 Fn: createLoongArchAsmTargetStreamer);
223 }
224}
225