clang  9.0.0
RISCV.cpp
Go to the documentation of this file.
1 //===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
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 #include "RISCV.h"
10 #include "clang/Basic/CharInfo.h"
11 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/Options.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/Support/TargetParser.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "ToolChains/CommonArgs.h"
18 
19 using namespace clang::driver;
20 using namespace clang::driver::tools;
21 using namespace clang;
22 using namespace llvm::opt;
23 
24 static StringRef getExtensionTypeDesc(StringRef Ext) {
25  if (Ext.startswith("sx"))
26  return "non-standard supervisor-level extension";
27  if (Ext.startswith("s"))
28  return "standard supervisor-level extension";
29  if (Ext.startswith("x"))
30  return "non-standard user-level extension";
31  return StringRef();
32 }
33 
34 static StringRef getExtensionType(StringRef Ext) {
35  if (Ext.startswith("sx"))
36  return "sx";
37  if (Ext.startswith("s"))
38  return "s";
39  if (Ext.startswith("x"))
40  return "x";
41  return StringRef();
42 }
43 
44 static bool isSupportedExtension(StringRef Ext) {
45  // LLVM does not support "sx", "s" nor "x" extensions.
46  return false;
47 }
48 
49 // Extensions may have a version number, and may be separated by
50 // an underscore '_' e.g.: rv32i2_m2.
51 // Version number is divided into major and minor version numbers,
52 // separated by a 'p'. If the minor version is 0 then 'p0' can be
53 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
54 static bool getExtensionVersion(const Driver &D, StringRef MArch,
55  StringRef Ext, StringRef In,
56  std::string &Major, std::string &Minor) {
57  Major = In.take_while(isDigit);
58  In = In.substr(Major.size());
59  if (Major.empty())
60  return true;
61 
62  if (In.consume_front("p")) {
63  Minor = In.take_while(isDigit);
64  In = In.substr(Major.size());
65 
66  // Expected 'p' to be followed by minor version number.
67  if (Minor.empty()) {
68  std::string Error =
69  "minor version number missing after 'p' for extension";
70  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
71  << MArch << Error << Ext;
72  return false;
73  }
74  }
75 
76  // TODO: Handle extensions with version number.
77  std::string Error = "unsupported version number " + Major;
78  if (!Minor.empty())
79  Error += "." + Minor;
80  Error += " for extension";
81  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
82 
83  return false;
84 }
85 
86 // Handle other types of extensions other than the standard
87 // general purpose and standard user-level extensions.
88 // Parse the ISA string containing non-standard user-level
89 // extensions, standard supervisor-level extensions and
90 // non-standard supervisor-level extensions.
91 // These extensions start with 'x', 's', 'sx' prefixes, follow a
92 // canonical order, might have a version number (major, minor)
93 // and are separated by a single underscore '_'.
94 // Set the hardware features for the extensions that are supported.
95 static void getExtensionFeatures(const Driver &D,
96  const ArgList &Args,
97  std::vector<StringRef> &Features,
98  StringRef &MArch, StringRef &Exts) {
99  if (Exts.empty())
100  return;
101 
102  // Multi-letter extensions are seperated by a single underscore
103  // as described in RISC-V User-Level ISA V2.2.
105  Exts.split(Split, StringRef("_"));
106 
107  SmallVector<StringRef, 3> Prefix{"x", "s", "sx"};
108  auto I = Prefix.begin();
109  auto E = Prefix.end();
110 
112 
113  for (StringRef Ext : Split) {
114  if (Ext.empty()) {
115  D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
116  << "extension name missing after separator '_'";
117  return;
118  }
119 
120  StringRef Type = getExtensionType(Ext);
121  StringRef Name(Ext.substr(Type.size()));
122  StringRef Desc = getExtensionTypeDesc(Ext);
123 
124  if (Type.empty()) {
125  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
126  << MArch << "invalid extension prefix" << Ext;
127  return;
128  }
129 
130  // Check ISA extensions are specified in the canonical order.
131  while (I != E && *I != Type)
132  ++I;
133 
134  if (I == E) {
135  std::string Error = Desc;
136  Error += " not given in canonical order";
137  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
138  << MArch << Error << Ext;
139  return;
140  }
141 
142  // The order is OK, do not advance I to the next prefix
143  // to allow repeated extension type, e.g.: rv32ixabc_xdef.
144 
145  if (Name.empty()) {
146  std::string Error = Desc;
147  Error += " name missing after";
148  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
149  << MArch << Error << Ext;
150  return;
151  }
152 
153  std::string Major, Minor;
154  auto Pos = Name.find_if(isDigit);
155  if (Pos != StringRef::npos) {
156  auto Next = Name.substr(Pos);
157  Name = Name.substr(0, Pos);
158  if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
159  return;
160  }
161 
162  // Check if duplicated extension.
163  if (llvm::is_contained(AllExts, Ext)) {
164  std::string Error = "duplicated ";
165  Error += Desc;
166  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
167  << MArch << Error << Ext;
168  return;
169  }
170 
171  // Extension format is correct, keep parsing the extensions.
172  // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
173  AllExts.push_back(Ext);
174  }
175 
176  // Set target features.
177  // TODO: Hardware features to be handled in Support/TargetParser.cpp.
178  // TODO: Use version number when setting target features.
179  for (auto Ext : AllExts) {
180  if (!isSupportedExtension(Ext)) {
181  StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
182  std::string Error = "unsupported ";
183  Error += Desc;
184  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
185  << MArch << Error << Ext;
186  return;
187  }
188  Features.push_back(Args.MakeArgString("+" + Ext));
189  }
190 }
191 
192 void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
193  std::vector<StringRef> &Features) {
194  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
195  StringRef MArch = A->getValue();
196 
197  // RISC-V ISA strings must be lowercase.
198  if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
199  D.Diag(diag::err_drv_invalid_riscv_arch_name)
200  << MArch << "string must be lowercase";
201  return;
202  }
203 
204  // ISA string must begin with rv32 or rv64.
205  if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
206  (MArch.size() < 5)) {
207  D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
208  << "string must begin with rv32{i,e,g} or rv64{i,g}";
209  return;
210  }
211 
212  bool HasRV64 = MArch.startswith("rv64");
213 
214  // The canonical order specified in ISA manual.
215  // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
216  StringRef StdExts = "mafdqlcbjtpvn";
217  bool HasF = false, HasD = false;
218  char Baseline = MArch[4];
219 
220  // First letter should be 'e', 'i' or 'g'.
221  switch (Baseline) {
222  default:
223  D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
224  << "first letter should be 'e', 'i' or 'g'";
225  return;
226  case 'e': {
227  StringRef Error;
228  // Currently LLVM does not support 'e'.
229  // Extension 'e' is not allowed in rv64.
230  if (HasRV64)
231  Error = "standard user-level extension 'e' requires 'rv32'";
232  else
233  Error = "unsupported standard user-level extension 'e'";
234  D.Diag(diag::err_drv_invalid_riscv_arch_name)
235  << MArch << Error;
236  return;
237  }
238  case 'i':
239  break;
240  case 'g':
241  // g = imafd
242  StdExts = StdExts.drop_front(4);
243  Features.push_back("+m");
244  Features.push_back("+a");
245  Features.push_back("+f");
246  Features.push_back("+d");
247  HasF = true;
248  HasD = true;
249  break;
250  }
251 
252  // Skip rvxxx
253  StringRef Exts = MArch.substr(5);
254 
255  // Remove non-standard extensions and supervisor-level extensions.
256  // They have 'x', 's', 'sx' prefixes. Parse them at the end.
257  // Find the very first occurrence of 's' or 'x'.
258  StringRef OtherExts;
259  size_t Pos = Exts.find_first_of("sx");
260  if (Pos != StringRef::npos) {
261  OtherExts = Exts.substr(Pos);
262  Exts = Exts.substr(0, Pos);
263  }
264 
265  std::string Major, Minor;
266  if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
267  Exts, Major, Minor))
268  return;
269 
270  // TODO: Use version number when setting target features
271  // and consume the underscore '_' that might follow.
272 
273  auto StdExtsItr = StdExts.begin();
274  auto StdExtsEnd = StdExts.end();
275 
276  for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
277  char c = *I;
278 
279  // Check ISA extensions are specified in the canonical order.
280  while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
281  ++StdExtsItr;
282 
283  if (StdExtsItr == StdExtsEnd) {
284  // Either c contains a valid extension but it was not given in
285  // canonical order or it is an invalid extension.
286  StringRef Error;
287  if (StdExts.contains(c))
288  Error = "standard user-level extension not given in canonical order";
289  else
290  Error = "invalid standard user-level extension";
291  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
292  << MArch << Error << std::string(1, c);
293  return;
294  }
295 
296  // Move to next char to prevent repeated letter.
297  ++StdExtsItr;
298 
299  if (std::next(I) != E) {
300  // Skip c.
301  std::string Next = std::string(std::next(I), E);
302  std::string Major, Minor;
303  if (!getExtensionVersion(D, MArch, std::string(1, c),
304  Next, Major, Minor))
305  return;
306 
307  // TODO: Use version number when setting target features
308  // and consume the underscore '_' that might follow.
309  }
310 
311  // The order is OK, then push it into features.
312  switch (c) {
313  default:
314  // Currently LLVM supports only "mafdc".
315  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
316  << MArch << "unsupported standard user-level extension"
317  << std::string(1, c);
318  return;
319  case 'm':
320  Features.push_back("+m");
321  break;
322  case 'a':
323  Features.push_back("+a");
324  break;
325  case 'f':
326  Features.push_back("+f");
327  HasF = true;
328  break;
329  case 'd':
330  Features.push_back("+d");
331  HasD = true;
332  break;
333  case 'c':
334  Features.push_back("+c");
335  break;
336  }
337  }
338 
339  // Dependency check.
340  // It's illegal to specify the 'd' (double-precision floating point)
341  // extension without also specifying the 'f' (single precision
342  // floating-point) extension.
343  if (HasD && !HasF)
344  D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
345  << "d requires f extension to also be specified";
346 
347  // Additional dependency checks.
348  // TODO: The 'q' extension requires rv64.
349  // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
350 
351  // Handle all other types of extensions.
352  getExtensionFeatures(D, Args, Features, MArch, OtherExts);
353  }
354 
355  // -mrelax is default, unless -mno-relax is specified.
356  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
357  Features.push_back("+relax");
358  else
359  Features.push_back("-relax");
360 
361  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
362  // specified...
363  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) {
364  // ... but we don't support -msave-restore, so issue a warning.
365  D.Diag(diag::warn_drv_clang_unsupported)
366  << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args);
367  }
368 
369  // Now add any that the user explicitly requested on the command line,
370  // which may override the defaults.
371  handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
372 }
373 
374 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
375  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
376  return A->getValue();
377 
378  return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";
379 }
void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, std::vector< StringRef > &Features, llvm::opt::OptSpecifier Group)
void getRISCVTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector< llvm::StringRef > &Features)
The base class of the type hierarchy.
Definition: Type.h:1433
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:108
static void getExtensionFeatures(const Driver &D, const ArgList &Args, std::vector< StringRef > &Features, StringRef &MArch, StringRef &Exts)
Definition: RISCV.cpp:95
static bool getExtensionVersion(const Driver &D, StringRef MArch, StringRef Ext, StringRef In, std::string &Major, std::string &Minor)
Definition: RISCV.cpp:54
c
Definition: emmintrin.h:306
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:57
StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
static StringRef getExtensionTypeDesc(StringRef Ext)
Definition: RISCV.cpp:24
Dataflow Directional Tag Classes.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
Definition: CharInfo.h:93
static StringRef getExtensionType(StringRef Ext)
Definition: RISCV.cpp:34
static bool isSupportedExtension(StringRef Ext)
Definition: RISCV.cpp:44