clang  10.0.0git
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/ADT/Optional.h"
16 #include "llvm/Support/TargetParser.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "ToolChains/CommonArgs.h"
19 
20 using namespace clang::driver;
21 using namespace clang::driver::tools;
22 using namespace clang;
23 using namespace llvm::opt;
24 
25 static StringRef getExtensionTypeDesc(StringRef Ext) {
26  if (Ext.startswith("sx"))
27  return "non-standard supervisor-level extension";
28  if (Ext.startswith("s"))
29  return "standard supervisor-level extension";
30  if (Ext.startswith("x"))
31  return "non-standard user-level extension";
32  return StringRef();
33 }
34 
35 static StringRef getExtensionType(StringRef Ext) {
36  if (Ext.startswith("sx"))
37  return "sx";
38  if (Ext.startswith("s"))
39  return "s";
40  if (Ext.startswith("x"))
41  return "x";
42  return StringRef();
43 }
44 
45 static bool isSupportedExtension(StringRef Ext) {
46  // LLVM does not support "sx", "s" nor "x" extensions.
47  return false;
48 }
49 
50 // Extensions may have a version number, and may be separated by
51 // an underscore '_' e.g.: rv32i2_m2.
52 // Version number is divided into major and minor version numbers,
53 // separated by a 'p'. If the minor version is 0 then 'p0' can be
54 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
55 static bool getExtensionVersion(const Driver &D, StringRef MArch,
56  StringRef Ext, StringRef In,
57  std::string &Major, std::string &Minor) {
58  Major = In.take_while(isDigit);
59  In = In.substr(Major.size());
60  if (Major.empty())
61  return true;
62 
63  if (In.consume_front("p")) {
64  Minor = In.take_while(isDigit);
65  In = In.substr(Major.size());
66 
67  // Expected 'p' to be followed by minor version number.
68  if (Minor.empty()) {
69  std::string Error =
70  "minor version number missing after 'p' for extension";
71  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
72  << MArch << Error << Ext;
73  return false;
74  }
75  }
76 
77  // TODO: Handle extensions with version number.
78  std::string Error = "unsupported version number " + Major;
79  if (!Minor.empty())
80  Error += "." + Minor;
81  Error += " for extension";
82  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
83 
84  return false;
85 }
86 
87 // Handle other types of extensions other than the standard
88 // general purpose and standard user-level extensions.
89 // Parse the ISA string containing non-standard user-level
90 // extensions, standard supervisor-level extensions and
91 // non-standard supervisor-level extensions.
92 // These extensions start with 'x', 's', 'sx' prefixes, follow a
93 // canonical order, might have a version number (major, minor)
94 // and are separated by a single underscore '_'.
95 // Set the hardware features for the extensions that are supported.
96 static void getExtensionFeatures(const Driver &D,
97  const ArgList &Args,
98  std::vector<StringRef> &Features,
99  StringRef &MArch, StringRef &Exts) {
100  if (Exts.empty())
101  return;
102 
103  // Multi-letter extensions are seperated by a single underscore
104  // as described in RISC-V User-Level ISA V2.2.
106  Exts.split(Split, StringRef("_"));
107 
108  SmallVector<StringRef, 3> Prefix{"x", "s", "sx"};
109  auto I = Prefix.begin();
110  auto E = Prefix.end();
111 
113 
114  for (StringRef Ext : Split) {
115  if (Ext.empty()) {
116  D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
117  << "extension name missing after separator '_'";
118  return;
119  }
120 
121  StringRef Type = getExtensionType(Ext);
122  StringRef Name(Ext.substr(Type.size()));
123  StringRef Desc = getExtensionTypeDesc(Ext);
124 
125  if (Type.empty()) {
126  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
127  << MArch << "invalid extension prefix" << Ext;
128  return;
129  }
130 
131  // Check ISA extensions are specified in the canonical order.
132  while (I != E && *I != Type)
133  ++I;
134 
135  if (I == E) {
136  std::string Error = Desc;
137  Error += " not given in canonical order";
138  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
139  << MArch << Error << Ext;
140  return;
141  }
142 
143  // The order is OK, do not advance I to the next prefix
144  // to allow repeated extension type, e.g.: rv32ixabc_xdef.
145 
146  if (Name.empty()) {
147  std::string Error = Desc;
148  Error += " name missing after";
149  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
150  << MArch << Error << Ext;
151  return;
152  }
153 
154  std::string Major, Minor;
155  auto Pos = Name.find_if(isDigit);
156  if (Pos != StringRef::npos) {
157  auto Next = Name.substr(Pos);
158  Name = Name.substr(0, Pos);
159  if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
160  return;
161  }
162 
163  // Check if duplicated extension.
164  if (llvm::is_contained(AllExts, Ext)) {
165  std::string Error = "duplicated ";
166  Error += Desc;
167  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
168  << MArch << Error << Ext;
169  return;
170  }
171 
172  // Extension format is correct, keep parsing the extensions.
173  // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
174  AllExts.push_back(Ext);
175  }
176 
177  // Set target features.
178  // TODO: Hardware features to be handled in Support/TargetParser.cpp.
179  // TODO: Use version number when setting target features.
180  for (auto Ext : AllExts) {
181  if (!isSupportedExtension(Ext)) {
182  StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
183  std::string Error = "unsupported ";
184  Error += Desc;
185  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
186  << MArch << Error << Ext;
187  return;
188  }
189  Features.push_back(Args.MakeArgString("+" + Ext));
190  }
191 }
192 
193 // Returns false if an error is diagnosed.
194 static bool getArchFeatures(const Driver &D, StringRef MArch,
195  std::vector<StringRef> &Features,
196  const ArgList &Args) {
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 false;
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)
208  << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
209  return false;
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)
224  << MArch << "first letter should be 'e', 'i' or 'g'";
225  return false;
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) << MArch << Error;
235  return false;
236  }
237  case 'i':
238  break;
239  case 'g':
240  // g = imafd
241  StdExts = StdExts.drop_front(4);
242  Features.push_back("+m");
243  Features.push_back("+a");
244  Features.push_back("+f");
245  Features.push_back("+d");
246  HasF = true;
247  HasD = true;
248  break;
249  }
250 
251  // Skip rvxxx
252  StringRef Exts = MArch.substr(5);
253 
254  // Remove non-standard extensions and supervisor-level extensions.
255  // They have 'x', 's', 'sx' prefixes. Parse them at the end.
256  // Find the very first occurrence of 's' or 'x'.
257  StringRef OtherExts;
258  size_t Pos = Exts.find_first_of("sx");
259  if (Pos != StringRef::npos) {
260  OtherExts = Exts.substr(Pos);
261  Exts = Exts.substr(0, Pos);
262  }
263 
264  std::string Major, Minor;
265  if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major,
266  Minor))
267  return false;
268 
269  // TODO: Use version number when setting target features
270  // and consume the underscore '_' that might follow.
271 
272  auto StdExtsItr = StdExts.begin();
273  auto StdExtsEnd = StdExts.end();
274 
275  for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
276  char c = *I;
277 
278  // Check ISA extensions are specified in the canonical order.
279  while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
280  ++StdExtsItr;
281 
282  if (StdExtsItr == StdExtsEnd) {
283  // Either c contains a valid extension but it was not given in
284  // canonical order or it is an invalid extension.
285  StringRef Error;
286  if (StdExts.contains(c))
287  Error = "standard user-level extension not given in canonical order";
288  else
289  Error = "invalid standard user-level extension";
290  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
291  << MArch << Error << std::string(1, c);
292  return false;
293  }
294 
295  // Move to next char to prevent repeated letter.
296  ++StdExtsItr;
297 
298  if (std::next(I) != E) {
299  // Skip c.
300  std::string Next = std::string(std::next(I), E);
301  std::string Major, Minor;
302  if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor))
303  return false;
304 
305  // TODO: Use version number when setting target features
306  // and consume the underscore '_' that might follow.
307  }
308 
309  // The order is OK, then push it into features.
310  switch (c) {
311  default:
312  // Currently LLVM supports only "mafdc".
313  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
314  << MArch << "unsupported standard user-level extension"
315  << std::string(1, c);
316  return false;
317  case 'm':
318  Features.push_back("+m");
319  break;
320  case 'a':
321  Features.push_back("+a");
322  break;
323  case 'f':
324  Features.push_back("+f");
325  HasF = true;
326  break;
327  case 'd':
328  Features.push_back("+d");
329  HasD = true;
330  break;
331  case 'c':
332  Features.push_back("+c");
333  break;
334  }
335  }
336 
337  // Dependency check.
338  // It's illegal to specify the 'd' (double-precision floating point)
339  // extension without also specifying the 'f' (single precision
340  // floating-point) extension.
341  if (HasD && !HasF) {
342  D.Diag(diag::err_drv_invalid_riscv_arch_name)
343  << MArch << "d requires f extension to also be specified";
344  return false;
345  }
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  return true;
355 }
356 
357 void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
358  const ArgList &Args,
359  std::vector<StringRef> &Features) {
360  StringRef MArch = getRISCVArch(Args, Triple);
361 
362  if (!getArchFeatures(D, MArch, Features, Args))
363  return;
364 
365  // Handle features corresponding to "-ffixed-X" options
366  if (Args.hasArg(options::OPT_ffixed_x1))
367  Features.push_back("+reserve-x1");
368  if (Args.hasArg(options::OPT_ffixed_x2))
369  Features.push_back("+reserve-x2");
370  if (Args.hasArg(options::OPT_ffixed_x3))
371  Features.push_back("+reserve-x3");
372  if (Args.hasArg(options::OPT_ffixed_x4))
373  Features.push_back("+reserve-x4");
374  if (Args.hasArg(options::OPT_ffixed_x5))
375  Features.push_back("+reserve-x5");
376  if (Args.hasArg(options::OPT_ffixed_x6))
377  Features.push_back("+reserve-x6");
378  if (Args.hasArg(options::OPT_ffixed_x7))
379  Features.push_back("+reserve-x7");
380  if (Args.hasArg(options::OPT_ffixed_x8))
381  Features.push_back("+reserve-x8");
382  if (Args.hasArg(options::OPT_ffixed_x9))
383  Features.push_back("+reserve-x9");
384  if (Args.hasArg(options::OPT_ffixed_x10))
385  Features.push_back("+reserve-x10");
386  if (Args.hasArg(options::OPT_ffixed_x11))
387  Features.push_back("+reserve-x11");
388  if (Args.hasArg(options::OPT_ffixed_x12))
389  Features.push_back("+reserve-x12");
390  if (Args.hasArg(options::OPT_ffixed_x13))
391  Features.push_back("+reserve-x13");
392  if (Args.hasArg(options::OPT_ffixed_x14))
393  Features.push_back("+reserve-x14");
394  if (Args.hasArg(options::OPT_ffixed_x15))
395  Features.push_back("+reserve-x15");
396  if (Args.hasArg(options::OPT_ffixed_x16))
397  Features.push_back("+reserve-x16");
398  if (Args.hasArg(options::OPT_ffixed_x17))
399  Features.push_back("+reserve-x17");
400  if (Args.hasArg(options::OPT_ffixed_x18))
401  Features.push_back("+reserve-x18");
402  if (Args.hasArg(options::OPT_ffixed_x19))
403  Features.push_back("+reserve-x19");
404  if (Args.hasArg(options::OPT_ffixed_x20))
405  Features.push_back("+reserve-x20");
406  if (Args.hasArg(options::OPT_ffixed_x21))
407  Features.push_back("+reserve-x21");
408  if (Args.hasArg(options::OPT_ffixed_x22))
409  Features.push_back("+reserve-x22");
410  if (Args.hasArg(options::OPT_ffixed_x23))
411  Features.push_back("+reserve-x23");
412  if (Args.hasArg(options::OPT_ffixed_x24))
413  Features.push_back("+reserve-x24");
414  if (Args.hasArg(options::OPT_ffixed_x25))
415  Features.push_back("+reserve-x25");
416  if (Args.hasArg(options::OPT_ffixed_x26))
417  Features.push_back("+reserve-x26");
418  if (Args.hasArg(options::OPT_ffixed_x27))
419  Features.push_back("+reserve-x27");
420  if (Args.hasArg(options::OPT_ffixed_x28))
421  Features.push_back("+reserve-x28");
422  if (Args.hasArg(options::OPT_ffixed_x29))
423  Features.push_back("+reserve-x29");
424  if (Args.hasArg(options::OPT_ffixed_x30))
425  Features.push_back("+reserve-x30");
426  if (Args.hasArg(options::OPT_ffixed_x31))
427  Features.push_back("+reserve-x31");
428 
429  // -mrelax is default, unless -mno-relax is specified.
430  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
431  Features.push_back("+relax");
432  else
433  Features.push_back("-relax");
434 
435  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
436  // specified...
437  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) {
438  // ... but we don't support -msave-restore, so issue a warning.
439  D.Diag(diag::warn_drv_clang_unsupported)
440  << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args);
441  }
442 
443  // Now add any that the user explicitly requested on the command line,
444  // which may override the defaults.
445  handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
446 }
447 
448 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
449  assert((Triple.getArch() == llvm::Triple::riscv32 ||
450  Triple.getArch() == llvm::Triple::riscv64) &&
451  "Unexpected triple");
452 
453  // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
454  // configured using `--with-abi=`, then the logic for the default choice is
455  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
456  // deviate from GCC's default only on baremetal targets (UnknownOS) where
457  // neither `-march` nor `-mabi` is specified.
458  //
459  // The logic uses the following, in order:
460  // 1. Explicit choices using `--with-abi=`
461  // 2. A default based on `--with-arch=`, if provided
462  // 3. A default based on the target triple's arch
463  //
464  // The logic in config.gcc is a little circular but it is not inconsistent.
465  //
466  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
467  // and `-mabi=` respectively instead.
468 
469  // 1. If `-mabi=` is specified, use it.
470  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
471  return A->getValue();
472 
473  // 2. Choose a default based on `-march=`
474  //
475  // rv32g | rv32*d -> ilp32d
476  // rv32e -> ilp32e
477  // rv32* -> ilp32
478  // rv64g | rv64*d -> lp64d
479  // rv64* -> lp64
480  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
481  StringRef MArch = A->getValue();
482 
483  if (MArch.startswith_lower("rv32")) {
484  // FIXME: parse `March` to find `D` extension properly
485  if (MArch.substr(4).contains_lower("d") ||
486  MArch.startswith_lower("rv32g"))
487  return "ilp32d";
488  else if (MArch.startswith_lower("rv32e"))
489  return "ilp32e";
490  else
491  return "ilp32";
492  } else if (MArch.startswith_lower("rv64")) {
493  // FIXME: parse `March` to find `D` extension properly
494  if (MArch.substr(4).contains_lower("d") ||
495  MArch.startswith_lower("rv64g"))
496  return "lp64d";
497  else
498  return "lp64";
499  }
500  }
501 
502  // 3. Choose a default based on the triple
503  //
504  // We deviate from GCC's defaults here:
505  // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
506  // - On all other OSs we use the double floating point calling convention.
507  if (Triple.getArch() == llvm::Triple::riscv32) {
508  if (Triple.getOS() == llvm::Triple::UnknownOS)
509  return "ilp32";
510  else
511  return "ilp32d";
512  } else {
513  if (Triple.getOS() == llvm::Triple::UnknownOS)
514  return "lp64";
515  else
516  return "lp64d";
517  }
518 }
519 
520 StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
521  const llvm::Triple &Triple) {
522  assert((Triple.getArch() == llvm::Triple::riscv32 ||
523  Triple.getArch() == llvm::Triple::riscv64) &&
524  "Unexpected triple");
525 
526  // GCC's logic around choosing a default `-march=` is complex. If GCC is not
527  // configured using `--with-arch=`, then the logic for the default choice is
528  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
529  // deviate from GCC's default only on baremetal targets (UnknownOS) where
530  // neither `-march` nor `-mabi` is specified.
531  //
532  // The logic uses the following, in order:
533  // 1. Explicit choices using `--with-arch=`
534  // 2. A default based on `--with-abi=`, if provided
535  // 3. A default based on the target triple's arch
536  //
537  // The logic in config.gcc is a little circular but it is not inconsistent.
538  //
539  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
540  // and `-mabi=` respectively instead.
541  //
542  // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
543  // instead of `rv{XLEN}gc` though they are (currently) equivalent.
544 
545  // 1. If `-march=` is specified, use it.
546  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
547  return A->getValue();
548 
549  // 2. Choose a default based on `-mabi=`
550  //
551  // ilp32e -> rv32e
552  // ilp32 | ilp32f | ilp32d -> rv32imafdc
553  // lp64 | lp64f | lp64d -> rv64imafdc
554  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
555  StringRef MABI = A->getValue();
556 
557  if (MABI.equals_lower("ilp32e"))
558  return "rv32e";
559  else if (MABI.startswith_lower("ilp32"))
560  return "rv32imafdc";
561  else if (MABI.startswith_lower("lp64"))
562  return "rv64imafdc";
563  }
564 
565  // 3. Choose a default based on the triple
566  //
567  // We deviate from GCC's defaults here:
568  // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
569  // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
570  if (Triple.getArch() == llvm::Triple::riscv32) {
571  if (Triple.getOS() == llvm::Triple::UnknownOS)
572  return "rv32imac";
573  else
574  return "rv32imafdc";
575  } else {
576  if (Triple.getOS() == llvm::Triple::UnknownOS)
577  return "rv64imac";
578  else
579  return "rv64imafdc";
580  }
581 }
void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, std::vector< StringRef > &Features, llvm::opt::OptSpecifier Group)
The base class of the type hierarchy.
Definition: Type.h:1450
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:109
static void getExtensionFeatures(const Driver &D, const ArgList &Args, std::vector< StringRef > &Features, StringRef &MArch, StringRef &Exts)
Definition: RISCV.cpp:96
static bool getExtensionVersion(const Driver &D, StringRef MArch, StringRef Ext, StringRef In, std::string &Major, std::string &Minor)
Definition: RISCV.cpp:55
StringRef getRISCVArch(const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
Definition: RISCV.cpp:520
llvm::Error Error
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:59
StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple)
static StringRef getExtensionTypeDesc(StringRef Ext)
Definition: RISCV.cpp:25
static bool getArchFeatures(const Driver &D, StringRef MArch, std::vector< StringRef > &Features, const ArgList &Args)
Definition: RISCV.cpp:194
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:35
static bool isSupportedExtension(StringRef Ext)
Definition: RISCV.cpp:45
void getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, std::vector< llvm::StringRef > &Features)