1 //===--- RISCV.cpp - Implement RISCV 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 RISCV TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "RISCV.h"
14 #include "clang/Basic/MacroBuilder.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/Support/TargetParser.h"
17
18 using namespace clang;
19 using namespace clang::targets;
20
getGCCRegNames() const21 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
22 static const char *const GCCRegNames[] = {
23 // Integer registers
24 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
25 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
26 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
27 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
28
29 // Floating point registers
30 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
31 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
32 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
33 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
34 return llvm::makeArrayRef(GCCRegNames);
35 }
36
getGCCRegAliases() const37 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
38 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
39 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
40 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
41 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
42 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"},
43 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
44 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
45 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
46 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"},
47 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"},
48 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"},
49 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"},
50 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"},
51 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"},
52 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"},
53 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
54 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
55 return llvm::makeArrayRef(GCCRegAliases);
56 }
57
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const58 bool RISCVTargetInfo::validateAsmConstraint(
59 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
60 switch (*Name) {
61 default:
62 return false;
63 case 'I':
64 // A 12-bit signed immediate.
65 Info.setRequiresImmediate(-2048, 2047);
66 return true;
67 case 'J':
68 // Integer zero.
69 Info.setRequiresImmediate(0);
70 return true;
71 case 'K':
72 // A 5-bit unsigned immediate for CSR access instructions.
73 Info.setRequiresImmediate(0, 31);
74 return true;
75 case 'f':
76 // A floating-point register.
77 Info.setAllowsRegister();
78 return true;
79 case 'A':
80 // An address that is held in a general-purpose register.
81 Info.setAllowsMemory();
82 return true;
83 }
84 }
85
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const86 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
87 MacroBuilder &Builder) const {
88 Builder.defineMacro("__ELF__");
89 Builder.defineMacro("__riscv");
90 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
91 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
92 StringRef CodeModel = getTargetOpts().CodeModel;
93 if (CodeModel == "default")
94 CodeModel = "small";
95
96 if (CodeModel == "small")
97 Builder.defineMacro("__riscv_cmodel_medlow");
98 else if (CodeModel == "medium")
99 Builder.defineMacro("__riscv_cmodel_medany");
100
101 StringRef ABIName = getABI();
102 if (ABIName == "ilp32f" || ABIName == "lp64f")
103 Builder.defineMacro("__riscv_float_abi_single");
104 else if (ABIName == "ilp32d" || ABIName == "lp64d")
105 Builder.defineMacro("__riscv_float_abi_double");
106 else
107 Builder.defineMacro("__riscv_float_abi_soft");
108
109 if (ABIName == "ilp32e")
110 Builder.defineMacro("__riscv_abi_rve");
111
112 Builder.defineMacro("__riscv_arch_test");
113 Builder.defineMacro("__riscv_i", "2000000");
114
115 if (HasM) {
116 Builder.defineMacro("__riscv_m", "2000000");
117 Builder.defineMacro("__riscv_mul");
118 Builder.defineMacro("__riscv_div");
119 Builder.defineMacro("__riscv_muldiv");
120 }
121
122 if (HasA) {
123 Builder.defineMacro("__riscv_a", "2000000");
124 Builder.defineMacro("__riscv_atomic");
125 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
126 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
127 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
128 if (Is64Bit)
129 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
130 }
131
132 if (HasF || HasD) {
133 Builder.defineMacro("__riscv_f", "2000000");
134 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
135 Builder.defineMacro("__riscv_fdiv");
136 Builder.defineMacro("__riscv_fsqrt");
137 }
138
139 if (HasD)
140 Builder.defineMacro("__riscv_d", "2000000");
141
142 if (HasC) {
143 Builder.defineMacro("__riscv_c", "2000000");
144 Builder.defineMacro("__riscv_compressed");
145 }
146
147 if (HasB) {
148 Builder.defineMacro("__riscv_b", "93000");
149 Builder.defineMacro("__riscv_bitmanip");
150 }
151
152 if (HasV) {
153 Builder.defineMacro("__riscv_v", "10000");
154 Builder.defineMacro("__riscv_vector");
155 }
156
157 if (HasZba)
158 Builder.defineMacro("__riscv_zba", "93000");
159
160 if (HasZbb)
161 Builder.defineMacro("__riscv_zbb", "93000");
162
163 if (HasZbc)
164 Builder.defineMacro("__riscv_zbc", "93000");
165
166 if (HasZbe)
167 Builder.defineMacro("__riscv_zbe", "93000");
168
169 if (HasZbf)
170 Builder.defineMacro("__riscv_zbf", "93000");
171
172 if (HasZbm)
173 Builder.defineMacro("__riscv_zbm", "93000");
174
175 if (HasZbp)
176 Builder.defineMacro("__riscv_zbp", "93000");
177
178 if (HasZbproposedc)
179 Builder.defineMacro("__riscv_zbproposedc", "93000");
180
181 if (HasZbr)
182 Builder.defineMacro("__riscv_zbr", "93000");
183
184 if (HasZbs)
185 Builder.defineMacro("__riscv_zbs", "93000");
186
187 if (HasZbt)
188 Builder.defineMacro("__riscv_zbt", "93000");
189
190 if (HasZfh)
191 Builder.defineMacro("__riscv_zfh", "1000");
192
193 if (HasZvamo)
194 Builder.defineMacro("__riscv_zvamo", "10000");
195
196 if (HasZvlsseg)
197 Builder.defineMacro("__riscv_zvlsseg", "10000");
198 }
199
200 /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const201 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
202 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
203 return llvm::StringSwitch<bool>(Feature)
204 .Case("riscv", true)
205 .Case("riscv32", !Is64Bit)
206 .Case("riscv64", Is64Bit)
207 .Case("m", HasM)
208 .Case("a", HasA)
209 .Case("f", HasF)
210 .Case("d", HasD)
211 .Case("c", HasC)
212 .Case("experimental-b", HasB)
213 .Case("experimental-v", HasV)
214 .Case("experimental-zba", HasZba)
215 .Case("experimental-zbb", HasZbb)
216 .Case("experimental-zbc", HasZbc)
217 .Case("experimental-zbe", HasZbe)
218 .Case("experimental-zbf", HasZbf)
219 .Case("experimental-zbm", HasZbm)
220 .Case("experimental-zbp", HasZbp)
221 .Case("experimental-zbproposedc", HasZbproposedc)
222 .Case("experimental-zbr", HasZbr)
223 .Case("experimental-zbs", HasZbs)
224 .Case("experimental-zbt", HasZbt)
225 .Case("experimental-zfh", HasZfh)
226 .Case("experimental-zvamo", HasZvamo)
227 .Case("experimental-zvlsseg", HasZvlsseg)
228 .Default(false);
229 }
230
231 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)232 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
233 DiagnosticsEngine &Diags) {
234 for (const auto &Feature : Features) {
235 if (Feature == "+m")
236 HasM = true;
237 else if (Feature == "+a")
238 HasA = true;
239 else if (Feature == "+f")
240 HasF = true;
241 else if (Feature == "+d")
242 HasD = true;
243 else if (Feature == "+c")
244 HasC = true;
245 else if (Feature == "+experimental-b")
246 HasB = true;
247 else if (Feature == "+experimental-v")
248 HasV = true;
249 else if (Feature == "+experimental-zba")
250 HasZba = true;
251 else if (Feature == "+experimental-zbb")
252 HasZbb = true;
253 else if (Feature == "+experimental-zbc")
254 HasZbc = true;
255 else if (Feature == "+experimental-zbe")
256 HasZbe = true;
257 else if (Feature == "+experimental-zbf")
258 HasZbf = true;
259 else if (Feature == "+experimental-zbm")
260 HasZbm = true;
261 else if (Feature == "+experimental-zbp")
262 HasZbp = true;
263 else if (Feature == "+experimental-zbproposedc")
264 HasZbproposedc = true;
265 else if (Feature == "+experimental-zbr")
266 HasZbr = true;
267 else if (Feature == "+experimental-zbs")
268 HasZbs = true;
269 else if (Feature == "+experimental-zbt")
270 HasZbt = true;
271 else if (Feature == "+experimental-zfh")
272 HasZfh = true;
273 else if (Feature == "+experimental-zvamo")
274 HasZvamo = true;
275 else if (Feature == "+experimental-zvlsseg")
276 HasZvlsseg = true;
277 }
278
279 return true;
280 }
281
isValidCPUName(StringRef Name) const282 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
283 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
284 /*Is64Bit=*/false);
285 }
286
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const287 void RISCV32TargetInfo::fillValidCPUList(
288 SmallVectorImpl<StringRef> &Values) const {
289 llvm::RISCV::fillValidCPUArchList(Values, false);
290 }
291
isValidTuneCPUName(StringRef Name) const292 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
293 return llvm::RISCV::checkTuneCPUKind(
294 llvm::RISCV::parseTuneCPUKind(Name, false),
295 /*Is64Bit=*/false);
296 }
297
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const298 void RISCV32TargetInfo::fillValidTuneCPUList(
299 SmallVectorImpl<StringRef> &Values) const {
300 llvm::RISCV::fillValidTuneCPUArchList(Values, false);
301 }
302
isValidCPUName(StringRef Name) const303 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
304 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
305 /*Is64Bit=*/true);
306 }
307
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const308 void RISCV64TargetInfo::fillValidCPUList(
309 SmallVectorImpl<StringRef> &Values) const {
310 llvm::RISCV::fillValidCPUArchList(Values, true);
311 }
312
isValidTuneCPUName(StringRef Name) const313 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
314 return llvm::RISCV::checkTuneCPUKind(
315 llvm::RISCV::parseTuneCPUKind(Name, true),
316 /*Is64Bit=*/true);
317 }
318
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const319 void RISCV64TargetInfo::fillValidTuneCPUList(
320 SmallVectorImpl<StringRef> &Values) const {
321 llvm::RISCV::fillValidTuneCPUArchList(Values, true);
322 }
323