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