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/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.
104   SmallVector<StringRef, 8> Split;
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 
111   SmallVector<StringRef, 8> AllExts;
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 }
380