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 | |
40 | using namespace llvm; |
41 | |
42 | static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { |
43 | MCRegisterInfo *X = new MCRegisterInfo(); |
44 | InitLoongArchMCRegisterInfo(RI: X, RA: LoongArch::R1); |
45 | return X; |
46 | } |
47 | |
48 | static MCInstrInfo *createLoongArchMCInstrInfo() { |
49 | MCInstrInfo *X = new MCInstrInfo(); |
50 | InitLoongArchMCInstrInfo(II: X); |
51 | return X; |
52 | } |
53 | |
54 | static MCSubtargetInfo * |
55 | createLoongArchMCSubtargetInfo(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 | |
61 | static 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 | |
74 | static 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 | |
82 | static MCTargetStreamer * |
83 | createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { |
84 | return STI.getTargetTriple().isOSBinFormatELF() |
85 | ? new LoongArchTargetELFStreamer(S, STI) |
86 | : nullptr; |
87 | } |
88 | |
89 | static MCTargetStreamer * |
90 | createLoongArchAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, |
91 | MCInstPrinter *InstPrint) { |
92 | return new LoongArchTargetAsmStreamer(S, OS); |
93 | } |
94 | |
95 | namespace { |
96 | |
97 | class LoongArchMCInstrAnalysis : public MCInstrAnalysis { |
98 | public: |
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 | |
193 | static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) { |
194 | return new LoongArchMCInstrAnalysis(Info); |
195 | } |
196 | |
197 | namespace { |
198 | MCStreamer *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 | |
207 | extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void |
208 | LLVMInitializeLoongArchTargetMC() { |
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 | |