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 
21 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 
37 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 
58 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 
86 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   if (HasM) {
113     Builder.defineMacro("__riscv_mul");
114     Builder.defineMacro("__riscv_div");
115     Builder.defineMacro("__riscv_muldiv");
116   }
117 
118   if (HasA) {
119     Builder.defineMacro("__riscv_atomic");
120     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
121     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
122     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
123     if (Is64Bit)
124       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
125   }
126 
127   if (HasF || HasD) {
128     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
129     Builder.defineMacro("__riscv_fdiv");
130     Builder.defineMacro("__riscv_fsqrt");
131   }
132 
133   if (HasC)
134     Builder.defineMacro("__riscv_compressed");
135 
136   if (HasB)
137     Builder.defineMacro("__riscv_bitmanip");
138 
139   if (HasZfh)
140     Builder.defineMacro("__riscv_zfh");
141 }
142 
143 /// Return true if has this feature, need to sync with handleTargetFeatures.
144 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
145   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
146   return llvm::StringSwitch<bool>(Feature)
147       .Case("riscv", true)
148       .Case("riscv32", !Is64Bit)
149       .Case("riscv64", Is64Bit)
150       .Case("m", HasM)
151       .Case("a", HasA)
152       .Case("f", HasF)
153       .Case("d", HasD)
154       .Case("c", HasC)
155       .Case("experimental-b", HasB)
156       .Case("experimental-zfh", HasZfh)
157       .Default(false);
158 }
159 
160 /// Perform initialization based on the user configured set of features.
161 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
162                                            DiagnosticsEngine &Diags) {
163   for (const auto &Feature : Features) {
164     if (Feature == "+m")
165       HasM = true;
166     else if (Feature == "+a")
167       HasA = true;
168     else if (Feature == "+f")
169       HasF = true;
170     else if (Feature == "+d")
171       HasD = true;
172     else if (Feature == "+c")
173       HasC = true;
174     else if (Feature == "+experimental-b")
175       HasB = true;
176     else if (Feature == "+experimental-zfh")
177       HasZfh = true;
178   }
179 
180   return true;
181 }
182 
183 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
184   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
185                                    /*Is64Bit=*/false);
186 }
187 
188 void RISCV32TargetInfo::fillValidCPUList(
189     SmallVectorImpl<StringRef> &Values) const {
190   llvm::RISCV::fillValidCPUArchList(Values, false);
191 }
192 
193 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
194   return llvm::RISCV::checkTuneCPUKind(
195       llvm::RISCV::parseTuneCPUKind(Name, false),
196       /*Is64Bit=*/false);
197 }
198 
199 void RISCV32TargetInfo::fillValidTuneCPUList(
200     SmallVectorImpl<StringRef> &Values) const {
201   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
202 }
203 
204 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
205   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
206                                    /*Is64Bit=*/true);
207 }
208 
209 void RISCV64TargetInfo::fillValidCPUList(
210     SmallVectorImpl<StringRef> &Values) const {
211   llvm::RISCV::fillValidCPUArchList(Values, true);
212 }
213 
214 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
215   return llvm::RISCV::checkTuneCPUKind(
216       llvm::RISCV::parseTuneCPUKind(Name, true),
217       /*Is64Bit=*/true);
218 }
219 
220 void RISCV64TargetInfo::fillValidTuneCPUList(
221     SmallVectorImpl<StringRef> &Values) const {
222   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
223 }
224