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