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