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   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 (HasV)
140     Builder.defineMacro("__riscv_vector");
141 
142   if (HasZfh)
143     Builder.defineMacro("__riscv_zfh");
144 }
145 
146 /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const147 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
148   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
149   return llvm::StringSwitch<bool>(Feature)
150       .Case("riscv", true)
151       .Case("riscv32", !Is64Bit)
152       .Case("riscv64", Is64Bit)
153       .Case("m", HasM)
154       .Case("a", HasA)
155       .Case("f", HasF)
156       .Case("d", HasD)
157       .Case("c", HasC)
158       .Case("experimental-b", HasB)
159       .Case("experimental-v", HasV)
160       .Case("experimental-zfh", HasZfh)
161       .Default(false);
162 }
163 
164 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)165 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
166                                            DiagnosticsEngine &Diags) {
167   for (const auto &Feature : Features) {
168     if (Feature == "+m")
169       HasM = true;
170     else if (Feature == "+a")
171       HasA = true;
172     else if (Feature == "+f")
173       HasF = true;
174     else if (Feature == "+d")
175       HasD = true;
176     else if (Feature == "+c")
177       HasC = true;
178     else if (Feature == "+experimental-b")
179       HasB = true;
180     else if (Feature == "+experimental-v")
181       HasV = true;
182     else if (Feature == "+experimental-zfh")
183       HasZfh = true;
184   }
185 
186   return true;
187 }
188 
isValidCPUName(StringRef Name) const189 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
190   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
191                                    /*Is64Bit=*/false);
192 }
193 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const194 void RISCV32TargetInfo::fillValidCPUList(
195     SmallVectorImpl<StringRef> &Values) const {
196   llvm::RISCV::fillValidCPUArchList(Values, false);
197 }
198 
isValidTuneCPUName(StringRef Name) const199 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
200   return llvm::RISCV::checkTuneCPUKind(
201       llvm::RISCV::parseTuneCPUKind(Name, false),
202       /*Is64Bit=*/false);
203 }
204 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const205 void RISCV32TargetInfo::fillValidTuneCPUList(
206     SmallVectorImpl<StringRef> &Values) const {
207   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
208 }
209 
isValidCPUName(StringRef Name) const210 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
211   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
212                                    /*Is64Bit=*/true);
213 }
214 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const215 void RISCV64TargetInfo::fillValidCPUList(
216     SmallVectorImpl<StringRef> &Values) const {
217   llvm::RISCV::fillValidCPUArchList(Values, true);
218 }
219 
isValidTuneCPUName(StringRef Name) const220 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
221   return llvm::RISCV::checkTuneCPUKind(
222       llvm::RISCV::parseTuneCPUKind(Name, true),
223       /*Is64Bit=*/true);
224 }
225 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const226 void RISCV64TargetInfo::fillValidTuneCPUList(
227     SmallVectorImpl<StringRef> &Values) const {
228   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
229 }
230