clang 22.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/TargetParser/LoongArchTargetParser.h"
18
19using namespace clang;
20using namespace clang::targets;
21
23 static const char *const GCCRegNames[] = {
24 // General purpose registers.
25 "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", "$r8", "$r9",
26 "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", "$r16", "$r17", "$r18",
27 "$r19", "$r20", "$r21", "$r22", "$r23", "$r24", "$r25", "$r26", "$r27",
28 "$r28", "$r29", "$r30", "$r31",
29 // Floating point registers.
30 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",
31 "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",
32 "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
33 "$f28", "$f29", "$f30", "$f31",
34 // Condition flag registers.
35 "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
36 // 128-bit vector registers.
37 "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7", "$vr8",
38 "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15", "$vr16",
39 "$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23", "$vr24",
40 "$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31",
41 // 256-bit vector registers.
42 "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6", "$xr7", "$xr8",
43 "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14", "$xr15", "$xr16",
44 "$xr17", "$xr18", "$xr19", "$xr20", "$xr21", "$xr22", "$xr23", "$xr24",
45 "$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31"};
47}
48
51 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
52 {{"zero", "$zero", "r0"}, "$r0"},
53 {{"ra", "$ra", "r1"}, "$r1"},
54 {{"tp", "$tp", "r2"}, "$r2"},
55 {{"sp", "$sp", "r3"}, "$r3"},
56 {{"a0", "$a0", "r4"}, "$r4"},
57 {{"a1", "$a1", "r5"}, "$r5"},
58 {{"a2", "$a2", "r6"}, "$r6"},
59 {{"a3", "$a3", "r7"}, "$r7"},
60 {{"a4", "$a4", "r8"}, "$r8"},
61 {{"a5", "$a5", "r9"}, "$r9"},
62 {{"a6", "$a6", "r10"}, "$r10"},
63 {{"a7", "$a7", "r11"}, "$r11"},
64 {{"t0", "$t0", "r12"}, "$r12"},
65 {{"t1", "$t1", "r13"}, "$r13"},
66 {{"t2", "$t2", "r14"}, "$r14"},
67 {{"t3", "$t3", "r15"}, "$r15"},
68 {{"t4", "$t4", "r16"}, "$r16"},
69 {{"t5", "$t5", "r17"}, "$r17"},
70 {{"t6", "$t6", "r18"}, "$r18"},
71 {{"t7", "$t7", "r19"}, "$r19"},
72 {{"t8", "$t8", "r20"}, "$r20"},
73 {{"r21"}, "$r21"},
74 {{"s9", "$s9", "r22", "fp", "$fp"}, "$r22"},
75 {{"s0", "$s0", "r23"}, "$r23"},
76 {{"s1", "$s1", "r24"}, "$r24"},
77 {{"s2", "$s2", "r25"}, "$r25"},
78 {{"s3", "$s3", "r26"}, "$r26"},
79 {{"s4", "$s4", "r27"}, "$r27"},
80 {{"s5", "$s5", "r28"}, "$r28"},
81 {{"s6", "$s6", "r29"}, "$r29"},
82 {{"s7", "$s7", "r30"}, "$r30"},
83 {{"s8", "$s8", "r31"}, "$r31"},
84 {{"fa0", "$fa0", "f0"}, "$f0"},
85 {{"fa1", "$fa1", "f1"}, "$f1"},
86 {{"fa2", "$fa2", "f2"}, "$f2"},
87 {{"fa3", "$fa3", "f3"}, "$f3"},
88 {{"fa4", "$fa4", "f4"}, "$f4"},
89 {{"fa5", "$fa5", "f5"}, "$f5"},
90 {{"fa6", "$fa6", "f6"}, "$f6"},
91 {{"fa7", "$fa7", "f7"}, "$f7"},
92 {{"ft0", "$ft0", "f8"}, "$f8"},
93 {{"ft1", "$ft1", "f9"}, "$f9"},
94 {{"ft2", "$ft2", "f10"}, "$f10"},
95 {{"ft3", "$ft3", "f11"}, "$f11"},
96 {{"ft4", "$ft4", "f12"}, "$f12"},
97 {{"ft5", "$ft5", "f13"}, "$f13"},
98 {{"ft6", "$ft6", "f14"}, "$f14"},
99 {{"ft7", "$ft7", "f15"}, "$f15"},
100 {{"ft8", "$ft8", "f16"}, "$f16"},
101 {{"ft9", "$ft9", "f17"}, "$f17"},
102 {{"ft10", "$ft10", "f18"}, "$f18"},
103 {{"ft11", "$ft11", "f19"}, "$f19"},
104 {{"ft12", "$ft12", "f20"}, "$f20"},
105 {{"ft13", "$ft13", "f21"}, "$f21"},
106 {{"ft14", "$ft14", "f22"}, "$f22"},
107 {{"ft15", "$ft15", "f23"}, "$f23"},
108 {{"fs0", "$fs0", "f24"}, "$f24"},
109 {{"fs1", "$fs1", "f25"}, "$f25"},
110 {{"fs2", "$fs2", "f26"}, "$f26"},
111 {{"fs3", "$fs3", "f27"}, "$f27"},
112 {{"fs4", "$fs4", "f28"}, "$f28"},
113 {{"fs5", "$fs5", "f29"}, "$f29"},
114 {{"fs6", "$fs6", "f30"}, "$f30"},
115 {{"fs7", "$fs7", "f31"}, "$f31"},
116 {{"fcc0"}, "$fcc0"},
117 {{"fcc1"}, "$fcc1"},
118 {{"fcc2"}, "$fcc2"},
119 {{"fcc3"}, "$fcc3"},
120 {{"fcc4"}, "$fcc4"},
121 {{"fcc5"}, "$fcc5"},
122 {{"fcc6"}, "$fcc6"},
123 {{"fcc7"}, "$fcc7"},
124 };
125 return llvm::ArrayRef(GCCRegAliases);
126}
127
129 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
130 // See the GCC definitions here:
131 // https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html
132 // Note that the 'm' constraint is handled in TargetInfo.
133 switch (*Name) {
134 default:
135 return false;
136 case 'f':
137 // A floating-point register (if available).
138 Info.setAllowsRegister();
139 return true;
140 case 'k':
141 // A memory operand whose address is formed by a base register and
142 // (optionally scaled) index register.
143 Info.setAllowsMemory();
144 return true;
145 case 'l':
146 // A signed 16-bit constant.
147 Info.setRequiresImmediate(-32768, 32767);
148 return true;
149 case 'q':
150 // A general-purpose register except for $r0 and $r1 (for the csrxchg
151 // instruction)
152 Info.setAllowsRegister();
153 return true;
154 case 'I':
155 // A signed 12-bit constant (for arithmetic instructions).
156 Info.setRequiresImmediate(-2048, 2047);
157 return true;
158 case 'J':
159 // Integer zero.
160 Info.setRequiresImmediate(0);
161 return true;
162 case 'K':
163 // An unsigned 12-bit constant (for logic instructions).
164 Info.setRequiresImmediate(0, 4095);
165 return true;
166 case 'Z':
167 // ZB: An address that is held in a general-purpose register. The offset is
168 // zero.
169 // ZC: A memory operand whose address is formed by a base register
170 // and offset that is suitable for use in instructions with the same
171 // addressing mode as ll.w and sc.w.
172 if (Name[1] == 'C' || Name[1] == 'B') {
173 Info.setAllowsMemory();
174 ++Name; // Skip over 'Z'.
175 return true;
176 }
177 return false;
178 }
179}
180
181std::string
182LoongArchTargetInfo::convertConstraint(const char *&Constraint) const {
183 std::string R;
184 switch (*Constraint) {
185 case 'Z':
186 // "ZC"/"ZB" are two-character constraints; add "^" hint for later
187 // parsing.
188 R = "^" + std::string(Constraint, 2);
189 ++Constraint;
190 break;
191 default:
192 R = TargetInfo::convertConstraint(Constraint);
193 break;
194 }
195 return R;
196}
197
199 MacroBuilder &Builder) const {
200 Builder.defineMacro("__loongarch__");
201 unsigned GRLen = getRegisterWidth();
202 Builder.defineMacro("__loongarch_grlen", Twine(GRLen));
203 if (GRLen == 64)
204 Builder.defineMacro("__loongarch64");
205
206 if (HasFeatureD)
207 Builder.defineMacro("__loongarch_frlen", "64");
208 else if (HasFeatureF)
209 Builder.defineMacro("__loongarch_frlen", "32");
210 else
211 Builder.defineMacro("__loongarch_frlen", "0");
212
213 // Define __loongarch_arch.
214 StringRef ArchName = getCPU();
215 if (ArchName == "loongarch64") {
216 if (HasFeatureLSX) {
217 // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1"
218 // arch feature set will be used to include all sub-features belonging to
219 // the V1.1 ISA version.
222 Builder.defineMacro("__loongarch_arch",
223 Twine('"') + "la64v1.1" + Twine('"'));
224 else
225 Builder.defineMacro("__loongarch_arch",
226 Twine('"') + "la64v1.0" + Twine('"'));
227 } else {
228 Builder.defineMacro("__loongarch_arch",
229 Twine('"') + ArchName + Twine('"'));
230 }
231 } else {
232 Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"'));
233 }
234
235 // Define __loongarch_tune.
236 StringRef TuneCPU = getTargetOpts().TuneCPU;
237 if (TuneCPU.empty())
238 TuneCPU = ArchName;
239 Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"'));
240
241 if (HasFeatureLASX) {
242 Builder.defineMacro("__loongarch_simd_width", "256");
243 Builder.defineMacro("__loongarch_sx", Twine(1));
244 Builder.defineMacro("__loongarch_asx", Twine(1));
245 Builder.defineMacro("__loongarch_asx_sx_conv", Twine(1));
246 } else if (HasFeatureLSX) {
247 Builder.defineMacro("__loongarch_simd_width", "128");
248 Builder.defineMacro("__loongarch_sx", Twine(1));
249 }
251 Builder.defineMacro("__loongarch_frecipe", Twine(1));
252
254 Builder.defineMacro("__loongarch_lam_bh", Twine(1));
255
257 Builder.defineMacro("__loongarch_lamcas", Twine(1));
258
260 Builder.defineMacro("__loongarch_ld_seq_sa", Twine(1));
261
262 if (HasFeatureDiv32)
263 Builder.defineMacro("__loongarch_div32", Twine(1));
264
265 if (HasFeatureSCQ)
266 Builder.defineMacro("__loongarch_scq", Twine(1));
267
268 StringRef ABI = getABI();
269 if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
270 Builder.defineMacro("__loongarch_lp64");
271
272 if (ABI == "lp64d" || ABI == "ilp32d") {
273 Builder.defineMacro("__loongarch_hard_float");
274 Builder.defineMacro("__loongarch_double_float");
275 } else if (ABI == "lp64f" || ABI == "ilp32f") {
276 Builder.defineMacro("__loongarch_hard_float");
277 Builder.defineMacro("__loongarch_single_float");
278 } else if (ABI == "lp64s" || ABI == "ilp32s") {
279 Builder.defineMacro("__loongarch_soft_float");
280 }
281
282 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
283 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
284 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
285 if (GRLen == 64)
286 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
287}
288
289static constexpr int NumBaseBuiltins =
291static constexpr int NumLSXBuiltins =
293static constexpr int NumLASXBuiltins =
295static constexpr int NumBuiltins =
297static_assert(NumBuiltins ==
299
300static constexpr llvm::StringTable BuiltinBaseStrings =
302#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
303#include "clang/Basic/BuiltinsLoongArchBase.def"
304#undef TARGET_BUILTIN
305 ;
306
308#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
309#include "clang/Basic/BuiltinsLoongArchBase.def"
310#undef TARGET_BUILTIN
311});
312
313static constexpr llvm::StringTable BuiltinLSXStrings =
315#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
316#include "clang/Basic/BuiltinsLoongArchLSX.def"
317#undef TARGET_BUILTIN
318 ;
319
321#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
322#include "clang/Basic/BuiltinsLoongArchLSX.def"
323#undef TARGET_BUILTIN
324});
325
326static constexpr llvm::StringTable BuiltinLASXStrings =
328#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
329#include "clang/Basic/BuiltinsLoongArchLASX.def"
330#undef TARGET_BUILTIN
331 ;
332
334#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
335#include "clang/Basic/BuiltinsLoongArchLASX.def"
336#undef TARGET_BUILTIN
337});
338
340 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
341 const std::vector<std::string> &FeaturesVec) const {
342 if (getTriple().getArch() == llvm::Triple::loongarch64)
343 Features["64bit"] = true;
344 if (getTriple().getArch() == llvm::Triple::loongarch32)
345 Features["32bit"] = true;
346
347 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
348}
349
350/// Return true if has this feature.
352 bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64;
353 // TODO: Handle more features.
354 return llvm::StringSwitch<bool>(Feature)
355 .Case("loongarch32", !Is64Bit)
356 .Case("loongarch64", Is64Bit)
357 .Case("32bit", !Is64Bit)
358 .Case("64bit", Is64Bit)
359 .Case("lsx", HasFeatureLSX)
360 .Case("lasx", HasFeatureLASX)
361 .Default(false);
362}
363
372
374 std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
375 for (const auto &Feature : Features) {
376 if (Feature == "+d" || Feature == "+f") {
377 // "d" implies "f".
378 HasFeatureF = true;
379 if (Feature == "+d") {
380 HasFeatureD = true;
381 }
382 } else if (Feature == "+lsx")
383 HasFeatureLSX = true;
384 else if (Feature == "+lasx")
385 HasFeatureLASX = true;
386 else if (Feature == "-ual")
387 HasUnalignedAccess = false;
388 else if (Feature == "+frecipe")
389 HasFeatureFrecipe = true;
390 else if (Feature == "+lam-bh")
391 HasFeatureLAM_BH = true;
392 else if (Feature == "+lamcas")
393 HasFeatureLAMCAS = true;
394 else if (Feature == "+ld-seq-sa")
395 HasFeatureLD_SEQ_SA = true;
396 else if (Feature == "+div32")
397 HasFeatureDiv32 = true;
398 else if (Feature == "+scq")
399 HasFeatureSCQ = true;
400 }
401 return true;
402}
403
405
406static std::pair<AttrFeatureKind, llvm::StringRef>
407getAttrFeatureTypeAndValue(llvm::StringRef AttrFeature) {
408 if (auto Split = AttrFeature.split("="); !Split.second.empty()) {
409 if (Split.first.trim() == "arch")
410 return {AttrFeatureKind::Arch, Split.second.trim()};
411 if (Split.first.trim() == "tune")
412 return {AttrFeatureKind::Tune, Split.second.trim()};
413 }
414 if (AttrFeature.starts_with("no-"))
415 return {AttrFeatureKind::NoFeature, AttrFeature.drop_front(3)};
416 return {AttrFeatureKind::Feature, AttrFeature};
417}
418
419ParsedTargetAttr
420LoongArchTargetInfo::parseTargetAttr(StringRef Features) const {
422 if (Features == "default")
423 return Ret;
424 SmallVector<StringRef, 1> AttrFeatures;
425 Features.split(AttrFeatures, ",");
426
427 for (auto &Feature : AttrFeatures) {
428 auto [Kind, Value] = getAttrFeatureTypeAndValue(Feature.trim());
429
430 switch (Kind) {
432 if (llvm::LoongArch::isValidArchName(Value) || Value == "la64v1.0" ||
433 Value == "la64v1.1") {
434 std::vector<llvm::StringRef> ArchFeatures;
435 if (llvm::LoongArch::getArchFeatures(Value, ArchFeatures)) {
436 Ret.Features.insert(Ret.Features.end(), ArchFeatures.begin(),
437 ArchFeatures.end());
438 }
439
440 if (!Ret.CPU.empty())
441 Ret.Duplicate = "arch=";
442 else if (Value == "la64v1.0" || Value == "la64v1.1")
443 Ret.CPU = "loongarch64";
444 else
445 Ret.CPU = Value;
446 } else {
447 Ret.Features.push_back("!arch=" + Value.str());
448 }
449 break;
450 }
451
453 if (!Ret.Tune.empty())
454 Ret.Duplicate = "tune=";
455 else
456 Ret.Tune = Value;
457 break;
458
460 Ret.Features.push_back("-" + Value.str());
461 break;
462
464 Ret.Features.push_back("+" + Value.str());
465 if (Value == "lasx")
466 Ret.Features.push_back("+lsx");
467 break;
468 }
469 }
470 return Ret;
471}
472
473bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const {
474 return llvm::LoongArch::isValidCPUName(Name);
475}
476
478 SmallVectorImpl<StringRef> &Values) const {
479 llvm::LoongArch::fillValidCPUList(Values);
480}
481
482bool LoongArchTargetInfo::isValidFeatureName(StringRef Name) const {
483 return llvm::LoongArch::isValidFeatureName(Name);
484}
Defines the Diagnostic-related interfaces.
AttrFeatureKind
static constexpr llvm::StringTable BuiltinLSXStrings
static std::pair< AttrFeatureKind, llvm::StringRef > getAttrFeatureTypeAndValue(llvm::StringRef AttrFeature)
static constexpr llvm::StringTable BuiltinBaseStrings
static constexpr int NumBaseBuiltins
static constexpr int NumLSXBuiltins
static constexpr auto BuiltinBaseInfos
static constexpr auto BuiltinLSXInfos
static constexpr llvm::StringTable BuiltinLASXStrings
static constexpr int NumLASXBuiltins
static constexpr auto BuiltinLASXInfos
static constexpr unsigned NumBuiltins
Definition Builtins.cpp:32
#define CLANG_BUILTIN_STR_TABLE_START
Definition Builtins.h:165
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:232
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:326
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned HasUnalignedAccess
Definition TargetInfo.h:284
virtual unsigned getRegisterWidth() const
Return the "preferred" register width on this target.
Definition TargetInfo.h:903
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 ...
virtual std::string convertConstraint(const char *&Constraint) const
std::string TuneCPU
If given, the name of the target CPU to tune code for.
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
ParsedTargetAttr parseTargetAttr(StringRef Str) const override
StringRef getABI() const override
Get the ABI currently in use.
Definition LoongArch.h:75
llvm::SmallVector< Builtin::InfosShard > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
bool isValidCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name.
bool isValidFeatureName(StringRef Name) const override
Determine whether this TargetInfo supports the given feature.
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
ArrayRef< const char * > getGCCRegNames() const override
Definition LoongArch.cpp:22
bool hasFeature(StringRef Feature) const override
Return true if has this feature.
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features (e.g., +sse4).
std::string convertConstraint(const char *&Constraint) const override
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 ...
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition LoongArch.cpp:50
static constexpr std::array< Info, N > MakeInfos(std::array< Info, N > Infos)
A constexpr function to construct an infos array from X-macros.
Definition Builtins.h:114
static const char *const GCCRegNames[]
Definition X86.cpp:73
The JSON file list parser is used to communicate input to InstallAPI.
Contains information gathered from parsing the contents of TargetAttr.
Definition TargetInfo.h:60
void setRequiresImmediate(int Min, int Max)