clang  14.0.0git
RISCV.cpp
Go to the documentation of this file.
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/Diagnostic.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/TargetParser.h"
19 #include "llvm/Support/raw_ostream.h"
20 
21 using namespace clang;
22 using namespace clang::targets;
23 
25  static const char *const GCCRegNames[] = {
26  // Integer registers
27  "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
28  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
29  "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
30  "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
31 
32  // Floating point registers
33  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
34  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
35  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
36  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
37 
38  // Vector registers
39  "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
40  "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
41  "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
42  "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
43  return llvm::makeArrayRef(GCCRegNames);
44 }
45 
47  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
48  {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
49  {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
50  {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
51  {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"},
52  {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
53  {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
54  {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
55  {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"},
56  {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"},
57  {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"},
58  {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"},
59  {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"},
60  {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"},
61  {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"},
62  {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
63  {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
64  return llvm::makeArrayRef(GCCRegAliases);
65 }
66 
68  const char *&Name, TargetInfo::ConstraintInfo &Info) const {
69  switch (*Name) {
70  default:
71  return false;
72  case 'I':
73  // A 12-bit signed immediate.
74  Info.setRequiresImmediate(-2048, 2047);
75  return true;
76  case 'J':
77  // Integer zero.
78  Info.setRequiresImmediate(0);
79  return true;
80  case 'K':
81  // A 5-bit unsigned immediate for CSR access instructions.
82  Info.setRequiresImmediate(0, 31);
83  return true;
84  case 'f':
85  // A floating-point register.
86  Info.setAllowsRegister();
87  return true;
88  case 'A':
89  // An address that is held in a general-purpose register.
90  Info.setAllowsMemory();
91  return true;
92  case 'S': // A symbolic address
93  Info.setAllowsRegister();
94  return true;
95  case 'v':
96  // A vector register.
97  if (Name[1] == 'r' || Name[1] == 'm') {
98  Info.setAllowsRegister();
99  Name += 1;
100  return true;
101  }
102  return false;
103  }
104 }
105 
106 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
107  std::string R;
108  switch (*Constraint) {
109  case 'v':
110  R = std::string("^") + std::string(Constraint, 2);
111  Constraint += 1;
112  break;
113  default:
114  R = TargetInfo::convertConstraint(Constraint);
115  break;
116  }
117  return R;
118 }
119 
121  MacroBuilder &Builder) const {
122  Builder.defineMacro("__ELF__");
123  Builder.defineMacro("__riscv");
124  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
125  Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
126  StringRef CodeModel = getTargetOpts().CodeModel;
127  unsigned FLen = ISAInfo->getFLen();
128  if (CodeModel == "default")
129  CodeModel = "small";
130 
131  if (CodeModel == "small")
132  Builder.defineMacro("__riscv_cmodel_medlow");
133  else if (CodeModel == "medium")
134  Builder.defineMacro("__riscv_cmodel_medany");
135 
136  StringRef ABIName = getABI();
137  if (ABIName == "ilp32f" || ABIName == "lp64f")
138  Builder.defineMacro("__riscv_float_abi_single");
139  else if (ABIName == "ilp32d" || ABIName == "lp64d")
140  Builder.defineMacro("__riscv_float_abi_double");
141  else
142  Builder.defineMacro("__riscv_float_abi_soft");
143 
144  if (ABIName == "ilp32e")
145  Builder.defineMacro("__riscv_abi_rve");
146 
147  Builder.defineMacro("__riscv_arch_test");
148 
149  for (auto &Extension : ISAInfo->getExtensions()) {
150  auto ExtName = Extension.first;
151  auto ExtInfo = Extension.second;
152  unsigned Version =
153  (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
154 
155  Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
156  }
157 
158  if (ISAInfo->hasExtension("m")) {
159  Builder.defineMacro("__riscv_mul");
160  Builder.defineMacro("__riscv_div");
161  Builder.defineMacro("__riscv_muldiv");
162  }
163 
164  if (ISAInfo->hasExtension("a")) {
165  Builder.defineMacro("__riscv_atomic");
166  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
167  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
168  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
169  if (Is64Bit)
170  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
171  }
172 
173  if (FLen) {
174  Builder.defineMacro("__riscv_flen", Twine(FLen));
175  Builder.defineMacro("__riscv_fdiv");
176  Builder.defineMacro("__riscv_fsqrt");
177  }
178 
179  if (ISAInfo->hasExtension("c"))
180  Builder.defineMacro("__riscv_compressed");
181 
182  if (ISAInfo->hasExtension("v"))
183  Builder.defineMacro("__riscv_vector");
184 }
185 
187 #define BUILTIN(ID, TYPE, ATTRS) \
188  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
189 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
190  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
191 #include "clang/Basic/BuiltinsRISCVVector.def"
192 #define BUILTIN(ID, TYPE, ATTRS) \
193  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
194 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
195  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
196 #include "clang/Basic/BuiltinsRISCV.def"
197 };
198 
200  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
202 }
203 
205  llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
206  const std::vector<std::string> &FeaturesVec) const {
207 
208  if (getTriple().getArch() == llvm::Triple::riscv64)
209  Features["64bit"] = true;
210 
211  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
212 }
213 
214 /// Return true if has this feature, need to sync with handleTargetFeatures.
215 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
216  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
217  auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
218  .Case("riscv", true)
219  .Case("riscv32", !Is64Bit)
220  .Case("riscv64", Is64Bit)
221  .Case("64bit", Is64Bit)
222  .Default(None);
223  if (Result.hasValue())
224  return Result.getValue();
225 
226  if (ISAInfo->isSupportedExtensionFeature(Feature))
227  return ISAInfo->hasExtension(Feature);
228 
229  return false;
230 }
231 
232 /// Perform initialization based on the user configured set of features.
233 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
234  DiagnosticsEngine &Diags) {
235  unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
236  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
237  if (!ParseResult) {
238  std::string Buffer;
239  llvm::raw_string_ostream OutputErrMsg(Buffer);
240  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
241  OutputErrMsg << ErrMsg.getMessage();
242  });
243  Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
244  return false;
245  } else {
246  ISAInfo = std::move(*ParseResult);
247  }
248 
249  return true;
250 }
251 
252 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
253  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
254  /*Is64Bit=*/false);
255 }
256 
258  SmallVectorImpl<StringRef> &Values) const {
259  llvm::RISCV::fillValidCPUArchList(Values, false);
260 }
261 
262 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
263  return llvm::RISCV::checkTuneCPUKind(
264  llvm::RISCV::parseTuneCPUKind(Name, false),
265  /*Is64Bit=*/false);
266 }
267 
269  SmallVectorImpl<StringRef> &Values) const {
270  llvm::RISCV::fillValidTuneCPUArchList(Values, false);
271 }
272 
273 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
274  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
275  /*Is64Bit=*/true);
276 }
277 
279  SmallVectorImpl<StringRef> &Values) const {
280  llvm::RISCV::fillValidCPUArchList(Values, true);
281 }
282 
283 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
284  return llvm::RISCV::checkTuneCPUKind(
285  llvm::RISCV::parseTuneCPUKind(Name, true),
286  /*Is64Bit=*/true);
287 }
288 
290  SmallVectorImpl<StringRef> &Values) const {
291  llvm::RISCV::fillValidTuneCPUArchList(Values, true);
292 }
clang::targets::RISCVTargetInfo::BuiltinInfo
static const Builtin::Info BuiltinInfo[]
Definition: RISCV.h:30
clang::targets::RISCV64TargetInfo::fillValidTuneCPUList
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
Definition: RISCV.cpp:289
clang::targets::RISCV32TargetInfo::fillValidCPUList
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: RISCV.cpp:257
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::targets::RISCV32TargetInfo::isValidTuneCPUName
bool isValidTuneCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name for
Definition: RISCV.cpp:262
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
clang::targets::RISCV64TargetInfo::isValidTuneCPUName
bool isValidTuneCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name for
Definition: RISCV.cpp:283
clang::targets::RISCVTargetInfo::convertConstraint
std::string convertConstraint(const char *&Constraint) const override
Definition: RISCV.cpp:106
clang::targets::RISCVTargetInfo::initFeatureMap
bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeaturesVec) const override
Initialize the map with the default set of target features for the CPU this should include all legal ...
Definition: RISCV.cpp:204
clang::TargetInfo::ConstraintInfo::setAllowsRegister
void setAllowsRegister()
Definition: TargetInfo.h:1025
clang::targets::RISCVTargetInfo::handleTargetFeatures
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features.
Definition: RISCV.cpp:233
clang::RISCV::LastTSBuiltin
@ LastTSBuiltin
Definition: TargetBuiltins.h:144
clang::TargetInfo::ConstraintInfo::setAllowsMemory
void setAllowsMemory()
Definition: TargetInfo.h:1024
clang::TargetInfo::ConstraintInfo::setRequiresImmediate
void setRequiresImmediate(int Min, int Max)
Definition: TargetInfo.h:1027
clang::targets::RISCV32TargetInfo::isValidCPUName
bool isValidCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name.
Definition: RISCV.cpp:252
clang::targets::RISCVTargetInfo::getABI
StringRef getABI() const override
Get the ABI currently in use.
Definition: RISCV.h:53
clang::targets::RISCVTargetInfo::validateAsmConstraint
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
Definition: RISCV.cpp:67
Diagnostic.h
clang::TargetInfo::initFeatureMap
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
Definition: TargetInfo.cpp:461
MacroBuilder.h
clang::targets::RISCVTargetInfo::getGCCRegNames
ArrayRef< const char * > getGCCRegNames() const override
Definition: RISCV.cpp:24
clang::targets::GCCRegNames
static const char *const GCCRegNames[]
Definition: X86.cpp:43
clang::TargetInfo::GCCRegAlias
Definition: TargetInfo.h:1142
clang::TargetInfo::getTriple
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1130
clang::targets::RISCVTargetInfo::hasFeature
bool hasFeature(StringRef Feature) const override
Return true if has this feature, need to sync with handleTargetFeatures.
Definition: RISCV.cpp:215
clang::TargetInfo::getTargetOpts
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:258
llvm::ArrayRef< const char * >
TargetBuiltins.h
clang::targets::RISCVTargetInfo::ISAInfo
std::unique_ptr< llvm::RISCVISAInfo > ISAInfo
Definition: RISCV.h:29
clang::TargetInfo::ConstraintInfo
Definition: TargetInfo.h:960
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
clang::targets::RISCV64TargetInfo::isValidCPUName
bool isValidCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name.
Definition: RISCV.cpp:273
clang
Definition: CalledOnceCheck.h:17
clang::targets
Definition: AArch64.h:21
clang::Builtin::Info
Definition: Builtins.h:55
clang::targets::RISCVTargetInfo::CPU
std::string CPU
Definition: RISCV.h:28
RISCV.h
clang::TargetInfo::convertConstraint
virtual std::string convertConstraint(const char *&Constraint) const
Definition: TargetInfo.h:1107
clang::targets::RISCV64TargetInfo::fillValidCPUList
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: RISCV.cpp:278
clang::Builtin::FirstTSBuiltin
@ FirstTSBuiltin
Definition: Builtins.h:52
llvm::SmallVectorImpl
Definition: LLVM.h:39
clang::targets::RISCVTargetInfo::getGCCRegAliases
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition: RISCV.cpp:46
clang::MacroBuilder
Definition: MacroBuilder.h:23
clang::targets::RISCVTargetInfo::getTargetDefines
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
Definition: RISCV.cpp:120
clang::targets::RISCVTargetInfo::getTargetBuiltins
ArrayRef< Builtin::Info > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
Definition: RISCV.cpp:199
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1523
clang::targets::RISCV32TargetInfo::fillValidTuneCPUList
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
Definition: RISCV.cpp:268
clang::TargetOptions::CodeModel
std::string CodeModel
Definition: TargetOptions.h:85