1 //===--- LoongArch.cpp - Implement LoongArch target feature support -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements LoongArch TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #include "LoongArch.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/MacroBuilder.h"
16 #include "clang/Basic/TargetBuiltins.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/TargetParser/LoongArchTargetParser.h"
20 using namespace clang
;
21 using namespace clang::targets
;
23 ArrayRef
<const char *> LoongArchTargetInfo::getGCCRegNames() const {
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"};
47 return llvm::ArrayRef(GCCRegNames
);
50 ArrayRef
<TargetInfo::GCCRegAlias
>
51 LoongArchTargetInfo::getGCCRegAliases() const {
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"},
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"},
118 return llvm::ArrayRef(GCCRegAliases
);
121 bool LoongArchTargetInfo::validateAsmConstraint(
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.
130 // A floating-point register (if available).
131 Info
.setAllowsRegister();
134 // A memory operand whose address is formed by a base register and
135 // (optionally scaled) index register.
136 Info
.setAllowsMemory();
139 // A signed 16-bit constant.
140 Info
.setRequiresImmediate(-32768, 32767);
143 // A signed 12-bit constant (for arithmetic instructions).
144 Info
.setRequiresImmediate(-2048, 2047);
148 Info
.setRequiresImmediate(0);
151 // An unsigned 12-bit constant (for logic instructions).
152 Info
.setRequiresImmediate(0, 4095);
155 // ZB: An address that is held in a general-purpose register. The offset is
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'.
170 LoongArchTargetInfo::convertConstraint(const char *&Constraint
) const {
172 switch (*Constraint
) {
174 // "ZC"/"ZB" are two-character constraints; add "^" hint for later
176 R
= "^" + std::string(Constraint
, 2);
180 R
= TargetInfo::convertConstraint(Constraint
);
186 void LoongArchTargetInfo::getTargetDefines(const LangOptions
&Opts
,
187 MacroBuilder
&Builder
) const {
188 Builder
.defineMacro("__loongarch__");
189 unsigned GRLen
= getRegisterWidth();
190 Builder
.defineMacro("__loongarch_grlen", Twine(GRLen
));
192 Builder
.defineMacro("__loongarch64");
195 Builder
.defineMacro("__loongarch_frlen", "64");
196 else if (HasFeatureF
)
197 Builder
.defineMacro("__loongarch_frlen", "32");
199 Builder
.defineMacro("__loongarch_frlen", "0");
201 // Define __loongarch_arch.
202 StringRef ArchName
= getCPU();
203 Builder
.defineMacro("__loongarch_arch", Twine('"') + ArchName
+ Twine('"'));
205 // Define __loongarch_tune.
206 StringRef TuneCPU
= getTargetOpts().TuneCPU
;
209 Builder
.defineMacro("__loongarch_tune", Twine('"') + TuneCPU
+ Twine('"'));
212 Builder
.defineMacro("__loongarch_sx", Twine(1));
214 Builder
.defineMacro("__loongarch_asx", Twine(1));
216 StringRef ABI
= getABI();
217 if (ABI
== "lp64d" || ABI
== "lp64f" || ABI
== "lp64s")
218 Builder
.defineMacro("__loongarch_lp64");
220 if (ABI
== "lp64d" || ABI
== "ilp32d") {
221 Builder
.defineMacro("__loongarch_hard_float");
222 Builder
.defineMacro("__loongarch_double_float");
223 } else if (ABI
== "lp64f" || ABI
== "ilp32f") {
224 Builder
.defineMacro("__loongarch_hard_float");
225 Builder
.defineMacro("__loongarch_single_float");
226 } else if (ABI
== "lp64s" || ABI
== "ilp32s") {
227 Builder
.defineMacro("__loongarch_soft_float");
230 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
231 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
232 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
234 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
237 static constexpr Builtin::Info BuiltinInfo
[] = {
238 #define BUILTIN(ID, TYPE, ATTRS) \
239 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
240 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
241 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
242 #include "clang/Basic/BuiltinsLoongArch.def"
245 bool LoongArchTargetInfo::initFeatureMap(
246 llvm::StringMap
<bool> &Features
, DiagnosticsEngine
&Diags
, StringRef CPU
,
247 const std::vector
<std::string
> &FeaturesVec
) const {
248 if (getTriple().getArch() == llvm::Triple::loongarch64
)
249 Features
["64bit"] = true;
250 if (getTriple().getArch() == llvm::Triple::loongarch32
)
251 Features
["32bit"] = true;
253 return TargetInfo::initFeatureMap(Features
, Diags
, CPU
, FeaturesVec
);
256 /// Return true if has this feature.
257 bool LoongArchTargetInfo::hasFeature(StringRef Feature
) const {
258 bool Is64Bit
= getTriple().getArch() == llvm::Triple::loongarch64
;
259 // TODO: Handle more features.
260 return llvm::StringSwitch
<bool>(Feature
)
261 .Case("loongarch32", !Is64Bit
)
262 .Case("loongarch64", Is64Bit
)
263 .Case("32bit", !Is64Bit
)
264 .Case("64bit", Is64Bit
)
265 .Case("lsx", HasFeatureLSX
)
266 .Case("lasx", HasFeatureLASX
)
270 ArrayRef
<Builtin::Info
> LoongArchTargetInfo::getTargetBuiltins() const {
271 return llvm::ArrayRef(BuiltinInfo
, clang::LoongArch::LastTSBuiltin
-
272 Builtin::FirstTSBuiltin
);
275 bool LoongArchTargetInfo::handleTargetFeatures(
276 std::vector
<std::string
> &Features
, DiagnosticsEngine
&Diags
) {
277 for (const auto &Feature
: Features
) {
278 if (Feature
== "+d" || Feature
== "+f") {
281 if (Feature
== "+d") {
284 } else if (Feature
== "+lsx")
285 HasFeatureLSX
= true;
286 else if (Feature
== "+lasx")
287 HasFeatureLASX
= true;
292 bool LoongArchTargetInfo::isValidCPUName(StringRef Name
) const {
293 return llvm::LoongArch::isValidCPUName(Name
);
296 void LoongArchTargetInfo::fillValidCPUList(
297 SmallVectorImpl
<StringRef
> &Values
) const {
298 llvm::LoongArch::fillValidCPUList(Values
);