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