clang  16.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") || ISAInfo->hasExtension("zmmul"))
162  Builder.defineMacro("__riscv_mul");
163 
164  if (ISAInfo->hasExtension("m")) {
165  Builder.defineMacro("__riscv_div");
166  Builder.defineMacro("__riscv_muldiv");
167  }
168 
169  if (ISAInfo->hasExtension("a")) {
170  Builder.defineMacro("__riscv_atomic");
171  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
172  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
173  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
174  if (Is64Bit)
175  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
176  }
177 
178  if (FLen) {
179  Builder.defineMacro("__riscv_flen", Twine(FLen));
180  Builder.defineMacro("__riscv_fdiv");
181  Builder.defineMacro("__riscv_fsqrt");
182  }
183 
184  if (MinVLen) {
185  Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
186  Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
187  Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
188  }
189 
190  if (ISAInfo->hasExtension("c"))
191  Builder.defineMacro("__riscv_compressed");
192 
193  if (ISAInfo->hasExtension("zve32x"))
194  Builder.defineMacro("__riscv_vector");
195 }
196 
198 #define BUILTIN(ID, TYPE, ATTRS) \
199  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
200 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
201  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
202 #include "clang/Basic/BuiltinsRISCVVector.def"
203 #define BUILTIN(ID, TYPE, ATTRS) \
204  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
205 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
206  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
207 #include "clang/Basic/BuiltinsRISCV.def"
208 };
209 
211  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
213 }
214 
216  llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
217  const std::vector<std::string> &FeaturesVec) const {
218 
219  unsigned XLen = 32;
220 
221  if (getTriple().getArch() == llvm::Triple::riscv64) {
222  Features["64bit"] = true;
223  XLen = 64;
224  } else {
225  Features["32bit"] = true;
226  }
227 
228  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
229  if (!ParseResult) {
230  std::string Buffer;
231  llvm::raw_string_ostream OutputErrMsg(Buffer);
232  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
233  OutputErrMsg << ErrMsg.getMessage();
234  });
235  Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
236  return false;
237  }
238 
239  // RISCVISAInfo makes implications for ISA features
240  std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
241  // Add non-ISA features like `relax` and `save-restore` back
242  for (const std::string &Feature : FeaturesVec)
243  if (!llvm::is_contained(ImpliedFeatures, Feature))
244  ImpliedFeatures.push_back(Feature);
245 
246  return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
247 }
248 
251  if (LangOpts.VScaleMin || LangOpts.VScaleMax)
252  return std::pair<unsigned, unsigned>(
253  LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax);
254 
255  if (unsigned MinVLen = ISAInfo->getMinVLen();
256  MinVLen >= llvm::RISCV::RVVBitsPerBlock) {
257  unsigned MaxVLen = ISAInfo->getMaxVLen();
258  // RISCV::RVVBitsPerBlock is 64.
259  return std::make_pair(MinVLen / llvm::RISCV::RVVBitsPerBlock,
260  MaxVLen / llvm::RISCV::RVVBitsPerBlock);
261  }
262 
263  return None;
264 }
265 
266 /// Return true if has this feature, need to sync with handleTargetFeatures.
267 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
268  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
269  auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
270  .Case("riscv", true)
271  .Case("riscv32", !Is64Bit)
272  .Case("riscv64", Is64Bit)
273  .Case("32bit", !Is64Bit)
274  .Case("64bit", Is64Bit)
275  .Default(None);
276  if (Result)
277  return Result.value();
278 
279  if (ISAInfo->isSupportedExtensionFeature(Feature))
280  return ISAInfo->hasExtension(Feature);
281 
282  return false;
283 }
284 
285 /// Perform initialization based on the user configured set of features.
286 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
287  DiagnosticsEngine &Diags) {
288  unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
289  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
290  if (!ParseResult) {
291  std::string Buffer;
292  llvm::raw_string_ostream OutputErrMsg(Buffer);
293  handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
294  OutputErrMsg << ErrMsg.getMessage();
295  });
296  Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
297  return false;
298  } else {
299  ISAInfo = std::move(*ParseResult);
300  }
301 
302  if (ABI.empty())
303  ABI = ISAInfo->computeDefaultABI().str();
304 
305  return true;
306 }
307 
308 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
309  bool Is64Bit = getTriple().isArch64Bit();
310  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), Is64Bit);
311 }
312 
314  SmallVectorImpl<StringRef> &Values) const {
315  bool Is64Bit = getTriple().isArch64Bit();
316  llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
317 }
318 
319 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
320  bool Is64Bit = getTriple().isArch64Bit();
321  return llvm::RISCV::checkTuneCPUKind(
322  llvm::RISCV::parseTuneCPUKind(Name, Is64Bit), Is64Bit);
323 }
324 
326  SmallVectorImpl<StringRef> &Values) const {
327  bool Is64Bit = getTriple().isArch64Bit();
328  llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
329 }
clang::targets::RISCVTargetInfo::BuiltinInfo
static const Builtin::Info BuiltinInfo[]
Definition: RISCV.h:30
clang::targets::RISCVTargetInfo::fillValidCPUList
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition: RISCV.cpp:313
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::targets::RISCVTargetInfo::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::getVScaleRange
Optional< std::pair< unsigned, unsigned > > getVScaleRange(const LangOptions &LangOpts) const override
Returns target-specific min and max values VScale_Range.
Definition: RISCV.cpp:250
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
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:215
llvm::Optional
Definition: LLVM.h:40
clang::TargetInfo::ConstraintInfo::setAllowsRegister
void setAllowsRegister()
Definition: TargetInfo.h:1090
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:286
clang::TargetInfo::ConstraintInfo::setAllowsMemory
void setAllowsMemory()
Definition: TargetInfo.h:1089
clang::TargetInfo::ConstraintInfo::setRequiresImmediate
void setRequiresImmediate(int Min, int Max)
Definition: TargetInfo.h:1092
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:494
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::targets::RISCVTargetInfo::isValidCPUName
bool isValidCPUName(StringRef Name) const override
brief Determine whether this TargetInfo supports the given CPU name.
Definition: RISCV.cpp:308
clang::TargetInfo::GCCRegAlias
Definition: TargetInfo.h:1207
clang::TargetInfo::getTriple
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1195
clang::targets::RISCVTargetInfo::hasFeature
bool hasFeature(StringRef Feature) const override
Return true if has this feature, need to sync with handleTargetFeatures.
Definition: RISCV.cpp:267
clang::TargetInfo::getTargetOpts
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:282
clang::targets::RISCVTargetInfo::fillValidTuneCPUList
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
Definition: RISCV.cpp:325
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:1026
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:81
clang
Definition: CalledOnceCheck.h:17
clang::targets
Definition: AArch64.h:21
clang::Builtin::Info
Definition: Builtins.h:59
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:1172
clang::Builtin::FirstTSBuiltin
@ FirstTSBuiltin
Definition: Builtins.h:56
clang::RISCV::LastTSBuiltin
@ LastTSBuiltin
Definition: TargetBuiltins.h:150
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:210
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1537
clang::TargetOptions::CodeModel
std::string CodeModel
Definition: TargetOptions.h:97