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 'S': // A symbolic address
91 Info.setAllowsRegister();
92 return true;
93 case 'v':
94 // A vector register.
95 if (Name[1] == 'r' || Name[1] == 'm') {
96 Info.setAllowsRegister();
97 Name += 1;
98 return true;
99 }
100 return false;
101 }
102 }
103
convertConstraint(const char * & Constraint) const104 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
105 std::string R;
106 switch (*Constraint) {
107 case 'v':
108 R = std::string("^") + std::string(Constraint, 2);
109 Constraint += 1;
110 break;
111 default:
112 R = TargetInfo::convertConstraint(Constraint);
113 break;
114 }
115 return R;
116 }
117
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const118 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
119 MacroBuilder &Builder) const {
120 Builder.defineMacro("__ELF__");
121 Builder.defineMacro("__riscv");
122 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
123 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
124 StringRef CodeModel = getTargetOpts().CodeModel;
125 if (CodeModel == "default")
126 CodeModel = "small";
127
128 if (CodeModel == "small")
129 Builder.defineMacro("__riscv_cmodel_medlow");
130 else if (CodeModel == "medium")
131 Builder.defineMacro("__riscv_cmodel_medany");
132
133 StringRef ABIName = getABI();
134 if (ABIName == "ilp32f" || ABIName == "lp64f")
135 Builder.defineMacro("__riscv_float_abi_single");
136 else if (ABIName == "ilp32d" || ABIName == "lp64d")
137 Builder.defineMacro("__riscv_float_abi_double");
138 else
139 Builder.defineMacro("__riscv_float_abi_soft");
140
141 if (ABIName == "ilp32e")
142 Builder.defineMacro("__riscv_abi_rve");
143
144 Builder.defineMacro("__riscv_arch_test");
145 Builder.defineMacro("__riscv_i", "2000000");
146
147 if (HasM) {
148 Builder.defineMacro("__riscv_m", "2000000");
149 Builder.defineMacro("__riscv_mul");
150 Builder.defineMacro("__riscv_div");
151 Builder.defineMacro("__riscv_muldiv");
152 }
153
154 if (HasA) {
155 Builder.defineMacro("__riscv_a", "2000000");
156 Builder.defineMacro("__riscv_atomic");
157 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
158 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
159 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
160 if (Is64Bit)
161 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
162 }
163
164 if (HasF || HasD) {
165 Builder.defineMacro("__riscv_f", "2000000");
166 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
167 Builder.defineMacro("__riscv_fdiv");
168 Builder.defineMacro("__riscv_fsqrt");
169 }
170
171 if (HasD)
172 Builder.defineMacro("__riscv_d", "2000000");
173
174 if (HasC) {
175 Builder.defineMacro("__riscv_c", "2000000");
176 Builder.defineMacro("__riscv_compressed");
177 }
178
179 if (HasV) {
180 Builder.defineMacro("__riscv_v", "10000");
181 Builder.defineMacro("__riscv_vector");
182 }
183
184 if (HasZba)
185 Builder.defineMacro("__riscv_zba", "93000");
186
187 if (HasZbb)
188 Builder.defineMacro("__riscv_zbb", "93000");
189
190 if (HasZbc)
191 Builder.defineMacro("__riscv_zbc", "93000");
192
193 if (HasZbe)
194 Builder.defineMacro("__riscv_zbe", "93000");
195
196 if (HasZbf)
197 Builder.defineMacro("__riscv_zbf", "93000");
198
199 if (HasZbm)
200 Builder.defineMacro("__riscv_zbm", "93000");
201
202 if (HasZbp)
203 Builder.defineMacro("__riscv_zbp", "93000");
204
205 if (HasZbr)
206 Builder.defineMacro("__riscv_zbr", "93000");
207
208 if (HasZbs)
209 Builder.defineMacro("__riscv_zbs", "93000");
210
211 if (HasZbt)
212 Builder.defineMacro("__riscv_zbt", "93000");
213
214 if (HasZfh)
215 Builder.defineMacro("__riscv_zfh", "1000");
216
217 if (HasZvamo)
218 Builder.defineMacro("__riscv_zvamo", "10000");
219
220 if (HasZvlsseg)
221 Builder.defineMacro("__riscv_zvlsseg", "10000");
222 }
223
224 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
225 #define BUILTIN(ID, TYPE, ATTRS) \
226 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
227 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
228 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
229 #include "clang/Basic/BuiltinsRISCV.def"
230 };
231
getTargetBuiltins() const232 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
233 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
234 Builtin::FirstTSBuiltin);
235 }
236
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const237 bool RISCVTargetInfo::initFeatureMap(
238 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
239 const std::vector<std::string> &FeaturesVec) const {
240
241 if (getTriple().getArch() == llvm::Triple::riscv64)
242 Features["64bit"] = true;
243
244 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
245 }
246
247 /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const248 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
249 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
250 return llvm::StringSwitch<bool>(Feature)
251 .Case("riscv", true)
252 .Case("riscv32", !Is64Bit)
253 .Case("riscv64", Is64Bit)
254 .Case("64bit", Is64Bit)
255 .Case("m", HasM)
256 .Case("a", HasA)
257 .Case("f", HasF)
258 .Case("d", HasD)
259 .Case("c", HasC)
260 .Case("experimental-v", HasV)
261 .Case("experimental-zba", HasZba)
262 .Case("experimental-zbb", HasZbb)
263 .Case("experimental-zbc", HasZbc)
264 .Case("experimental-zbe", HasZbe)
265 .Case("experimental-zbf", HasZbf)
266 .Case("experimental-zbm", HasZbm)
267 .Case("experimental-zbp", HasZbp)
268 .Case("experimental-zbr", HasZbr)
269 .Case("experimental-zbs", HasZbs)
270 .Case("experimental-zbt", HasZbt)
271 .Case("experimental-zfh", HasZfh)
272 .Case("experimental-zvamo", HasZvamo)
273 .Case("experimental-zvlsseg", HasZvlsseg)
274 .Default(false);
275 }
276
277 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)278 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
279 DiagnosticsEngine &Diags) {
280 for (const auto &Feature : Features) {
281 if (Feature == "+m")
282 HasM = true;
283 else if (Feature == "+a")
284 HasA = true;
285 else if (Feature == "+f")
286 HasF = true;
287 else if (Feature == "+d")
288 HasD = true;
289 else if (Feature == "+c")
290 HasC = true;
291 else if (Feature == "+experimental-v")
292 HasV = true;
293 else if (Feature == "+experimental-zba")
294 HasZba = true;
295 else if (Feature == "+experimental-zbb")
296 HasZbb = true;
297 else if (Feature == "+experimental-zbc")
298 HasZbc = true;
299 else if (Feature == "+experimental-zbe")
300 HasZbe = true;
301 else if (Feature == "+experimental-zbf")
302 HasZbf = true;
303 else if (Feature == "+experimental-zbm")
304 HasZbm = true;
305 else if (Feature == "+experimental-zbp")
306 HasZbp = true;
307 else if (Feature == "+experimental-zbr")
308 HasZbr = true;
309 else if (Feature == "+experimental-zbs")
310 HasZbs = true;
311 else if (Feature == "+experimental-zbt")
312 HasZbt = true;
313 else if (Feature == "+experimental-zfh")
314 HasZfh = true;
315 else if (Feature == "+experimental-zvamo")
316 HasZvamo = true;
317 else if (Feature == "+experimental-zvlsseg")
318 HasZvlsseg = true;
319 }
320
321 return true;
322 }
323
isValidCPUName(StringRef Name) const324 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
325 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
326 /*Is64Bit=*/false);
327 }
328
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const329 void RISCV32TargetInfo::fillValidCPUList(
330 SmallVectorImpl<StringRef> &Values) const {
331 llvm::RISCV::fillValidCPUArchList(Values, false);
332 }
333
isValidTuneCPUName(StringRef Name) const334 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
335 return llvm::RISCV::checkTuneCPUKind(
336 llvm::RISCV::parseTuneCPUKind(Name, false),
337 /*Is64Bit=*/false);
338 }
339
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const340 void RISCV32TargetInfo::fillValidTuneCPUList(
341 SmallVectorImpl<StringRef> &Values) const {
342 llvm::RISCV::fillValidTuneCPUArchList(Values, false);
343 }
344
isValidCPUName(StringRef Name) const345 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
346 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
347 /*Is64Bit=*/true);
348 }
349
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const350 void RISCV64TargetInfo::fillValidCPUList(
351 SmallVectorImpl<StringRef> &Values) const {
352 llvm::RISCV::fillValidCPUArchList(Values, true);
353 }
354
isValidTuneCPUName(StringRef Name) const355 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
356 return llvm::RISCV::checkTuneCPUKind(
357 llvm::RISCV::parseTuneCPUKind(Name, true),
358 /*Is64Bit=*/true);
359 }
360
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const361 void RISCV64TargetInfo::fillValidTuneCPUList(
362 SmallVectorImpl<StringRef> &Values) const {
363 llvm::RISCV::fillValidTuneCPUArchList(Values, true);
364 }
365