clang 17.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/TargetParser.h"
18#include "llvm/Support/raw_ostream.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"};
36}
37
40 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
41 {{"$zero"}, "$r0"}, {{"$ra"}, "$r1"}, {{"$tp"}, "$r2"},
42 {{"$sp"}, "$r3"}, {{"$a0"}, "$r4"}, {{"$a1"}, "$r5"},
43 {{"$a2"}, "$r6"}, {{"$a3"}, "$r7"}, {{"$a4"}, "$r8"},
44 {{"$a5"}, "$r9"}, {{"$a6"}, "$r10"}, {{"$a7"}, "$r11"},
45 {{"$t0"}, "$r12"}, {{"$t1"}, "$r13"}, {{"$t2"}, "$r14"},
46 {{"$t3"}, "$r15"}, {{"$t4"}, "$r16"}, {{"$t5"}, "$r17"},
47 {{"$t6"}, "$r18"}, {{"$t7"}, "$r19"}, {{"$t8"}, "$r20"},
48 {{"$fp", "$s9"}, "$r22"}, {{"$s0"}, "$r23"}, {{"$s1"}, "$r24"},
49 {{"$s2"}, "$r25"}, {{"$s3"}, "$r26"}, {{"$s4"}, "$r27"},
50 {{"$s5"}, "$r28"}, {{"$s6"}, "$r29"}, {{"$s7"}, "$r30"},
51 {{"$s8"}, "$r31"}, {{"$fa0"}, "$f0"}, {{"$fa1"}, "$f1"},
52 {{"$fa2"}, "$f2"}, {{"$fa3"}, "$f3"}, {{"$fa4"}, "$f4"},
53 {{"$fa5"}, "$f5"}, {{"$fa6"}, "$f6"}, {{"$fa7"}, "$f7"},
54 {{"$ft0"}, "$f8"}, {{"$ft1"}, "$f9"}, {{"$ft2"}, "$f10"},
55 {{"$ft3"}, "$f11"}, {{"$ft4"}, "$f12"}, {{"$ft5"}, "$f13"},
56 {{"$ft6"}, "$f14"}, {{"$ft7"}, "$f15"}, {{"$ft8"}, "$f16"},
57 {{"$ft9"}, "$f17"}, {{"$ft10"}, "$f18"}, {{"$ft11"}, "$f19"},
58 {{"$ft12"}, "$f20"}, {{"$ft13"}, "$f21"}, {{"$ft14"}, "$f22"},
59 {{"$ft15"}, "$f23"}, {{"$fs0"}, "$f24"}, {{"$fs1"}, "$f25"},
60 {{"$fs2"}, "$f26"}, {{"$fs3"}, "$f27"}, {{"$fs4"}, "$f28"},
61 {{"$fs5"}, "$f29"}, {{"$fs6"}, "$f30"}, {{"$fs7"}, "$f31"},
62 };
63 return llvm::ArrayRef(GCCRegAliases);
64}
65
67 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
68 // See the GCC definitions here:
69 // https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html
70 // Note that the 'm' constraint is handled in TargetInfo.
71 switch (*Name) {
72 default:
73 return false;
74 case 'f':
75 // A floating-point register (if available).
76 Info.setAllowsRegister();
77 return true;
78 case 'k':
79 // A memory operand whose address is formed by a base register and
80 // (optionally scaled) index register.
81 Info.setAllowsMemory();
82 return true;
83 case 'l':
84 // A signed 16-bit constant.
85 Info.setRequiresImmediate(-32768, 32767);
86 return true;
87 case 'I':
88 // A signed 12-bit constant (for arithmetic instructions).
89 Info.setRequiresImmediate(-2048, 2047);
90 return true;
91 case 'J':
92 // Integer zero.
94 return true;
95 case 'K':
96 // An unsigned 12-bit constant (for logic instructions).
97 Info.setRequiresImmediate(0, 4095);
98 return true;
99 case 'Z':
100 // ZB: An address that is held in a general-purpose register. The offset is
101 // zero.
102 // ZC: A memory operand whose address is formed by a base register
103 // and offset that is suitable for use in instructions with the same
104 // addressing mode as ll.w and sc.w.
105 if (Name[1] == 'C' || Name[1] == 'B') {
106 Info.setAllowsMemory();
107 ++Name; // Skip over 'Z'.
108 return true;
109 }
110 return false;
111 }
112}
113
114std::string
115LoongArchTargetInfo::convertConstraint(const char *&Constraint) const {
116 std::string R;
117 switch (*Constraint) {
118 case 'Z':
119 // "ZC"/"ZB" are two-character constraints; add "^" hint for later
120 // parsing.
121 R = "^" + std::string(Constraint, 2);
122 ++Constraint;
123 break;
124 default:
125 R = TargetInfo::convertConstraint(Constraint);
126 break;
127 }
128 return R;
129}
130
132 MacroBuilder &Builder) const {
133 Builder.defineMacro("__loongarch__");
134 unsigned GRLen = getRegisterWidth();
135 Builder.defineMacro("__loongarch_grlen", Twine(GRLen));
136 if (GRLen == 64)
137 Builder.defineMacro("__loongarch64");
138
139 if (HasFeatureD)
140 Builder.defineMacro("__loongarch_frlen", "64");
141 else if (HasFeatureF)
142 Builder.defineMacro("__loongarch_frlen", "32");
143 else
144 Builder.defineMacro("__loongarch_frlen", "0");
145
146 // TODO: define __loongarch_arch and __loongarch_tune.
147
148 StringRef ABI = getABI();
149 if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s")
150 Builder.defineMacro("__loongarch_lp64");
151
152 if (ABI == "lp64d" || ABI == "ilp32d") {
153 Builder.defineMacro("__loongarch_hard_float");
154 Builder.defineMacro("__loongarch_double_float");
155 } else if (ABI == "lp64f" || ABI == "ilp32f") {
156 Builder.defineMacro("__loongarch_hard_float");
157 Builder.defineMacro("__loongarch_single_float");
158 } else if (ABI == "lp64s" || ABI == "ilp32s") {
159 Builder.defineMacro("__loongarch_soft_float");
160 }
161
162 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
163 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
164 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
165 if (GRLen == 64)
166 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
167}
168
169static constexpr Builtin::Info BuiltinInfo[] = {
170#define BUILTIN(ID, TYPE, ATTRS) \
171 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
172#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
173 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
174#include "clang/Basic/BuiltinsLoongArch.def"
175};
176
178 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
179 const std::vector<std::string> &FeaturesVec) const {
180 if (getTriple().getArch() == llvm::Triple::loongarch64)
181 Features["64bit"] = true;
182 if (getTriple().getArch() == llvm::Triple::loongarch32)
183 Features["32bit"] = true;
184
185 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
186}
187
188/// Return true if has this feature.
189bool LoongArchTargetInfo::hasFeature(StringRef Feature) const {
190 bool Is64Bit = getTriple().getArch() == llvm::Triple::loongarch64;
191 // TODO: Handle more features.
192 return llvm::StringSwitch<bool>(Feature)
193 .Case("loongarch32", !Is64Bit)
194 .Case("loongarch64", Is64Bit)
195 .Case("32bit", !Is64Bit)
196 .Case("64bit", Is64Bit)
197 .Default(false);
198}
199
203}
204
206 std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
207 for (const auto &Feature : Features) {
208 if (Feature == "+d" || Feature == "+f") {
209 // "d" implies "f".
210 HasFeatureF = true;
211 if (Feature == "+d") {
212 HasFeatureD = true;
213 }
214 }
215 }
216 return true;
217}
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:82
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1195
virtual unsigned getRegisterWidth() const
Return the "preferred" register width on this target.
Definition: TargetInfo.h:830
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:519
virtual std::string convertConstraint(const char *&Constraint) const
Definition: TargetInfo.h:1172
StringRef getABI() const override
Get the ABI currently in use.
Definition: LoongArch.h:43
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
Definition: LoongArch.cpp:131
ArrayRef< Builtin::Info > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
Definition: LoongArch.cpp:200
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
Definition: LoongArch.cpp:66
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:189
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:205
std::string convertConstraint(const char *&Constraint) const override
Definition: LoongArch.cpp:115
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:177
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition: LoongArch.cpp:39
static const char *const GCCRegNames[]
Definition: X86.cpp:44
void setRequiresImmediate(int Min, int Max)
Definition: TargetInfo.h:1092