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