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" |
14 | #include "clang/Basic/Diagnostic.h" |
15 | #include "clang/Basic/MacroBuilder.h" |
16 | #include "clang/Basic/TargetBuiltins.h" |
17 | #include "llvm/TargetParser/LoongArchTargetParser.h" |
18 | |
19 | using namespace clang; |
20 | using namespace clang::targets; |
21 | |
22 | ArrayRef<const char *> LoongArchTargetInfo::getGCCRegNames() const { |
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"}; |
46 | return llvm::ArrayRef(GCCRegNames); |
47 | } |
48 | |
49 | ArrayRef<TargetInfo::GCCRegAlias> |
50 | LoongArchTargetInfo::getGCCRegAliases() const { |
51 | static const TargetInfo::GCCRegAlias GCCRegAliases[] = { |
52 | {.Aliases: {"zero", "$zero", "r0"}, .Register: "$r0"}, |
53 | {.Aliases: {"ra", "$ra", "r1"}, .Register: "$r1"}, |
54 | {.Aliases: {"tp", "$tp", "r2"}, .Register: "$r2"}, |
55 | {.Aliases: {"sp", "$sp", "r3"}, .Register: "$r3"}, |
56 | {.Aliases: {"a0", "$a0", "r4"}, .Register: "$r4"}, |
57 | {.Aliases: {"a1", "$a1", "r5"}, .Register: "$r5"}, |
58 | {.Aliases: {"a2", "$a2", "r6"}, .Register: "$r6"}, |
59 | {.Aliases: {"a3", "$a3", "r7"}, .Register: "$r7"}, |
60 | {.Aliases: {"a4", "$a4", "r8"}, .Register: "$r8"}, |
61 | {.Aliases: {"a5", "$a5", "r9"}, .Register: "$r9"}, |
62 | {.Aliases: {"a6", "$a6", "r10"}, .Register: "$r10"}, |
63 | {.Aliases: {"a7", "$a7", "r11"}, .Register: "$r11"}, |
64 | {.Aliases: {"t0", "$t0", "r12"}, .Register: "$r12"}, |
65 | {.Aliases: {"t1", "$t1", "r13"}, .Register: "$r13"}, |
66 | {.Aliases: {"t2", "$t2", "r14"}, .Register: "$r14"}, |
67 | {.Aliases: {"t3", "$t3", "r15"}, .Register: "$r15"}, |
68 | {.Aliases: {"t4", "$t4", "r16"}, .Register: "$r16"}, |
69 | {.Aliases: {"t5", "$t5", "r17"}, .Register: "$r17"}, |
70 | {.Aliases: {"t6", "$t6", "r18"}, .Register: "$r18"}, |
71 | {.Aliases: {"t7", "$t7", "r19"}, .Register: "$r19"}, |
72 | {.Aliases: {"t8", "$t8", "r20"}, .Register: "$r20"}, |
73 | {.Aliases: {"r21"}, .Register: "$r21"}, |
74 | {.Aliases: {"s9", "$s9", "r22", "fp", "$fp"}, .Register: "$r22"}, |
75 | {.Aliases: {"s0", "$s0", "r23"}, .Register: "$r23"}, |
76 | {.Aliases: {"s1", "$s1", "r24"}, .Register: "$r24"}, |
77 | {.Aliases: {"s2", "$s2", "r25"}, .Register: "$r25"}, |
78 | {.Aliases: {"s3", "$s3", "r26"}, .Register: "$r26"}, |
79 | {.Aliases: {"s4", "$s4", "r27"}, .Register: "$r27"}, |
80 | {.Aliases: {"s5", "$s5", "r28"}, .Register: "$r28"}, |
81 | {.Aliases: {"s6", "$s6", "r29"}, .Register: "$r29"}, |
82 | {.Aliases: {"s7", "$s7", "r30"}, .Register: "$r30"}, |
83 | {.Aliases: {"s8", "$s8", "r31"}, .Register: "$r31"}, |
84 | {.Aliases: {"$fa0"}, .Register: "$f0"}, |
85 | {.Aliases: {"$fa1"}, .Register: "$f1"}, |
86 | {.Aliases: {"$fa2"}, .Register: "$f2"}, |
87 | {.Aliases: {"$fa3"}, .Register: "$f3"}, |
88 | {.Aliases: {"$fa4"}, .Register: "$f4"}, |
89 | {.Aliases: {"$fa5"}, .Register: "$f5"}, |
90 | {.Aliases: {"$fa6"}, .Register: "$f6"}, |
91 | {.Aliases: {"$fa7"}, .Register: "$f7"}, |
92 | {.Aliases: {"$ft0"}, .Register: "$f8"}, |
93 | {.Aliases: {"$ft1"}, .Register: "$f9"}, |
94 | {.Aliases: {"$ft2"}, .Register: "$f10"}, |
95 | {.Aliases: {"$ft3"}, .Register: "$f11"}, |
96 | {.Aliases: {"$ft4"}, .Register: "$f12"}, |
97 | {.Aliases: {"$ft5"}, .Register: "$f13"}, |
98 | {.Aliases: {"$ft6"}, .Register: "$f14"}, |
99 | {.Aliases: {"$ft7"}, .Register: "$f15"}, |
100 | {.Aliases: {"$ft8"}, .Register: "$f16"}, |
101 | {.Aliases: {"$ft9"}, .Register: "$f17"}, |
102 | {.Aliases: {"$ft10"}, .Register: "$f18"}, |
103 | {.Aliases: {"$ft11"}, .Register: "$f19"}, |
104 | {.Aliases: {"$ft12"}, .Register: "$f20"}, |
105 | {.Aliases: {"$ft13"}, .Register: "$f21"}, |
106 | {.Aliases: {"$ft14"}, .Register: "$f22"}, |
107 | {.Aliases: {"$ft15"}, .Register: "$f23"}, |
108 | {.Aliases: {"$fs0"}, .Register: "$f24"}, |
109 | {.Aliases: {"$fs1"}, .Register: "$f25"}, |
110 | {.Aliases: {"$fs2"}, .Register: "$f26"}, |
111 | {.Aliases: {"$fs3"}, .Register: "$f27"}, |
112 | {.Aliases: {"$fs4"}, .Register: "$f28"}, |
113 | {.Aliases: {"$fs5"}, .Register: "$f29"}, |
114 | {.Aliases: {"$fs6"}, .Register: "$f30"}, |
115 | {.Aliases: {"$fs7"}, .Register: "$f31"}, |
116 | }; |
117 | return llvm::ArrayRef(GCCRegAliases); |
118 | } |
119 | |
120 | bool LoongArchTargetInfo::validateAsmConstraint( |
121 | const char *&Name, TargetInfo::ConstraintInfo &Info) const { |
122 | // See the GCC definitions here: |
123 | // https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html |
124 | // Note that the 'm' constraint is handled in TargetInfo. |
125 | switch (*Name) { |
126 | default: |
127 | return false; |
128 | case 'f': |
129 | // A floating-point register (if available). |
130 | Info.setAllowsRegister(); |
131 | return true; |
132 | case 'k': |
133 | // A memory operand whose address is formed by a base register and |
134 | // (optionally scaled) index register. |
135 | Info.setAllowsMemory(); |
136 | return true; |
137 | case 'l': |
138 | // A signed 16-bit constant. |
139 | Info.setRequiresImmediate(Min: -32768, Max: 32767); |
140 | return true; |
141 | case 'q': |
142 | // A general-purpose register except for $r0 and $r1 (for the csrxchg |
143 | // instruction) |
144 | Info.setAllowsRegister(); |
145 | return true; |
146 | case 'I': |
147 | // A signed 12-bit constant (for arithmetic instructions). |
148 | Info.setRequiresImmediate(Min: -2048, Max: 2047); |
149 | return true; |
150 | case 'J': |
151 | // Integer zero. |
152 | Info.setRequiresImmediate(0); |
153 | return true; |
154 | case 'K': |
155 | // An unsigned 12-bit constant (for logic instructions). |
156 | Info.setRequiresImmediate(Min: 0, Max: 4095); |
157 | return true; |
158 | case 'Z': |
159 | // ZB: An address that is held in a general-purpose register. The offset is |
160 | // zero. |
161 | // ZC: A memory operand whose address is formed by a base register |
162 | // and offset that is suitable for use in instructions with the same |
163 | // addressing mode as ll.w and sc.w. |
164 | if (Name[1] == 'C' || Name[1] == 'B') { |
165 | Info.setAllowsMemory(); |
166 | ++Name; // Skip over 'Z'. |
167 | return true; |
168 | } |
169 | return false; |
170 | } |
171 | } |
172 | |
173 | std::string |
174 | LoongArchTargetInfo::convertConstraint(const char *&Constraint) const { |
175 | std::string R; |
176 | switch (*Constraint) { |
177 | case 'Z': |
178 | // "ZC"/"ZB" are two-character constraints; add "^" hint for later |
179 | // parsing. |
180 | R = "^"+ std::string(Constraint, 2); |
181 | ++Constraint; |
182 | break; |
183 | default: |
184 | R = TargetInfo::convertConstraint(Constraint); |
185 | break; |
186 | } |
187 | return R; |
188 | } |
189 | |
190 | void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, |
191 | MacroBuilder &Builder) const { |
192 | Builder.defineMacro(Name: "__loongarch__"); |
193 | unsigned GRLen = getRegisterWidth(); |
194 | Builder.defineMacro(Name: "__loongarch_grlen", Value: Twine(GRLen)); |
195 | if (GRLen == 64) |
196 | Builder.defineMacro(Name: "__loongarch64"); |
197 | |
198 | if (HasFeatureD) |
199 | Builder.defineMacro(Name: "__loongarch_frlen", Value: "64"); |
200 | else if (HasFeatureF) |
201 | Builder.defineMacro(Name: "__loongarch_frlen", Value: "32"); |
202 | else |
203 | Builder.defineMacro(Name: "__loongarch_frlen", Value: "0"); |
204 | |
205 | // Define __loongarch_arch. |
206 | StringRef ArchName = getCPU(); |
207 | if (ArchName == "loongarch64") { |
208 | if (HasFeatureLSX) { |
209 | // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1" |
210 | // arch feature set will be used to include all sub-features belonging to |
211 | // the V1.1 ISA version. |
212 | if (HasFeatureFrecipe && HasFeatureLAM_BH && HasFeatureLAMCAS && |
213 | HasFeatureLD_SEQ_SA && HasFeatureDiv32 && HasFeatureSCQ) |
214 | Builder.defineMacro(Name: "__loongarch_arch", |
215 | Value: Twine('"') + "la64v1.1"+ Twine('"')); |
216 | else |
217 | Builder.defineMacro(Name: "__loongarch_arch", |
218 | Value: Twine('"') + "la64v1.0"+ Twine('"')); |
219 | } else { |
220 | Builder.defineMacro(Name: "__loongarch_arch", |
221 | Value: Twine('"') + ArchName + Twine('"')); |
222 | } |
223 | } else { |
224 | Builder.defineMacro(Name: "__loongarch_arch", Value: Twine('"') + ArchName + Twine('"')); |
225 | } |
226 | |
227 | // Define __loongarch_tune. |
228 | StringRef TuneCPU = getTargetOpts().TuneCPU; |
229 | if (TuneCPU.empty()) |
230 | TuneCPU = ArchName; |
231 | Builder.defineMacro(Name: "__loongarch_tune", Value: Twine('"') + TuneCPU + Twine('"')); |
232 | |
233 | if (HasFeatureLASX) { |
234 | Builder.defineMacro(Name: "__loongarch_simd_width", Value: "256"); |
235 | Builder.defineMacro(Name: "__loongarch_sx", Value: Twine(1)); |
236 | Builder.defineMacro(Name: "__loongarch_asx", Value: Twine(1)); |
237 | } else if (HasFeatureLSX) { |
238 | Builder.defineMacro(Name: "__loongarch_simd_width", Value: "128"); |
239 | Builder.defineMacro(Name: "__loongarch_sx", Value: Twine(1)); |
240 | } |
241 | if (HasFeatureFrecipe) |
242 | Builder.defineMacro(Name: "__loongarch_frecipe", Value: Twine(1)); |
243 | |
244 | if (HasFeatureLAM_BH) |
245 | Builder.defineMacro(Name: "__loongarch_lam_bh", Value: Twine(1)); |
246 | |
247 | if (HasFeatureLAMCAS) |
248 | Builder.defineMacro(Name: "__loongarch_lamcas", Value: Twine(1)); |
249 | |
250 | if (HasFeatureLD_SEQ_SA) |
251 | Builder.defineMacro(Name: "__loongarch_ld_seq_sa", Value: Twine(1)); |
252 | |
253 | if (HasFeatureDiv32) |
254 | Builder.defineMacro(Name: "__loongarch_div32", Value: Twine(1)); |
255 | |
256 | if (HasFeatureSCQ) |
257 | Builder.defineMacro(Name: "__loongarch_scq", Value: Twine(1)); |
258 | |
259 | StringRef ABI = getABI(); |
260 | if (ABI == "lp64d"|| ABI == "lp64f"|| ABI == "lp64s") |
261 | Builder.defineMacro(Name: "__loongarch_lp64"); |
262 | |
263 | if (ABI == "lp64d"|| ABI == "ilp32d") { |
264 | Builder.defineMacro(Name: "__loongarch_hard_float"); |
265 | Builder.defineMacro(Name: "__loongarch_double_float"); |
266 | } else if (ABI == "lp64f"|| ABI == "ilp32f") { |
267 | Builder.defineMacro(Name: "__loongarch_hard_float"); |
268 | Builder.defineMacro(Name: "__loongarch_single_float"); |
269 | } else if (ABI == "lp64s"|| ABI == "ilp32s") { |
270 | Builder.defineMacro(Name: "__loongarch_soft_float"); |
271 | } |
272 | |
273 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
274 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
275 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
276 | if (GRLen == 64) |
277 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
278 | } |
279 | |
280 | static constexpr int NumBaseBuiltins = |
281 | LoongArch::FirstLSXBuiltin - Builtin::FirstTSBuiltin; |
282 | static constexpr int NumLSXBuiltins = |
283 | LoongArch::FirstLASXBuiltin - LoongArch::FirstLSXBuiltin; |
284 | static constexpr int NumLASXBuiltins = |
285 | LoongArch::LastTSBuiltin - LoongArch::FirstLASXBuiltin; |
286 | static constexpr int NumBuiltins = |
287 | LoongArch::LastTSBuiltin - Builtin::FirstTSBuiltin; |
288 | static_assert(NumBuiltins == |
289 | (NumBaseBuiltins + NumLSXBuiltins + NumLASXBuiltins)); |
290 | |
291 | static constexpr llvm::StringTable BuiltinBaseStrings = |
292 | CLANG_BUILTIN_STR_TABLE_START |
293 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE |
294 | #include "clang/Basic/BuiltinsLoongArchBase.def" |
295 | #undef TARGET_BUILTIN |
296 | ; |
297 | |
298 | static constexpr auto BuiltinBaseInfos = Builtin::MakeInfos<NumBaseBuiltins>(Infos: { |
299 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY |
300 | #include "clang/Basic/BuiltinsLoongArchBase.def" |
301 | #undef TARGET_BUILTIN |
302 | }); |
303 | |
304 | static constexpr llvm::StringTable BuiltinLSXStrings = |
305 | CLANG_BUILTIN_STR_TABLE_START |
306 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE |
307 | #include "clang/Basic/BuiltinsLoongArchLSX.def" |
308 | #undef TARGET_BUILTIN |
309 | ; |
310 | |
311 | static constexpr auto BuiltinLSXInfos = Builtin::MakeInfos<NumLSXBuiltins>(Infos: { |
312 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY |
313 | #include "clang/Basic/BuiltinsLoongArchLSX.def" |
314 | #undef TARGET_BUILTIN |
315 | }); |
316 | |
317 | static constexpr llvm::StringTable BuiltinLASXStrings = |
318 | CLANG_BUILTIN_STR_TABLE_START |
319 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE |
320 | #include "clang/Basic/BuiltinsLoongArchLASX.def" |
321 | #undef TARGET_BUILTIN |
322 | ; |
323 | |
324 | static constexpr auto BuiltinLASXInfos = Builtin::MakeInfos<NumLASXBuiltins>(Infos: { |
325 | #define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY |
326 | #include "clang/Basic/BuiltinsLoongArchLASX.def" |
327 | #undef TARGET_BUILTIN |
328 | }); |
329 | |
330 | bool LoongArchTargetInfo::initFeatureMap( |
331 | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
332 | const std::vector<std::string> &FeaturesVec) const { |
333 | if (getTriple().getArch() == llvm::Triple::loongarch64) |
334 | Features["64bit"] = true; |
335 | if (getTriple().getArch() == llvm::Triple::loongarch32) |
336 | Features["32bit"] = true; |
337 | |
338 | return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec: FeaturesVec); |
339 | } |
340 | |
341 | /// Return true if has this feature. |
342 | bool LoongArchTargetInfo::hasFeature(StringRef Feature) const { |
343 | bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64; |
344 | // TODO: Handle more features. |
345 | return llvm::StringSwitch<bool>(Feature) |
346 | .Case(S: "loongarch32", Value: !Is64Bit) |
347 | .Case(S: "loongarch64", Value: Is64Bit) |
348 | .Case(S: "32bit", Value: !Is64Bit) |
349 | .Case(S: "64bit", Value: Is64Bit) |
350 | .Case(S: "lsx", Value: HasFeatureLSX) |
351 | .Case(S: "lasx", Value: HasFeatureLASX) |
352 | .Default(Value: false); |
353 | } |
354 | |
355 | llvm::SmallVector<Builtin::InfosShard> |
356 | LoongArchTargetInfo::getTargetBuiltins() const { |
357 | return { |
358 | {&BuiltinBaseStrings, BuiltinBaseInfos}, |
359 | {&BuiltinLSXStrings, BuiltinLSXInfos}, |
360 | {&BuiltinLASXStrings, BuiltinLASXInfos}, |
361 | }; |
362 | } |
363 | |
364 | bool LoongArchTargetInfo::handleTargetFeatures( |
365 | std::vector<std::string> &Features, DiagnosticsEngine &Diags) { |
366 | for (const auto &Feature : Features) { |
367 | if (Feature == "+d"|| Feature == "+f") { |
368 | // "d" implies "f". |
369 | HasFeatureF = true; |
370 | if (Feature == "+d") { |
371 | HasFeatureD = true; |
372 | } |
373 | } else if (Feature == "+lsx") |
374 | HasFeatureLSX = true; |
375 | else if (Feature == "+lasx") |
376 | HasFeatureLASX = true; |
377 | else if (Feature == "-ual") |
378 | HasUnalignedAccess = false; |
379 | else if (Feature == "+frecipe") |
380 | HasFeatureFrecipe = true; |
381 | else if (Feature == "+lam-bh") |
382 | HasFeatureLAM_BH = true; |
383 | else if (Feature == "+lamcas") |
384 | HasFeatureLAMCAS = true; |
385 | else if (Feature == "+ld-seq-sa") |
386 | HasFeatureLD_SEQ_SA = true; |
387 | else if (Feature == "+div32") |
388 | HasFeatureDiv32 = true; |
389 | else if (Feature == "+scq") |
390 | HasFeatureSCQ = true; |
391 | } |
392 | return true; |
393 | } |
394 | |
395 | enum class AttrFeatureKind { Arch, Tune, NoFeature, Feature }; |
396 | |
397 | static std::pair<AttrFeatureKind, llvm::StringRef> |
398 | getAttrFeatureTypeAndValue(llvm::StringRef AttrFeature) { |
399 | if (auto Split = AttrFeature.split(Separator: "="); !Split.second.empty()) { |
400 | if (Split.first.trim() == "arch") |
401 | return {AttrFeatureKind::Arch, Split.second.trim()}; |
402 | if (Split.first.trim() == "tune") |
403 | return {AttrFeatureKind::Tune, Split.second.trim()}; |
404 | } |
405 | if (AttrFeature.starts_with(Prefix: "no-")) |
406 | return {AttrFeatureKind::NoFeature, AttrFeature.drop_front(N: 3)}; |
407 | return {AttrFeatureKind::Feature, AttrFeature}; |
408 | } |
409 | |
410 | ParsedTargetAttr |
411 | LoongArchTargetInfo::parseTargetAttr(StringRef Features) const { |
412 | ParsedTargetAttr Ret; |
413 | if (Features == "default") |
414 | return Ret; |
415 | SmallVector<StringRef, 1> AttrFeatures; |
416 | Features.split(A&: AttrFeatures, Separator: ","); |
417 | |
418 | for (auto &Feature : AttrFeatures) { |
419 | auto [Kind, Value] = getAttrFeatureTypeAndValue(AttrFeature: Feature.trim()); |
420 | |
421 | switch (Kind) { |
422 | case AttrFeatureKind::Arch: { |
423 | if (llvm::LoongArch::isValidArchName(Arch: Value) || Value == "la64v1.0"|| |
424 | Value == "la64v1.1") { |
425 | std::vector<llvm::StringRef> ArchFeatures; |
426 | if (llvm::LoongArch::getArchFeatures(Arch: Value, Features&: ArchFeatures)) { |
427 | Ret.Features.insert(position: Ret.Features.end(), first: ArchFeatures.begin(), |
428 | last: ArchFeatures.end()); |
429 | } |
430 | |
431 | if (!Ret.CPU.empty()) |
432 | Ret.Duplicate = "arch="; |
433 | else if (Value == "la64v1.0"|| Value == "la64v1.1") |
434 | Ret.CPU = "loongarch64"; |
435 | else |
436 | Ret.CPU = Value; |
437 | } else { |
438 | Ret.Features.push_back(x: "!arch="+ Value.str()); |
439 | } |
440 | break; |
441 | } |
442 | |
443 | case AttrFeatureKind::Tune: |
444 | if (!Ret.Tune.empty()) |
445 | Ret.Duplicate = "tune="; |
446 | else |
447 | Ret.Tune = Value; |
448 | break; |
449 | |
450 | case AttrFeatureKind::NoFeature: |
451 | Ret.Features.push_back(x: "-"+ Value.str()); |
452 | break; |
453 | |
454 | case AttrFeatureKind::Feature: |
455 | Ret.Features.push_back(x: "+"+ Value.str()); |
456 | break; |
457 | } |
458 | } |
459 | return Ret; |
460 | } |
461 | |
462 | bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const { |
463 | return llvm::LoongArch::isValidCPUName(TuneCPU: Name); |
464 | } |
465 | |
466 | void LoongArchTargetInfo::fillValidCPUList( |
467 | SmallVectorImpl<StringRef> &Values) const { |
468 | llvm::LoongArch::fillValidCPUList(Values); |
469 | } |
470 | |
471 | bool LoongArchTargetInfo::isValidFeatureName(StringRef Name) const { |
472 | return llvm::LoongArch::isValidFeatureName(Feature: Name); |
473 | } |
474 |
Definitions
- getGCCRegNames
- getGCCRegAliases
- validateAsmConstraint
- convertConstraint
- getTargetDefines
- NumBaseBuiltins
- NumLSXBuiltins
- NumLASXBuiltins
- NumBuiltins
- BuiltinBaseStrings
- BuiltinBaseInfos
- BuiltinLSXStrings
- BuiltinLSXInfos
- BuiltinLASXStrings
- BuiltinLASXInfos
- initFeatureMap
- hasFeature
- getTargetBuiltins
- handleTargetFeatures
- AttrFeatureKind
- getAttrFeatureTypeAndValue
- parseTargetAttr
- isValidCPUName
- fillValidCPUList
Learn to use CMake with our Intro Training
Find out more