1 //===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
20 using namespace clang::driver;
21 using namespace clang::driver::tools;
22 using namespace clang;
23 using namespace llvm::opt;
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";
35 static StringRef getExtensionType(StringRef Ext) {
36 if (Ext.startswith("sx"))
38 if (Ext.startswith("s"))
40 if (Ext.startswith("x"))
45 static bool isSupportedExtension(StringRef Ext) {
46 // LLVM does not support "sx", "s" nor "x" extensions.
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) {
61 while (I != E && isDigit(*I))
62 Major.append(1, *I++);
67 if (I != E && *I == 'p') {
70 while (I != E && isDigit(*I))
71 Minor.append(1, *I++);
73 // Expected 'p' to be followed by minor version number.
76 "minor version number missing after 'p' for extension";
77 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
78 << MArch << Error << Ext;
83 // TODO: Handle extensions with version number.
84 std::string Error = "unsupported version number " + Major;
87 Error += " for extension";
88 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
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,
104 std::vector<StringRef> &Features,
105 StringRef &MArch, StringRef &Exts) {
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("_"));
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();
121 SmallVector<StringRef, 8> AllExts;
123 for (StringRef Ext : Split) {
126 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
127 << "extension name missing after separator '_'";
131 StringRef Type = getExtensionType(Ext);
132 StringRef Name(Ext.substr(Type.size()));
133 StringRef Desc = getExtensionTypeDesc(Ext);
136 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
137 << MArch << "invalid extension prefix" << Ext;
141 // Check ISA extensions are specified in the canonical order.
142 while (I != E && *I != Type)
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;
153 // The order is OK, do not advance I to the next prefix
154 // to allow repeated extension type, e.g.: rv32ixabc_xdef.
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;
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))
173 // Check if duplicated extension.
174 if (std::find(AllExts.begin(), AllExts.end(), Ext) != AllExts.end()) {
175 std::string Error = "duplicated ";
177 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
178 << MArch << Error << Ext;
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);
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 ";
195 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
196 << MArch << Error << Ext;
199 Features.push_back(Args.MakeArgString("+" + Ext));
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();
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); })) {
212 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
213 << "string must be lowercase";
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}";
225 bool HasRV64 = MArch.startswith("rv64") ? true : false;
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];
233 // First letter should be 'e', 'i' or 'g'.
236 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
237 << "first letter should be 'e', 'i' or 'g'";
241 // Currently LLVM does not support 'e'.
242 // Extension 'e' is not allowed in rv64.
244 Error = "standard user-level extension 'e' requires 'rv32'";
246 Error = "unsupported standard user-level extension 'e'";
247 D.Diag(diag::err_drv_invalid_riscv_arch_name)
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");
266 StringRef Exts = MArch.substr(5);
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'.
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);
278 std::string Major, Minor;
279 if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
283 // TODO: Use version number when setting target features
284 // and consume the underscore '_' that might follow.
286 auto StdExtsItr = StdExts.begin();
287 auto StdExtsEnd = StdExts.end();
289 for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
292 // Check ISA extensions are specified in the canonical order.
293 while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
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.
300 if (StdExts.contains(c))
301 Error = "standard user-level extension not given in canonical order";
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);
309 // Move to next char to prevent repeated letter.
312 if (std::next(I) != E) {
314 std::string Next = std::string(std::next(I), E);
315 std::string Major, Minor;
316 if (!getExtensionVersion(D, MArch, std::string(1, c),
320 // TODO: Use version number when setting target features
321 // and consume the underscore '_' that might follow.
324 // The order is OK, then push it into features.
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);
333 Features.push_back("+m");
336 Features.push_back("+a");
339 Features.push_back("+f");
343 Features.push_back("+d");
347 Features.push_back("+c");
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.
357 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
358 << "d requires f extension to also be specified";
360 // Additional dependency checks.
361 // TODO: The 'q' extension requires rv64.
362 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
364 // Handle all other types of extensions.
365 getExtensionFeatures(D, Args, Features, MArch, OtherExts);
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);
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();
377 return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";