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