clang  15.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  unsigned MinVLen = ISAInfo->getMinVLen();
129  unsigned MaxELen = ISAInfo->getMaxELen();
130  unsigned MaxELenFp = ISAInfo->getMaxELenFp();
131  if (CodeModel == "default")
132  CodeModel = "small";
133 
134  if (CodeModel == "small")
135  Builder.defineMacro("__riscv_cmodel_medlow");
136  else if (CodeModel == "medium")
137  Builder.defineMacro("__riscv_cmodel_medany");
138 
139  StringRef ABIName = getABI();
140  if (ABIName == "ilp32f" || ABIName == "lp64f")
141  Builder.defineMacro("__riscv_float_abi_single");
142  else if (ABIName == "ilp32d" || ABIName == "lp64d")
143  Builder.defineMacro("__riscv_float_abi_double");
144  else
145  Builder.defineMacro("__riscv_float_abi_soft");
146 
147  if (ABIName == "ilp32e")
148  Builder.defineMacro("__riscv_abi_rve");
149 
150  Builder.defineMacro("__riscv_arch_test");
151 
152  for (auto &Extension : ISAInfo->getExtensions()) {
153  auto ExtName = Extension.first;
154  auto ExtInfo = Extension.second;
155  unsigned Version =
156  (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
157 
158  Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
159  }
160 
161  if (ISAInfo->hasExtension("m")) {
162  Builder.defineMacro("__riscv_mul");
163  Builder.defineMacro("__riscv_div");
164  Builder.defineMacro("__riscv_muldiv");
165  }
166 
167  if (ISAInfo->hasExtension("a")) {
168  Builder.defineMacro("__riscv_atomic");
169  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
170  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
171  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
172  if (Is64Bit)
173  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
174  }
175 
176  if (FLen) {
177  Builder.defineMacro("__riscv_flen", Twine(FLen));
178  Builder.defineMacro("__riscv_fdiv");
179  Builder.defineMacro("__riscv_fsqrt");
180  }
181 
182  if (MinVLen) {
183  Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
184  Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
185  Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
186  }
187 
188  if (ISAInfo->hasExtension("c"))
189  Builder.defineMacro("__riscv_compressed");
190 
191  if (ISAInfo->hasExtension("zve32x"))
192  Builder.defineMacro("__riscv_vector");
193 }
194 
196 #define BUILTIN(ID, TYPE, ATTRS) \
197  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
198 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
199  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
200 #include "clang/Basic/BuiltinsRISCVVector.def"
201 #define BUILTIN(ID, TYPE, ATTRS) \
202  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
203 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
204  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
205 #include "clang/Basic/BuiltinsRISCV.def"
206 };
207 
209  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
211 }
212 
214  llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
215  const std::vector<std::string> &FeaturesVec) const {
216 
217  unsigned XLen = 32;
218 
219  if (getTriple().getArch() == llvm::Triple::riscv64) {
220  Features["64bit"] = true;
221  XLen = 64;
222  }
223 
224  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
225  if (!ParseResult) {
226  std::string Buffer;
227  llvm::raw_string_ostream OutputErrMsg(Buffer);
228  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
229  OutputErrMsg << ErrMsg.getMessage();
230  });
231  Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
232  return false;
233  }
234 
235  // RISCVISAInfo makes implications for ISA features
236  std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
237  // Add non-ISA features like `relax` and `save-restore` back
238  for (std::string Feature : FeaturesVec) {
239  if (std::find(begin(ImpliedFeatures), end(ImpliedFeatures), Feature) ==
240  end(ImpliedFeatures))
241  ImpliedFeatures.push_back(Feature);
242  }
243 
244  return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
245 }
246 
247 /// Return true if has this feature, need to sync with handleTargetFeatures.
248 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
249  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
250  auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
251  .Case("riscv", true)
252  .Case("riscv32", !Is64Bit)
253  .Case("riscv64", Is64Bit)
254  .Case("64bit", Is64Bit)
255  .Default(None);
256  if (Result.hasValue())
257  return Result.getValue();
258 
259  if (ISAInfo->isSupportedExtensionFeature(Feature))
260  return ISAInfo->hasExtension(Feature);
261 
262  return false;
263 }
264 
265 /// Perform initialization based on the user configured set of features.
266 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
267  DiagnosticsEngine &Diags) {
268  unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
269  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
270  if (!ParseResult) {
271  std::string Buffer;
272  llvm::raw_string_ostream OutputErrMsg(Buffer);
273  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
274  OutputErrMsg << ErrMsg.getMessage();
275  });
276  Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
277  return false;
278  } else {
279  ISAInfo = std::move(*ParseResult);
280  }
281 
282  if (ABI.empty())
283  ABI = ISAInfo->computeDefaultABI().str();
284 
285  return true;
286 }
287 
288 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
289  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
290  /*Is64Bit=*/false);
291 }
292 
294  SmallVectorImpl<StringRef> &Values) const {
295  llvm::RISCV::fillValidCPUArchList(Values, false);
296 }
297 
298 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
299  return llvm::RISCV::checkTuneCPUKind(
300  llvm::RISCV::parseTuneCPUKind(Name, false),
301  /*Is64Bit=*/false);
302 }
303 
305  SmallVectorImpl<StringRef> &Values) const {
306  llvm::RISCV::fillValidTuneCPUArchList(Values, false);
307 }
308 
309 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
310  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
311  /*Is64Bit=*/true);
312 }
313 
315  SmallVectorImpl<StringRef> &Values) const {
316  llvm::RISCV::fillValidCPUArchList(Values, true);
317 }
318 
319 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
320  return llvm::RISCV::checkTuneCPUKind(
321  llvm::RISCV::parseTuneCPUKind(Name, true),
322  /*Is64Bit=*/true);
323 }
324 
326  SmallVectorImpl<StringRef> &Values) const {
327  llvm::RISCV::fillValidTuneCPUArchList(Values, true);
328 }
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:325
clang::targets::RISCV32TargetInfo::fillValidCPUList
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: RISCV.cpp:293
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:298
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
clang::targets::RISCV64TargetInfo::isValidTuneCPUName
bool isValidTuneCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name for
Definition: RISCV.cpp:319
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:213
clang::TargetInfo::ConstraintInfo::setAllowsRegister
void setAllowsRegister()
Definition: TargetInfo.h:1055
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:266
clang::TargetInfo::ConstraintInfo::setAllowsMemory
void setAllowsMemory()
Definition: TargetInfo.h:1054
clang::TargetInfo::ConstraintInfo::setRequiresImmediate
void setRequiresImmediate(int Min, int Max)
Definition: TargetInfo.h:1057
clang::targets::RISCV32TargetInfo::isValidCPUName
bool isValidCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name.
Definition: RISCV.cpp:288
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:483
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:1172
clang::TargetInfo::getTriple
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1160
clang::targets::RISCVTargetInfo::hasFeature
bool hasFeature(StringRef Feature) const override
Return true if has this feature, need to sync with handleTargetFeatures.
Definition: RISCV.cpp:248
clang::TargetInfo::getTargetOpts
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:260
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:991
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:78
clang::targets::RISCV64TargetInfo::isValidCPUName
bool isValidCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name.
Definition: RISCV.cpp:309
clang
Definition: CalledOnceCheck.h:17
clang::targets
Definition: AArch64.h:22
clang::Builtin::Info
Definition: Builtins.h:58
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:1137
clang::targets::RISCV64TargetInfo::fillValidCPUList
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: RISCV.cpp:314
clang::Builtin::FirstTSBuiltin
@ FirstTSBuiltin
Definition: Builtins.h:55
clang::RISCV::LastTSBuiltin
@ LastTSBuiltin
Definition: TargetBuiltins.h:149
llvm::SmallVectorImpl
Definition: Randstruct.h:18
clang::targets::RISCVTargetInfo::getGCCRegAliases
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition: RISCV.cpp:46
clang::MacroBuilder
Definition: MacroBuilder.h:23
clang::targets::RISCVTargetInfo::ABI
std::string ABI
Definition: RISCV.h:28
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:208
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1536
clang::targets::RISCV32TargetInfo::fillValidTuneCPUList
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
Definition: RISCV.cpp:304
clang::TargetOptions::CodeModel
std::string CodeModel
Definition: TargetOptions.h:97