clang 20.0.0git
LoongArch.cpp
Go to the documentation of this file.
1//===--- LoongArch.cpp - Implement LoongArch target feature support -------===//
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 implements LoongArch TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LoongArch.h"
17#include "llvm/Support/raw_ostream.h"
18#include "llvm/TargetParser/LoongArchTargetParser.h"
19
20using namespace clang;
21using namespace clang::targets;
22
24 static const char *const GCCRegNames[] = {
25 // General purpose registers.
26 "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", "$r8", "$r9",
27 "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", "$r16", "$r17", "$r18",
28 "$r19", "$r20", "$r21", "$r22", "$r23", "$r24", "$r25", "$r26", "$r27",
29 "$r28", "$r29", "$r30", "$r31",
30 // Floating point registers.
31 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
32 "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
33 "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
34 "$f28", "$f29", "$f30", "$f31",
35 // Condition flag registers.
36 "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
37 // 128-bit vector registers.
38 "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7", "$vr8",
39 "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15", "$vr16",
40 "$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23", "$vr24",
41 "$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31",
42 // 256-bit vector registers.
43 "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6", "$xr7", "$xr8",
44 "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14", "$xr15", "$xr16",
45 "$xr17", "$xr18", "$xr19", "$xr20", "$xr21", "$xr22", "$xr23", "$xr24",
46 "$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31"};
48}
49
52 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
53 {{"zero", "$zero", "r0"}, "$r0"},
54 {{"ra", "$ra", "r1"}, "$r1"},
55 {{"tp", "$tp", "r2"}, "$r2"},
56 {{"sp", "$sp", "r3"}, "$r3"},
57 {{"a0", "$a0", "r4"}, "$r4"},
58 {{"a1", "$a1", "r5"}, "$r5"},
59 {{"a2", "$a2", "r6"}, "$r6"},
60 {{"a3", "$a3", "r7"}, "$r7"},
61 {{"a4", "$a4", "r8"}, "$r8"},
62 {{"a5", "$a5", "r9"}, "$r9"},
63 {{"a6", "$a6", "r10"}, "$r10"},
64 {{"a7", "$a7", "r11"}, "$r11"},
65 {{"t0", "$t0", "r12"}, "$r12"},
66 {{"t1", "$t1", "r13"}, "$r13"},
67 {{"t2", "$t2", "r14"}, "$r14"},
68 {{"t3", "$t3", "r15"}, "$r15"},
69 {{"t4", "$t4", "r16"}, "$r16"},
70 {{"t5", "$t5", "r17"}, "$r17"},
71 {{"t6", "$t6", "r18"}, "$r18"},
72 {{"t7", "$t7", "r19"}, "$r19"},
73 {{"t8", "$t8", "r20"}, "$r20"},
74 {{"r21"}, "$r21"},
75 {{"s9", "$s9", "r22", "fp", "$fp"}, "$r22"},
76 {{"s0", "$s0", "r23"}, "$r23"},
77 {{"s1", "$s1", "r24"}, "$r24"},
78 {{"s2", "$s2", "r25"}, "$r25"},
79 {{"s3", "$s3", "r26"}, "$r26"},
80 {{"s4", "$s4", "r27"}, "$r27"},
81 {{"s5", "$s5", "r28"}, "$r28"},
82 {{"s6", "$s6", "r29"}, "$r29"},
83 {{"s7", "$s7", "r30"}, "$r30"},
84 {{"s8", "$s8", "r31"}, "$r31"},
85 {{"$fa0"}, "$f0"},
86 {{"$fa1"}, "$f1"},
87 {{"$fa2"}, "$f2"},
88 {{"$fa3"}, "$f3"},
89 {{"$fa4"}, "$f4"},
90 {{"$fa5"}, "$f5"},
91 {{"$fa6"}, "$f6"},
92 {{"$fa7"}, "$f7"},
93 {{"$ft0"}, "$f8"},
94 {{"$ft1"}, "$f9"},
95 {{"$ft2"}, "$f10"},
96 {{"$ft3"}, "$f11"},
97 {{"$ft4"}, "$f12"},
98 {{"$ft5"}, "$f13"},
99 {{"$ft6"}, "$f14"},
100 {{"$ft7"}, "$f15"},
101 {{"$ft8"}, "$f16"},
102 {{"$ft9"}, "$f17"},
103 {{"$ft10"}, "$f18"},
104 {{"$ft11"}, "$f19"},
105 {{"$ft12"}, "$f20"},
106 {{"$ft13"}, "$f21"},
107 {{"$ft14"}, "$f22"},
108 {{"$ft15"}, "$f23"},
109 {{"$fs0"}, "$f24"},
110 {{"$fs1"}, "$f25"},
111 {{"$fs2"}, "$f26"},
112 {{"$fs3"}, "$f27"},
113 {{"$fs4"}, "$f28"},
114 {{"$fs5"}, "$f29"},
115 {{"$fs6"}, "$f30"},
116 {{"$fs7"}, "$f31"},
117 };
118 return llvm::ArrayRef(GCCRegAliases);
119}
120
122 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
123 // See the GCC definitions here:
124 // https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html
125 // Note that the 'm' constraint is handled in TargetInfo.
126 switch (*Name) {
127 default:
128 return false;
129 case 'f':
130 // A floating-point register (if available).
131 Info.setAllowsRegister();
132 return true;
133 case 'k':
134 // A memory operand whose address is formed by a base register and
135 // (optionally scaled) index register.
136 Info.setAllowsMemory();
137 return true;
138 case 'l':
139 // A signed 16-bit constant.
140 Info.setRequiresImmediate(-32768, 32767);
141 return true;
142 case 'I':
143 // A signed 12-bit constant (for arithmetic instructions).
144 Info.setRequiresImmediate(-2048, 2047);
145 return true;
146 case 'J':
147 // Integer zero.
148 Info.setRequiresImmediate(0);
149 return true;
150 case 'K':
151 // An unsigned 12-bit constant (for logic instructions).
152 Info.setRequiresImmediate(0, 4095);
153 return true;
154 case 'Z':
155 // ZB: An address that is held in a general-purpose register. The offset is
156 // zero.
157 // ZC: A memory operand whose address is formed by a base register
158 // and offset that is suitable for use in instructions with the same
159 // addressing mode as ll.w and sc.w.
160 if (Name[1] == 'C' || Name[1] == 'B') {
161 Info.setAllowsMemory();
162 ++Name; // Skip over 'Z'.
163 return true;
164 }
165 return false;
166 }
167}
168
169std::string
170LoongArchTargetInfo::convertConstraint(const char *&Constraint) const {
171 std::string R;
172 switch (*Constraint) {
173 case 'Z':
174 // "ZC"/"ZB" are two-character constraints; add "^" hint for later
175 // parsing.
176 R = "^" + std::string(Constraint, 2);
177 ++Constraint;
178 break;
179 default:
180 R = TargetInfo::convertConstraint(Constraint);
181 break;
182 }
183 return R;
184}
185
187 MacroBuilder &Builder) const {
188 Builder.defineMacro("__loongarch__");
189 unsigned GRLen = getRegisterWidth();
190 Builder.defineMacro("__loongarch_grlen", Twine(GRLen));
191 if (GRLen == 64)
192 Builder.defineMacro("__loongarch64");
193
194 if (HasFeatureD)
195 Builder.defineMacro("__loongarch_frlen", "64");
196 else if (HasFeatureF)
197 Builder.defineMacro("__loongarch_frlen", "32");
198 else
199 Builder.defineMacro("__loongarch_frlen", "0");
200
201 // Define __loongarch_arch.
202 StringRef ArchName = getCPU();
203 if (ArchName == "loongarch64") {
204 if (HasFeatureLSX) {
205 // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1"
206 // arch feature set will be used to include all sub-features belonging to
207 // the V1.1 ISA version.
209 Builder.defineMacro("__loongarch_arch",
210 Twine('"') + "la64v1.1" + Twine('"'));
211 else
212 Builder.defineMacro("__loongarch_arch",
213 Twine('"') + "la64v1.0" + Twine('"'));
214 } else {
215 Builder.defineMacro("__loongarch_arch",
216 Twine('"') + ArchName + Twine('"'));
217 }
218 } else {
219 Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));
220 }
221
222 // Define __loongarch_tune.
223 StringRef TuneCPU = getTargetOpts().TuneCPU;
224 if (TuneCPU.empty())
225 TuneCPU = ArchName;
226 Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"'));
227
228 if (HasFeatureLASX) {
229 Builder.defineMacro("__loongarch_simd_width", "256");
230 Builder.defineMacro("__loongarch_sx", Twine(1));
231 Builder.defineMacro("__loongarch_asx", Twine(1));
232 } else if (HasFeatureLSX) {
233 Builder.defineMacro("__loongarch_simd_width", "128");
234 Builder.defineMacro("__loongarch_sx", Twine(1));
235 }
237 Builder.defineMacro("__loongarch_frecipe", Twine(1));
238
239 StringRef ABI = getABI();
240 if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
241 Builder.defineMacro("__loongarch_lp64");
242
243 if (ABI == "lp64d" || ABI == "ilp32d") {
244 Builder.defineMacro("__loongarch_hard_float");
245 Builder.defineMacro("__loongarch_double_float");
246 } else if (ABI == "lp64f" || ABI == "ilp32f") {
247 Builder.defineMacro("__loongarch_hard_float");
248 Builder.defineMacro("__loongarch_single_float");
249 } else if (ABI == "lp64s" || ABI == "ilp32s") {
250 Builder.defineMacro("__loongarch_soft_float");
251 }
252
253 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
254 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
255 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
256 if (GRLen == 64)
257 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
258}
259
260static constexpr Builtin::Info BuiltinInfo[] = {
261#define BUILTIN(ID, TYPE, ATTRS) \
262 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
263#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
264 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
265#include "clang/Basic/BuiltinsLoongArch.def"
266};
267
269 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
270 const std::vector<std::string> &FeaturesVec) const {
271 if (getTriple().getArch() == llvm::Triple::loongarch64)
272 Features["64bit"] = true;
273 if (getTriple().getArch() == llvm::Triple::loongarch32)
274 Features["32bit"] = true;
275
276 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
277}
278
279/// Return true if has this feature.
280bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {
281 bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64;
282 // TODO: Handle more features.
283 return llvm::StringSwitch<bool>(Feature)
284 .Case("loongarch32", !Is64Bit)
285 .Case("loongarch64", Is64Bit)
286 .Case("32bit", !Is64Bit)
287 .Case("64bit", Is64Bit)
288 .Case("lsx", HasFeatureLSX)
289 .Case("lasx", HasFeatureLASX)
290 .Default(false);
291}
292
296}
297
299 std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
300 for (const auto &Feature : Features) {
301 if (Feature == "+d" || Feature == "+f") {
302 // "d" implies "f".
303 HasFeatureF = true;
304 if (Feature == "+d") {
305 HasFeatureD = true;
306 }
307 } else if (Feature == "+lsx")
308 HasFeatureLSX = true;
309 else if (Feature == "+lasx")
310 HasFeatureLASX = true;
311 else if (Feature == "-ual")
312 HasUnalignedAccess = false;
313 else if (Feature == "+frecipe")
314 HasFeatureFrecipe = true;
315 }
316 return true;
317}
318
319bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {
320 return llvm::LoongArch::isValidCPUName(Name);
321}
322
324 SmallVectorImpl<StringRef> &Values) const {
325 llvm::LoongArch::fillValidCPUList(Values);
326}
Defines the Diagnostic-related interfaces.
static constexpr Builtin::Info BuiltinInfo[]
Definition: Builtins.cpp:32
Defines the clang::MacroBuilder utility class.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:476
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:312
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
unsigned HasUnalignedAccess
Definition: TargetInfo.h:276
virtual unsigned getRegisterWidth() const
Return the "preferred" register width on this target.
Definition: TargetInfo.h:879
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
Definition: TargetInfo.cpp:532
virtual std::string convertConstraint(const char *&Constraint) const
Definition: TargetInfo.h:1233
std::string TuneCPU
If given, the name of the target CPU to tune code for.
Definition: TargetOptions.h:39
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: LoongArch.cpp:323
StringRef getABI() const override
Get the ABI currently in use.
Definition: LoongArch.h:60
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
Definition: LoongArch.cpp:186
ArrayRef< Builtin::Info > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
Definition: LoongArch.cpp:293
bool isValidCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name.
Definition: LoongArch.cpp:319
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
Definition: LoongArch.cpp:121
ArrayRef< const char * > getGCCRegNames() const override
Definition: LoongArch.cpp:23
bool hasFeature(StringRef Feature) const override
Return true if has this feature.
Definition: LoongArch.cpp:280
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features (e.g., +sse4).
Definition: LoongArch.cpp:298
std::string convertConstraint(const char *&Constraint) const override
Definition: LoongArch.cpp:170
bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeaturesVec) const override
Initialize the map with the default set of target features for the CPU this should include all legal ...
Definition: LoongArch.cpp:268
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition: LoongArch.cpp:51
static const char *const GCCRegNames[]
Definition: X86.cpp:44
The JSON file list parser is used to communicate input to InstallAPI.
void setRequiresImmediate(int Min, int Max)
Definition: TargetInfo.h:1153