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