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 
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.
105   SmallVector<StringRef, 8> Split;
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 
112   SmallVector<StringRef, 8> AllExts;
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   // FreeBSD local, because ld.lld doesn't support relaxations
430   // -mno-relax is default, unless -mrelax is specified.
431   if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
432     Features.push_back("+relax");
433   else
434     Features.push_back("-relax");
435 
436   // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
437   // specified...
438   if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) {
439     // ... but we don't support -msave-restore, so issue a warning.
440     D.Diag(diag::warn_drv_clang_unsupported)
441       << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args);
442   }
443 
444   // Now add any that the user explicitly requested on the command line,
445   // which may override the defaults.
446   handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
447 }
448 
449 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
450   assert((Triple.getArch() == llvm::Triple::riscv32 ||
451           Triple.getArch() == llvm::Triple::riscv64) &&
452          "Unexpected triple");
453 
454   // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
455   // configured using `--with-abi=`, then the logic for the default choice is
456   // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
457   // deviate from GCC's default only on baremetal targets (UnknownOS) where
458   // neither `-march` nor `-mabi` is specified.
459   //
460   // The logic uses the following, in order:
461   // 1. Explicit choices using `--with-abi=`
462   // 2. A default based on `--with-arch=`, if provided
463   // 3. A default based on the target triple's arch
464   //
465   // The logic in config.gcc is a little circular but it is not inconsistent.
466   //
467   // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
468   // and `-mabi=` respectively instead.
469 
470   // 1. If `-mabi=` is specified, use it.
471   if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
472     return A->getValue();
473 
474   // 2. Choose a default based on `-march=`
475   //
476   // rv32g | rv32*d -> ilp32d
477   // rv32e -> ilp32e
478   // rv32* -> ilp32
479   // rv64g | rv64*d -> lp64d
480   // rv64* -> lp64
481   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
482     StringRef MArch = A->getValue();
483 
484     if (MArch.startswith_lower("rv32")) {
485       // FIXME: parse `March` to find `D` extension properly
486       if (MArch.substr(4).contains_lower("d") ||
487           MArch.startswith_lower("rv32g"))
488         return "ilp32d";
489       else if (MArch.startswith_lower("rv32e"))
490         return "ilp32e";
491       else
492         return "ilp32";
493     } else if (MArch.startswith_lower("rv64")) {
494       // FIXME: parse `March` to find `D` extension properly
495       if (MArch.substr(4).contains_lower("d") ||
496           MArch.startswith_lower("rv64g"))
497         return "lp64d";
498       else
499         return "lp64";
500     }
501   }
502 
503   // 3. Choose a default based on the triple
504   //
505   // We deviate from GCC's defaults here:
506   // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
507   // - On all other OSs we use the double floating point calling convention.
508   if (Triple.getArch() == llvm::Triple::riscv32) {
509     if (Triple.getOS() == llvm::Triple::UnknownOS)
510       return "ilp32";
511     else
512       return "ilp32d";
513   } else {
514     if (Triple.getOS() == llvm::Triple::UnknownOS)
515       return "lp64";
516     else
517       return "lp64d";
518   }
519 }
520 
521 StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
522                               const llvm::Triple &Triple) {
523   assert((Triple.getArch() == llvm::Triple::riscv32 ||
524           Triple.getArch() == llvm::Triple::riscv64) &&
525          "Unexpected triple");
526 
527   // GCC's logic around choosing a default `-march=` is complex. If GCC is not
528   // configured using `--with-arch=`, then the logic for the default choice is
529   // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
530   // deviate from GCC's default only on baremetal targets (UnknownOS) where
531   // neither `-march` nor `-mabi` is specified.
532   //
533   // The logic uses the following, in order:
534   // 1. Explicit choices using `--with-arch=`
535   // 2. A default based on `--with-abi=`, if provided
536   // 3. A default based on the target triple's arch
537   //
538   // The logic in config.gcc is a little circular but it is not inconsistent.
539   //
540   // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
541   // and `-mabi=` respectively instead.
542   //
543   // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
544   // instead of `rv{XLEN}gc` though they are (currently) equivalent.
545 
546   // 1. If `-march=` is specified, use it.
547   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
548     return A->getValue();
549 
550   // 2. Choose a default based on `-mabi=`
551   //
552   // ilp32e -> rv32e
553   // ilp32 | ilp32f | ilp32d -> rv32imafdc
554   // lp64 | lp64f | lp64d -> rv64imafdc
555   if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
556     StringRef MABI = A->getValue();
557 
558     if (MABI.equals_lower("ilp32e"))
559       return "rv32e";
560     else if (MABI.startswith_lower("ilp32"))
561       return "rv32imafdc";
562     else if (MABI.startswith_lower("lp64"))
563       return "rv64imafdc";
564   }
565 
566   // 3. Choose a default based on the triple
567   //
568   // We deviate from GCC's defaults here:
569   // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
570   // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
571   if (Triple.getArch() == llvm::Triple::riscv32) {
572     if (Triple.getOS() == llvm::Triple::UnknownOS)
573       return "rv32imac";
574     else
575       return "rv32imafdc";
576   } else {
577     if (Triple.getOS() == llvm::Triple::UnknownOS)
578       return "rv64imac";
579     else
580       return "rv64imafdc";
581   }
582 }
583