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"
12#include "clang/Driver/DriverDiagnostic.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
20using namespace clang::driver;
21using namespace clang::driver::tools;
22using namespace clang;
23using namespace llvm::opt;
24
25namespace {
26// Represents the major and version number components of a RISC-V extension
27struct RISCVExtensionVersion {
28  StringRef Major;
29  StringRef Minor;
30};
31} // end anonymous namespace
32
33static StringRef getExtensionTypeDesc(StringRef Ext) {
34  if (Ext.startswith("sx"))
35    return "non-standard supervisor-level extension";
36  if (Ext.startswith("s"))
37    return "standard supervisor-level extension";
38  if (Ext.startswith("x"))
39    return "non-standard user-level extension";
40  if (Ext.startswith("z"))
41    return "standard user-level extension";
42  return StringRef();
43}
44
45static StringRef getExtensionType(StringRef Ext) {
46  if (Ext.startswith("sx"))
47    return "sx";
48  if (Ext.startswith("s"))
49    return "s";
50  if (Ext.startswith("x"))
51    return "x";
52  if (Ext.startswith("z"))
53    return "z";
54  return StringRef();
55}
56
57// If the extension is supported as experimental, return the version of that
58// extension that the compiler currently supports.
59static Optional<RISCVExtensionVersion>
60isExperimentalExtension(StringRef Ext) {
61  if (Ext == "b" || Ext == "zbb" || Ext == "zbc" || Ext == "zbe" ||
62      Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || Ext == "zbr" ||
63      Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc")
64    return RISCVExtensionVersion{"0", "92"};
65  if (Ext == "v")
66    return RISCVExtensionVersion{"0", "8"};
67  return None;
68}
69
70static bool isSupportedExtension(StringRef Ext) {
71  // LLVM supports "z" extensions which are marked as experimental.
72  if (isExperimentalExtension(Ext))
73    return true;
74
75  // LLVM does not support "sx", "s" nor "x" extensions.
76  return false;
77}
78
79// Extensions may have a version number, and may be separated by
80// an underscore '_' e.g.: rv32i2_m2.
81// Version number is divided into major and minor version numbers,
82// separated by a 'p'. If the minor version is 0 then 'p0' can be
83// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
84static bool getExtensionVersion(const Driver &D, const ArgList &Args,
85                                StringRef MArch, StringRef Ext, StringRef In,
86                                std::string &Major, std::string &Minor) {
87  Major = std::string(In.take_while(isDigit));
88  In = In.substr(Major.size());
89
90  if (Major.size() && In.consume_front("p")) {
91    Minor = std::string(In.take_while(isDigit));
92    In = In.substr(Major.size() + 1);
93
94    // Expected 'p' to be followed by minor version number.
95    if (Minor.empty()) {
96      std::string Error =
97        "minor version number missing after 'p' for extension";
98      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
99        << MArch << Error << Ext;
100      return false;
101    }
102  }
103
104  // Expected multi-character extension with version number to have no
105  // subsequent characters (i.e. must either end string or be followed by
106  // an underscore).
107  if (Ext.size() > 1 && In.size()) {
108    std::string Error =
109        "multi-character extensions must be separated by underscores";
110    D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << In;
111    return false;
112  }
113
114  // If experimental extension, require use of current version number number
115  if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
116    if (!Args.hasArg(options::OPT_menable_experimental_extensions)) {
117      std::string Error =
118          "requires '-menable-experimental-extensions' for experimental extension";
119      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
120          << MArch << Error << Ext;
121      return false;
122    } else if (Major.empty() && Minor.empty()) {
123      std::string Error =
124          "experimental extension requires explicit version number";
125      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
126          << MArch << Error << Ext;
127      return false;
128    }
129    auto SupportedVers = *ExperimentalExtension;
130    if (Major != SupportedVers.Major || Minor != SupportedVers.Minor) {
131      std::string Error =
132          "unsupported version number " + Major;
133      if (!Minor.empty())
134        Error += "." + Minor;
135      Error += " for experimental extension (this compiler supports "
136            + SupportedVers.Major.str() + "."
137            + SupportedVers.Minor.str() + ")";
138
139      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
140          << MArch << Error << Ext;
141      return false;
142    }
143    return true;
144  }
145
146  // Allow extensions to declare no version number
147  if (Major.empty() && Minor.empty())
148    return true;
149
150  // TODO: Handle supported extensions with version number.
151  std::string Error = "unsupported version number " + Major;
152  if (!Minor.empty())
153    Error += "." + Minor;
154  Error += " for extension";
155  D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
156
157  return false;
158}
159
160// Handle other types of extensions other than the standard
161// general purpose and standard user-level extensions.
162// Parse the ISA string containing non-standard user-level
163// extensions, standard supervisor-level extensions and
164// non-standard supervisor-level extensions.
165// These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
166// canonical order, might have a version number (major, minor)
167// and are separated by a single underscore '_'.
168// Set the hardware features for the extensions that are supported.
169static void getExtensionFeatures(const Driver &D,
170                                 const ArgList &Args,
171                                 std::vector<StringRef> &Features,
172                                 StringRef &MArch, StringRef &Exts) {
173  if (Exts.empty())
174    return;
175
176  // Multi-letter extensions are seperated by a single underscore
177  // as described in RISC-V User-Level ISA V2.2.
178  SmallVector<StringRef, 8> Split;
179  Exts.split(Split, StringRef("_"));
180
181  SmallVector<StringRef, 4> Prefix{"z", "x", "s", "sx"};
182  auto I = Prefix.begin();
183  auto E = Prefix.end();
184
185  SmallVector<StringRef, 8> AllExts;
186
187  for (StringRef Ext : Split) {
188    if (Ext.empty()) {
189      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
190        << "extension name missing after separator '_'";
191      return;
192    }
193
194    StringRef Type = getExtensionType(Ext);
195    StringRef Desc = getExtensionTypeDesc(Ext);
196    auto Pos = Ext.find_if(isDigit);
197    StringRef Name(Ext.substr(0, Pos));
198    StringRef Vers(Ext.substr(Pos));
199
200    if (Type.empty()) {
201      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
202        << MArch << "invalid extension prefix" << Ext;
203      return;
204    }
205
206    // Check ISA extensions are specified in the canonical order.
207    while (I != E && *I != Type)
208      ++I;
209
210    if (I == E) {
211      std::string Error = std::string(Desc);
212      Error += " not given in canonical order";
213      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
214        << MArch <<  Error << Ext;
215      return;
216    }
217
218    // The order is OK, do not advance I to the next prefix
219    // to allow repeated extension type, e.g.: rv32ixabc_xdef.
220
221    if (Name.size() == Type.size()) {
222      std::string Error = std::string(Desc);
223      Error += " name missing after";
224      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
225        << MArch << Error << Type;
226      return;
227    }
228
229    std::string Major, Minor;
230    if (!getExtensionVersion(D, Args, MArch, Name, Vers, Major, Minor))
231      return;
232
233    // Check if duplicated extension.
234    if (llvm::is_contained(AllExts, Name)) {
235      std::string Error = "duplicated ";
236      Error += Desc;
237      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
238        << MArch << Error << Name;
239      return;
240    }
241
242    // Extension format is correct, keep parsing the extensions.
243    // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
244    AllExts.push_back(Name);
245  }
246
247  // Set target features.
248  // TODO: Hardware features to be handled in Support/TargetParser.cpp.
249  // TODO: Use version number when setting target features.
250  for (auto Ext : AllExts) {
251    if (!isSupportedExtension(Ext)) {
252      StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
253      std::string Error = "unsupported ";
254      Error += Desc;
255      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
256        << MArch << Error << Ext;
257      return;
258    }
259    if (isExperimentalExtension(Ext))
260      Features.push_back(Args.MakeArgString("+experimental-" + Ext));
261    else
262      Features.push_back(Args.MakeArgString("+" + Ext));
263  }
264}
265
266// Returns false if an error is diagnosed.
267static bool getArchFeatures(const Driver &D, StringRef MArch,
268                            std::vector<StringRef> &Features,
269                            const ArgList &Args) {
270  // RISC-V ISA strings must be lowercase.
271  if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
272    D.Diag(diag::err_drv_invalid_riscv_arch_name)
273        << MArch << "string must be lowercase";
274    return false;
275  }
276
277  // ISA string must begin with rv32 or rv64.
278  if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
279      (MArch.size() < 5)) {
280    D.Diag(diag::err_drv_invalid_riscv_arch_name)
281        << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
282    return false;
283  }
284
285  bool HasRV64 = MArch.startswith("rv64");
286
287  // The canonical order specified in ISA manual.
288  // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
289  StringRef StdExts = "mafdqlcbjtpvn";
290  bool HasF = false, HasD = false;
291  char Baseline = MArch[4];
292
293  // First letter should be 'e', 'i' or 'g'.
294  switch (Baseline) {
295  default:
296    D.Diag(diag::err_drv_invalid_riscv_arch_name)
297        << MArch << "first letter should be 'e', 'i' or 'g'";
298    return false;
299  case 'e': {
300    StringRef Error;
301    // Currently LLVM does not support 'e'.
302    // Extension 'e' is not allowed in rv64.
303    if (HasRV64)
304      Error = "standard user-level extension 'e' requires 'rv32'";
305    else
306      Error = "unsupported standard user-level extension 'e'";
307    D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error;
308    return false;
309  }
310  case 'i':
311    break;
312  case 'g':
313    // g = imafd
314    StdExts = StdExts.drop_front(4);
315    Features.push_back("+m");
316    Features.push_back("+a");
317    Features.push_back("+f");
318    Features.push_back("+d");
319    HasF = true;
320    HasD = true;
321    break;
322  }
323
324  // Skip rvxxx
325  StringRef Exts = MArch.substr(5);
326
327  // Remove multi-letter standard extensions, non-standard extensions and
328  // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
329  // Parse them at the end.
330  // Find the very first occurrence of 's', 'x' or 'z'.
331  StringRef OtherExts;
332  size_t Pos = Exts.find_first_of("zsx");
333  if (Pos != StringRef::npos) {
334    OtherExts = Exts.substr(Pos);
335    Exts = Exts.substr(0, Pos);
336  }
337
338  std::string Major, Minor;
339  if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts,
340                           Major, Minor))
341    return false;
342
343  // Consume the base ISA version number and any '_' between rvxxx and the
344  // first extension
345  Exts = Exts.drop_front(Major.size());
346  if (!Minor.empty())
347    Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/);
348  Exts.consume_front("_");
349
350  // TODO: Use version number when setting target features
351
352  auto StdExtsItr = StdExts.begin();
353  auto StdExtsEnd = StdExts.end();
354
355  for (auto I = Exts.begin(), E = Exts.end(); I != E; ) {
356    char c = *I;
357
358    // Check ISA extensions are specified in the canonical order.
359    while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
360      ++StdExtsItr;
361
362    if (StdExtsItr == StdExtsEnd) {
363      // Either c contains a valid extension but it was not given in
364      // canonical order or it is an invalid extension.
365      StringRef Error;
366      if (StdExts.contains(c))
367        Error = "standard user-level extension not given in canonical order";
368      else
369        Error = "invalid standard user-level extension";
370      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
371          << MArch << Error << std::string(1, c);
372      return false;
373    }
374
375    // Move to next char to prevent repeated letter.
376    ++StdExtsItr;
377
378    std::string Next, Major, Minor;
379    if (std::next(I) != E)
380      Next = std::string(std::next(I), E);
381    if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major,
382                             Minor))
383      return false;
384
385    // The order is OK, then push it into features.
386    // TODO: Use version number when setting target features
387    switch (c) {
388    default:
389      // Currently LLVM supports only "mafdc".
390      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
391          << MArch << "unsupported standard user-level extension"
392          << std::string(1, c);
393      return false;
394    case 'm':
395      Features.push_back("+m");
396      break;
397    case 'a':
398      Features.push_back("+a");
399      break;
400    case 'f':
401      Features.push_back("+f");
402      HasF = true;
403      break;
404    case 'd':
405      Features.push_back("+d");
406      HasD = true;
407      break;
408    case 'c':
409      Features.push_back("+c");
410      break;
411    case 'b':
412      Features.push_back("+experimental-b");
413      break;
414    case 'v':
415      Features.push_back("+experimental-v");
416      break;
417    }
418
419    // Consume full extension name and version, including any optional '_'
420    // between this extension and the next
421    ++I;
422    I += Major.size();
423    if (Minor.size())
424      I += Minor.size() + 1 /*'p'*/;
425    if (*I == '_')
426      ++I;
427  }
428
429  // Dependency check.
430  // It's illegal to specify the 'd' (double-precision floating point)
431  // extension without also specifying the 'f' (single precision
432  // floating-point) extension.
433  if (HasD && !HasF) {
434    D.Diag(diag::err_drv_invalid_riscv_arch_name)
435        << MArch << "d requires f extension to also be specified";
436    return false;
437  }
438
439  // Additional dependency checks.
440  // TODO: The 'q' extension requires rv64.
441  // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
442
443  // Handle all other types of extensions.
444  getExtensionFeatures(D, Args, Features, MArch, OtherExts);
445
446  return true;
447}
448
449// Get features except standard extension feature
450void getRISCFeaturesFromMcpu(const Driver &D, const llvm::Triple &Triple,
451                             const llvm::opt::ArgList &Args,
452                             const llvm::opt::Arg *A, StringRef Mcpu,
453                             std::vector<StringRef> &Features) {
454  bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64);
455  llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu);
456  if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) ||
457      !llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) {
458    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
459  }
460}
461
462void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
463                                   const ArgList &Args,
464                                   std::vector<StringRef> &Features) {
465  StringRef MArch = getRISCVArch(Args, Triple);
466
467  if (!getArchFeatures(D, MArch, Features, Args))
468    return;
469
470  // If users give march and mcpu, get std extension feature from MArch
471  // and other features (ex. mirco architecture feature) from mcpu
472  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
473    getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
474
475  // Handle features corresponding to "-ffixed-X" options
476  if (Args.hasArg(options::OPT_ffixed_x1))
477    Features.push_back("+reserve-x1");
478  if (Args.hasArg(options::OPT_ffixed_x2))
479    Features.push_back("+reserve-x2");
480  if (Args.hasArg(options::OPT_ffixed_x3))
481    Features.push_back("+reserve-x3");
482  if (Args.hasArg(options::OPT_ffixed_x4))
483    Features.push_back("+reserve-x4");
484  if (Args.hasArg(options::OPT_ffixed_x5))
485    Features.push_back("+reserve-x5");
486  if (Args.hasArg(options::OPT_ffixed_x6))
487    Features.push_back("+reserve-x6");
488  if (Args.hasArg(options::OPT_ffixed_x7))
489    Features.push_back("+reserve-x7");
490  if (Args.hasArg(options::OPT_ffixed_x8))
491    Features.push_back("+reserve-x8");
492  if (Args.hasArg(options::OPT_ffixed_x9))
493    Features.push_back("+reserve-x9");
494  if (Args.hasArg(options::OPT_ffixed_x10))
495    Features.push_back("+reserve-x10");
496  if (Args.hasArg(options::OPT_ffixed_x11))
497    Features.push_back("+reserve-x11");
498  if (Args.hasArg(options::OPT_ffixed_x12))
499    Features.push_back("+reserve-x12");
500  if (Args.hasArg(options::OPT_ffixed_x13))
501    Features.push_back("+reserve-x13");
502  if (Args.hasArg(options::OPT_ffixed_x14))
503    Features.push_back("+reserve-x14");
504  if (Args.hasArg(options::OPT_ffixed_x15))
505    Features.push_back("+reserve-x15");
506  if (Args.hasArg(options::OPT_ffixed_x16))
507    Features.push_back("+reserve-x16");
508  if (Args.hasArg(options::OPT_ffixed_x17))
509    Features.push_back("+reserve-x17");
510  if (Args.hasArg(options::OPT_ffixed_x18))
511    Features.push_back("+reserve-x18");
512  if (Args.hasArg(options::OPT_ffixed_x19))
513    Features.push_back("+reserve-x19");
514  if (Args.hasArg(options::OPT_ffixed_x20))
515    Features.push_back("+reserve-x20");
516  if (Args.hasArg(options::OPT_ffixed_x21))
517    Features.push_back("+reserve-x21");
518  if (Args.hasArg(options::OPT_ffixed_x22))
519    Features.push_back("+reserve-x22");
520  if (Args.hasArg(options::OPT_ffixed_x23))
521    Features.push_back("+reserve-x23");
522  if (Args.hasArg(options::OPT_ffixed_x24))
523    Features.push_back("+reserve-x24");
524  if (Args.hasArg(options::OPT_ffixed_x25))
525    Features.push_back("+reserve-x25");
526  if (Args.hasArg(options::OPT_ffixed_x26))
527    Features.push_back("+reserve-x26");
528  if (Args.hasArg(options::OPT_ffixed_x27))
529    Features.push_back("+reserve-x27");
530  if (Args.hasArg(options::OPT_ffixed_x28))
531    Features.push_back("+reserve-x28");
532  if (Args.hasArg(options::OPT_ffixed_x29))
533    Features.push_back("+reserve-x29");
534  if (Args.hasArg(options::OPT_ffixed_x30))
535    Features.push_back("+reserve-x30");
536  if (Args.hasArg(options::OPT_ffixed_x31))
537    Features.push_back("+reserve-x31");
538
539  // FreeBSD local, because ld.lld doesn't support relaxations
540  // -mno-relax is default, unless -mrelax is specified.
541  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
542    Features.push_back("+relax");
543  else
544    Features.push_back("-relax");
545
546  // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
547  // specified.
548  if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
549    Features.push_back("+save-restore");
550  else
551    Features.push_back("-save-restore");
552
553  // Now add any that the user explicitly requested on the command line,
554  // which may override the defaults.
555  handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
556}
557
558StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
559  assert((Triple.getArch() == llvm::Triple::riscv32 ||
560          Triple.getArch() == llvm::Triple::riscv64) &&
561         "Unexpected triple");
562
563  // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
564  // configured using `--with-abi=`, then the logic for the default choice is
565  // defined in config.gcc. This function is based on the logic in GCC 9.2.0.
566  //
567  // The logic used in GCC 9.2.0 is the following, in order:
568  // 1. Explicit choices using `--with-abi=`
569  // 2. A default based on `--with-arch=`, if provided
570  // 3. A default based on the target triple's arch
571  //
572  // The logic in config.gcc is a little circular but it is not inconsistent.
573  //
574  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
575  // and `-mabi=` respectively instead.
576  //
577  // In order to make chosing logic more clear, Clang uses the following logic,
578  // in order:
579  // 1. Explicit choices using `-mabi=`
580  // 2. A default based on the architecture as determined by getRISCVArch
581  // 3. Choose a default based on the triple
582
583  // 1. If `-mabi=` is specified, use it.
584  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
585    return A->getValue();
586
587  // 2. Choose a default based on the target architecture.
588  //
589  // rv32g | rv32*d -> ilp32d
590  // rv32e -> ilp32e
591  // rv32* -> ilp32
592  // rv64g | rv64*d -> lp64d
593  // rv64* -> lp64
594  StringRef MArch = getRISCVArch(Args, Triple);
595
596  if (MArch.startswith_lower("rv32")) {
597    // FIXME: parse `March` to find `D` extension properly
598    if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv32g"))
599      return "ilp32d";
600    else if (MArch.startswith_lower("rv32e"))
601      return "ilp32e";
602    else
603      return "ilp32";
604  } else if (MArch.startswith_lower("rv64")) {
605    // FIXME: parse `March` to find `D` extension properly
606    if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv64g"))
607      return "lp64d";
608    else
609      return "lp64";
610  }
611
612  // 3. Choose a default based on the triple
613  //
614  // We deviate from GCC's defaults here:
615  // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
616  // - On all other OSs we use the double floating point calling convention.
617  if (Triple.getArch() == llvm::Triple::riscv32) {
618    if (Triple.getOS() == llvm::Triple::UnknownOS)
619      return "ilp32";
620    else
621      return "ilp32d";
622  } else {
623    if (Triple.getOS() == llvm::Triple::UnknownOS)
624      return "lp64";
625    else
626      return "lp64d";
627  }
628}
629
630StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
631                              const llvm::Triple &Triple) {
632  assert((Triple.getArch() == llvm::Triple::riscv32 ||
633          Triple.getArch() == llvm::Triple::riscv64) &&
634         "Unexpected triple");
635
636  // GCC's logic around choosing a default `-march=` is complex. If GCC is not
637  // configured using `--with-arch=`, then the logic for the default choice is
638  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
639  // deviate from GCC's default on additional `-mcpu` option (GCC does not
640  // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
641  // nor `-mabi` is specified.
642  //
643  // The logic used in GCC 9.2.0 is the following, in order:
644  // 1. Explicit choices using `--with-arch=`
645  // 2. A default based on `--with-abi=`, if provided
646  // 3. A default based on the target triple's arch
647  //
648  // The logic in config.gcc is a little circular but it is not inconsistent.
649  //
650  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
651  // and `-mabi=` respectively instead.
652  //
653  // Clang uses the following logic, in order:
654  // 1. Explicit choices using `-march=`
655  // 2. Based on `-mcpu` if the target CPU has a default ISA string
656  // 3. A default based on `-mabi`, if provided
657  // 4. A default based on the target triple's arch
658  //
659  // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
660  // instead of `rv{XLEN}gc` though they are (currently) equivalent.
661
662  // 1. If `-march=` is specified, use it.
663  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
664    return A->getValue();
665
666  // 2. Get march (isa string) based on `-mcpu=`
667  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
668    StringRef MArch = llvm::RISCV::getMArchFromMcpu(A->getValue());
669    // Bypass if target cpu's default march is empty.
670    if (MArch != "")
671      return MArch;
672  }
673
674  // 3. Choose a default based on `-mabi=`
675  //
676  // ilp32e -> rv32e
677  // ilp32 | ilp32f | ilp32d -> rv32imafdc
678  // lp64 | lp64f | lp64d -> rv64imafdc
679  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
680    StringRef MABI = A->getValue();
681
682    if (MABI.equals_lower("ilp32e"))
683      return "rv32e";
684    else if (MABI.startswith_lower("ilp32"))
685      return "rv32imafdc";
686    else if (MABI.startswith_lower("lp64"))
687      return "rv64imafdc";
688  }
689
690  // 4. Choose a default based on the triple
691  //
692  // We deviate from GCC's defaults here:
693  // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
694  // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
695  if (Triple.getArch() == llvm::Triple::riscv32) {
696    if (Triple.getOS() == llvm::Triple::UnknownOS)
697      return "rv32imac";
698    else
699      return "rv32imafdc";
700  } else {
701    if (Triple.getOS() == llvm::Triple::UnknownOS)
702      return "rv64imac";
703    else
704      return "rv64imafdc";
705  }
706}
707