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 namespace { 26 // Represents the major and version number components of a RISC-V extension 27 struct RISCVExtensionVersion { 28 StringRef Major; 29 StringRef Minor; 30 }; 31 } // end anonymous namespace 32 33 static StringRef getExtensionTypeDesc(StringRef Ext) { 34 if (Ext.startswith("sx")) 35 return "non-standard supervisor-level extension"; 36 if (Ext.startswith("s")) 37 return "standard supervisor-level extension"; 38 if (Ext.startswith("x")) 39 return "non-standard user-level extension"; 40 if (Ext.startswith("z")) 41 return "standard user-level extension"; 42 return StringRef(); 43 } 44 45 static StringRef getExtensionType(StringRef Ext) { 46 if (Ext.startswith("sx")) 47 return "sx"; 48 if (Ext.startswith("s")) 49 return "s"; 50 if (Ext.startswith("x")) 51 return "x"; 52 if (Ext.startswith("z")) 53 return "z"; 54 return StringRef(); 55 } 56 57 // If the extension is supported as experimental, return the version of that 58 // extension that the compiler currently supports. 59 static Optional<RISCVExtensionVersion> 60 isExperimentalExtension(StringRef Ext) { 61 if (Ext == "b" || Ext == "zba" || Ext == "zbb" || Ext == "zbc" || 62 Ext == "zbe" || Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || 63 Ext == "zbr" || Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") 64 return RISCVExtensionVersion{"0", "93"}; 65 if (Ext == "v" || Ext == "zvamo" || Ext == "zvlsseg") 66 return RISCVExtensionVersion{"0", "10"}; 67 if (Ext == "zfh") 68 return RISCVExtensionVersion{"0", "1"}; 69 return None; 70 } 71 72 static bool isSupportedExtension(StringRef Ext) { 73 // LLVM supports "z" extensions which are marked as experimental. 74 if (isExperimentalExtension(Ext)) 75 return true; 76 77 // LLVM does not support "sx", "s" nor "x" extensions. 78 return false; 79 } 80 81 // Extensions may have a version number, and may be separated by 82 // an underscore '_' e.g.: rv32i2_m2. 83 // Version number is divided into major and minor version numbers, 84 // separated by a 'p'. If the minor version is 0 then 'p0' can be 85 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 86 static bool getExtensionVersion(const Driver &D, const ArgList &Args, 87 StringRef MArch, StringRef Ext, StringRef In, 88 std::string &Major, std::string &Minor) { 89 Major = std::string(In.take_while(isDigit)); 90 In = In.substr(Major.size()); 91 92 if (Major.size() && In.consume_front("p")) { 93 Minor = std::string(In.take_while(isDigit)); 94 In = In.substr(Major.size() + 1); 95 96 // Expected 'p' to be followed by minor version number. 97 if (Minor.empty()) { 98 std::string Error = 99 "minor version number missing after 'p' for extension"; 100 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 101 << MArch << Error << Ext; 102 return false; 103 } 104 } 105 106 // Expected multi-character extension with version number to have no 107 // subsequent characters (i.e. must either end string or be followed by 108 // an underscore). 109 if (Ext.size() > 1 && In.size()) { 110 std::string Error = 111 "multi-character extensions must be separated by underscores"; 112 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << In; 113 return false; 114 } 115 116 // If experimental extension, require use of current version number number 117 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { 118 if (!Args.hasArg(options::OPT_menable_experimental_extensions)) { 119 std::string Error = 120 "requires '-menable-experimental-extensions' for experimental extension"; 121 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 122 << MArch << Error << Ext; 123 return false; 124 } else if (Major.empty() && Minor.empty()) { 125 std::string Error = 126 "experimental extension requires explicit version number"; 127 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 128 << MArch << Error << Ext; 129 return false; 130 } 131 auto SupportedVers = *ExperimentalExtension; 132 if (Major != SupportedVers.Major || Minor != SupportedVers.Minor) { 133 std::string Error = 134 "unsupported version number " + Major; 135 if (!Minor.empty()) 136 Error += "." + Minor; 137 Error += " for experimental extension (this compiler supports " 138 + SupportedVers.Major.str() + "." 139 + SupportedVers.Minor.str() + ")"; 140 141 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 142 << MArch << Error << Ext; 143 return false; 144 } 145 return true; 146 } 147 148 // Allow extensions to declare no version number 149 if (Major.empty() && Minor.empty()) 150 return true; 151 152 // TODO: Handle supported extensions with version number. 153 std::string Error = "unsupported version number " + Major; 154 if (!Minor.empty()) 155 Error += "." + Minor; 156 Error += " for extension"; 157 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext; 158 159 return false; 160 } 161 162 // Handle other types of extensions other than the standard 163 // general purpose and standard user-level extensions. 164 // Parse the ISA string containing non-standard user-level 165 // extensions, standard supervisor-level extensions and 166 // non-standard supervisor-level extensions. 167 // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a 168 // canonical order, might have a version number (major, minor) 169 // and are separated by a single underscore '_'. 170 // Set the hardware features for the extensions that are supported. 171 static void getExtensionFeatures(const Driver &D, 172 const ArgList &Args, 173 std::vector<StringRef> &Features, 174 StringRef &MArch, StringRef &Exts) { 175 if (Exts.empty()) 176 return; 177 178 // Multi-letter extensions are seperated by a single underscore 179 // as described in RISC-V User-Level ISA V2.2. 180 SmallVector<StringRef, 8> Split; 181 Exts.split(Split, StringRef("_")); 182 183 SmallVector<StringRef, 4> Prefix{"z", "x", "s", "sx"}; 184 auto I = Prefix.begin(); 185 auto E = Prefix.end(); 186 187 SmallVector<StringRef, 8> AllExts; 188 189 for (StringRef Ext : Split) { 190 if (Ext.empty()) { 191 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 192 << "extension name missing after separator '_'"; 193 return; 194 } 195 196 StringRef Type = getExtensionType(Ext); 197 StringRef Desc = getExtensionTypeDesc(Ext); 198 auto Pos = Ext.find_if(isDigit); 199 StringRef Name(Ext.substr(0, Pos)); 200 StringRef Vers(Ext.substr(Pos)); 201 202 if (Type.empty()) { 203 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 204 << MArch << "invalid extension prefix" << Ext; 205 return; 206 } 207 208 // Check ISA extensions are specified in the canonical order. 209 while (I != E && *I != Type) 210 ++I; 211 212 if (I == E) { 213 std::string Error = std::string(Desc); 214 Error += " not given in canonical order"; 215 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 216 << MArch << Error << Ext; 217 return; 218 } 219 220 // The order is OK, do not advance I to the next prefix 221 // to allow repeated extension type, e.g.: rv32ixabc_xdef. 222 223 if (Name.size() == Type.size()) { 224 std::string Error = std::string(Desc); 225 Error += " name missing after"; 226 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 227 << MArch << Error << Type; 228 return; 229 } 230 231 std::string Major, Minor; 232 if (!getExtensionVersion(D, Args, MArch, Name, Vers, Major, Minor)) 233 return; 234 235 // Check if duplicated extension. 236 if (llvm::is_contained(AllExts, Name)) { 237 std::string Error = "duplicated "; 238 Error += Desc; 239 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 240 << MArch << Error << Name; 241 return; 242 } 243 244 // Extension format is correct, keep parsing the extensions. 245 // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 246 AllExts.push_back(Name); 247 } 248 249 // Set target features. 250 // TODO: Hardware features to be handled in Support/TargetParser.cpp. 251 // TODO: Use version number when setting target features. 252 for (auto Ext : AllExts) { 253 if (!isSupportedExtension(Ext)) { 254 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 255 std::string Error = "unsupported "; 256 Error += Desc; 257 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 258 << MArch << Error << Ext; 259 return; 260 } 261 if (Ext == "zvamo" || Ext == "zvlsseg") { 262 Features.push_back("+experimental-v"); 263 Features.push_back("+experimental-zvamo"); 264 Features.push_back("+experimental-zvlsseg"); 265 } else if (isExperimentalExtension(Ext)) 266 Features.push_back(Args.MakeArgString("+experimental-" + Ext)); 267 else 268 Features.push_back(Args.MakeArgString("+" + Ext)); 269 } 270 } 271 272 // Returns false if an error is diagnosed. 273 static bool getArchFeatures(const Driver &D, StringRef MArch, 274 std::vector<StringRef> &Features, 275 const ArgList &Args) { 276 // RISC-V ISA strings must be lowercase. 277 if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { 278 D.Diag(diag::err_drv_invalid_riscv_arch_name) 279 << MArch << "string must be lowercase"; 280 return false; 281 } 282 283 // ISA string must begin with rv32 or rv64. 284 if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || 285 (MArch.size() < 5)) { 286 D.Diag(diag::err_drv_invalid_riscv_arch_name) 287 << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}"; 288 return false; 289 } 290 291 bool HasRV64 = MArch.startswith("rv64"); 292 293 // The canonical order specified in ISA manual. 294 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 295 StringRef StdExts = "mafdqlcbjtpvn"; 296 bool HasF = false, HasD = false; 297 char Baseline = MArch[4]; 298 299 // First letter should be 'e', 'i' or 'g'. 300 switch (Baseline) { 301 default: 302 D.Diag(diag::err_drv_invalid_riscv_arch_name) 303 << MArch << "first letter should be 'e', 'i' or 'g'"; 304 return false; 305 case 'e': { 306 StringRef Error; 307 // Currently LLVM does not support 'e'. 308 // Extension 'e' is not allowed in rv64. 309 if (HasRV64) 310 Error = "standard user-level extension 'e' requires 'rv32'"; 311 else 312 Error = "unsupported standard user-level extension 'e'"; 313 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error; 314 return false; 315 } 316 case 'i': 317 break; 318 case 'g': 319 // g = imafd 320 StdExts = StdExts.drop_front(4); 321 Features.push_back("+m"); 322 Features.push_back("+a"); 323 Features.push_back("+f"); 324 Features.push_back("+d"); 325 HasF = true; 326 HasD = true; 327 break; 328 } 329 330 // Skip rvxxx 331 StringRef Exts = MArch.substr(5); 332 333 // Remove multi-letter standard extensions, non-standard extensions and 334 // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes. 335 // Parse them at the end. 336 // Find the very first occurrence of 's', 'x' or 'z'. 337 StringRef OtherExts; 338 size_t Pos = Exts.find_first_of("zsx"); 339 if (Pos != StringRef::npos) { 340 OtherExts = Exts.substr(Pos); 341 Exts = Exts.substr(0, Pos); 342 } 343 344 std::string Major, Minor; 345 if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts, 346 Major, Minor)) 347 return false; 348 349 // Consume the base ISA version number and any '_' between rvxxx and the 350 // first extension 351 Exts = Exts.drop_front(Major.size()); 352 if (!Minor.empty()) 353 Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/); 354 Exts.consume_front("_"); 355 356 // TODO: Use version number when setting target features 357 358 auto StdExtsItr = StdExts.begin(); 359 auto StdExtsEnd = StdExts.end(); 360 361 for (auto I = Exts.begin(), E = Exts.end(); I != E; ) { 362 char c = *I; 363 364 // Check ISA extensions are specified in the canonical order. 365 while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) 366 ++StdExtsItr; 367 368 if (StdExtsItr == StdExtsEnd) { 369 // Either c contains a valid extension but it was not given in 370 // canonical order or it is an invalid extension. 371 StringRef Error; 372 if (StdExts.contains(c)) 373 Error = "standard user-level extension not given in canonical order"; 374 else 375 Error = "invalid standard user-level extension"; 376 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 377 << MArch << Error << std::string(1, c); 378 return false; 379 } 380 381 // Move to next char to prevent repeated letter. 382 ++StdExtsItr; 383 384 std::string Next, Major, Minor; 385 if (std::next(I) != E) 386 Next = std::string(std::next(I), E); 387 if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major, 388 Minor)) 389 return false; 390 391 // The order is OK, then push it into features. 392 // TODO: Use version number when setting target features 393 switch (c) { 394 default: 395 // Currently LLVM supports only "mafdc". 396 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 397 << MArch << "unsupported standard user-level extension" 398 << std::string(1, c); 399 return false; 400 case 'm': 401 Features.push_back("+m"); 402 break; 403 case 'a': 404 Features.push_back("+a"); 405 break; 406 case 'f': 407 Features.push_back("+f"); 408 HasF = true; 409 break; 410 case 'd': 411 Features.push_back("+d"); 412 HasD = true; 413 break; 414 case 'c': 415 Features.push_back("+c"); 416 break; 417 case 'b': 418 Features.push_back("+experimental-b"); 419 Features.push_back("+experimental-zba"); 420 Features.push_back("+experimental-zbb"); 421 Features.push_back("+experimental-zbc"); 422 Features.push_back("+experimental-zbe"); 423 Features.push_back("+experimental-zbf"); 424 Features.push_back("+experimental-zbm"); 425 Features.push_back("+experimental-zbp"); 426 Features.push_back("+experimental-zbr"); 427 Features.push_back("+experimental-zbs"); 428 Features.push_back("+experimental-zbt"); 429 break; 430 case 'v': 431 Features.push_back("+experimental-v"); 432 Features.push_back("+experimental-zvamo"); 433 Features.push_back("+experimental-zvlsseg"); 434 break; 435 } 436 437 // Consume full extension name and version, including any optional '_' 438 // between this extension and the next 439 ++I; 440 I += Major.size(); 441 if (Minor.size()) 442 I += Minor.size() + 1 /*'p'*/; 443 if (*I == '_') 444 ++I; 445 } 446 447 // Dependency check. 448 // It's illegal to specify the 'd' (double-precision floating point) 449 // extension without also specifying the 'f' (single precision 450 // floating-point) extension. 451 if (HasD && !HasF) { 452 D.Diag(diag::err_drv_invalid_riscv_arch_name) 453 << MArch << "d requires f extension to also be specified"; 454 return false; 455 } 456 457 // Additional dependency checks. 458 // TODO: The 'q' extension requires rv64. 459 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. 460 461 // Handle all other types of extensions. 462 getExtensionFeatures(D, Args, Features, MArch, OtherExts); 463 464 return true; 465 } 466 467 // Get features except standard extension feature 468 static void getRISCFeaturesFromMcpu(const Driver &D, const llvm::Triple &Triple, 469 const llvm::opt::ArgList &Args, 470 const llvm::opt::Arg *A, StringRef Mcpu, 471 std::vector<StringRef> &Features) { 472 bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64); 473 llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu); 474 if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) || 475 !llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) { 476 D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); 477 } 478 } 479 480 void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, 481 const ArgList &Args, 482 std::vector<StringRef> &Features) { 483 StringRef MArch = getRISCVArch(Args, Triple); 484 485 if (!getArchFeatures(D, MArch, Features, Args)) 486 return; 487 488 // If users give march and mcpu, get std extension feature from MArch 489 // and other features (ex. mirco architecture feature) from mcpu 490 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 491 getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features); 492 493 // Handle features corresponding to "-ffixed-X" options 494 if (Args.hasArg(options::OPT_ffixed_x1)) 495 Features.push_back("+reserve-x1"); 496 if (Args.hasArg(options::OPT_ffixed_x2)) 497 Features.push_back("+reserve-x2"); 498 if (Args.hasArg(options::OPT_ffixed_x3)) 499 Features.push_back("+reserve-x3"); 500 if (Args.hasArg(options::OPT_ffixed_x4)) 501 Features.push_back("+reserve-x4"); 502 if (Args.hasArg(options::OPT_ffixed_x5)) 503 Features.push_back("+reserve-x5"); 504 if (Args.hasArg(options::OPT_ffixed_x6)) 505 Features.push_back("+reserve-x6"); 506 if (Args.hasArg(options::OPT_ffixed_x7)) 507 Features.push_back("+reserve-x7"); 508 if (Args.hasArg(options::OPT_ffixed_x8)) 509 Features.push_back("+reserve-x8"); 510 if (Args.hasArg(options::OPT_ffixed_x9)) 511 Features.push_back("+reserve-x9"); 512 if (Args.hasArg(options::OPT_ffixed_x10)) 513 Features.push_back("+reserve-x10"); 514 if (Args.hasArg(options::OPT_ffixed_x11)) 515 Features.push_back("+reserve-x11"); 516 if (Args.hasArg(options::OPT_ffixed_x12)) 517 Features.push_back("+reserve-x12"); 518 if (Args.hasArg(options::OPT_ffixed_x13)) 519 Features.push_back("+reserve-x13"); 520 if (Args.hasArg(options::OPT_ffixed_x14)) 521 Features.push_back("+reserve-x14"); 522 if (Args.hasArg(options::OPT_ffixed_x15)) 523 Features.push_back("+reserve-x15"); 524 if (Args.hasArg(options::OPT_ffixed_x16)) 525 Features.push_back("+reserve-x16"); 526 if (Args.hasArg(options::OPT_ffixed_x17)) 527 Features.push_back("+reserve-x17"); 528 if (Args.hasArg(options::OPT_ffixed_x18)) 529 Features.push_back("+reserve-x18"); 530 if (Args.hasArg(options::OPT_ffixed_x19)) 531 Features.push_back("+reserve-x19"); 532 if (Args.hasArg(options::OPT_ffixed_x20)) 533 Features.push_back("+reserve-x20"); 534 if (Args.hasArg(options::OPT_ffixed_x21)) 535 Features.push_back("+reserve-x21"); 536 if (Args.hasArg(options::OPT_ffixed_x22)) 537 Features.push_back("+reserve-x22"); 538 if (Args.hasArg(options::OPT_ffixed_x23)) 539 Features.push_back("+reserve-x23"); 540 if (Args.hasArg(options::OPT_ffixed_x24)) 541 Features.push_back("+reserve-x24"); 542 if (Args.hasArg(options::OPT_ffixed_x25)) 543 Features.push_back("+reserve-x25"); 544 if (Args.hasArg(options::OPT_ffixed_x26)) 545 Features.push_back("+reserve-x26"); 546 if (Args.hasArg(options::OPT_ffixed_x27)) 547 Features.push_back("+reserve-x27"); 548 if (Args.hasArg(options::OPT_ffixed_x28)) 549 Features.push_back("+reserve-x28"); 550 if (Args.hasArg(options::OPT_ffixed_x29)) 551 Features.push_back("+reserve-x29"); 552 if (Args.hasArg(options::OPT_ffixed_x30)) 553 Features.push_back("+reserve-x30"); 554 if (Args.hasArg(options::OPT_ffixed_x31)) 555 Features.push_back("+reserve-x31"); 556 557 // FreeBSD local, because ld.lld doesn't support relaxations 558 // -mno-relax is default, unless -mrelax is specified. 559 if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) 560 Features.push_back("+relax"); 561 else 562 Features.push_back("-relax"); 563 564 // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is 565 // specified. 566 if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) 567 Features.push_back("+save-restore"); 568 else 569 Features.push_back("-save-restore"); 570 571 // Now add any that the user explicitly requested on the command line, 572 // which may override the defaults. 573 handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group); 574 } 575 576 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { 577 assert((Triple.getArch() == llvm::Triple::riscv32 || 578 Triple.getArch() == llvm::Triple::riscv64) && 579 "Unexpected triple"); 580 581 // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not 582 // configured using `--with-abi=`, then the logic for the default choice is 583 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. 584 // 585 // The logic used in GCC 9.2.0 is the following, in order: 586 // 1. Explicit choices using `--with-abi=` 587 // 2. A default based on `--with-arch=`, if provided 588 // 3. A default based on the target triple's arch 589 // 590 // The logic in config.gcc is a little circular but it is not inconsistent. 591 // 592 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 593 // and `-mabi=` respectively instead. 594 // 595 // In order to make chosing logic more clear, Clang uses the following logic, 596 // in order: 597 // 1. Explicit choices using `-mabi=` 598 // 2. A default based on the architecture as determined by getRISCVArch 599 // 3. Choose a default based on the triple 600 601 // 1. If `-mabi=` is specified, use it. 602 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) 603 return A->getValue(); 604 605 // 2. Choose a default based on the target architecture. 606 // 607 // rv32g | rv32*d -> ilp32d 608 // rv32e -> ilp32e 609 // rv32* -> ilp32 610 // rv64g | rv64*d -> lp64d 611 // rv64* -> lp64 612 StringRef MArch = getRISCVArch(Args, Triple); 613 614 if (MArch.startswith_lower("rv32")) { 615 // FIXME: parse `March` to find `D` extension properly 616 if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv32g")) 617 return "ilp32d"; 618 else if (MArch.startswith_lower("rv32e")) 619 return "ilp32e"; 620 else 621 return "ilp32"; 622 } else if (MArch.startswith_lower("rv64")) { 623 // FIXME: parse `March` to find `D` extension properly 624 if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv64g")) 625 return "lp64d"; 626 else 627 return "lp64"; 628 } 629 630 // 3. Choose a default based on the triple 631 // 632 // We deviate from GCC's defaults here: 633 // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only. 634 // - On all other OSs we use the double floating point calling convention. 635 if (Triple.getArch() == llvm::Triple::riscv32) { 636 if (Triple.getOS() == llvm::Triple::UnknownOS) 637 return "ilp32"; 638 else 639 return "ilp32d"; 640 } else { 641 if (Triple.getOS() == llvm::Triple::UnknownOS) 642 return "lp64"; 643 else 644 return "lp64d"; 645 } 646 } 647 648 StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args, 649 const llvm::Triple &Triple) { 650 assert((Triple.getArch() == llvm::Triple::riscv32 || 651 Triple.getArch() == llvm::Triple::riscv64) && 652 "Unexpected triple"); 653 654 // GCC's logic around choosing a default `-march=` is complex. If GCC is not 655 // configured using `--with-arch=`, then the logic for the default choice is 656 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We 657 // deviate from GCC's default on additional `-mcpu` option (GCC does not 658 // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march` 659 // nor `-mabi` is specified. 660 // 661 // The logic used in GCC 9.2.0 is the following, in order: 662 // 1. Explicit choices using `--with-arch=` 663 // 2. A default based on `--with-abi=`, if provided 664 // 3. A default based on the target triple's arch 665 // 666 // The logic in config.gcc is a little circular but it is not inconsistent. 667 // 668 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 669 // and `-mabi=` respectively instead. 670 // 671 // Clang uses the following logic, in order: 672 // 1. Explicit choices using `-march=` 673 // 2. Based on `-mcpu` if the target CPU has a default ISA string 674 // 3. A default based on `-mabi`, if provided 675 // 4. A default based on the target triple's arch 676 // 677 // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc` 678 // instead of `rv{XLEN}gc` though they are (currently) equivalent. 679 680 // 1. If `-march=` is specified, use it. 681 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 682 return A->getValue(); 683 684 // 2. Get march (isa string) based on `-mcpu=` 685 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { 686 StringRef MArch = llvm::RISCV::getMArchFromMcpu(A->getValue()); 687 // Bypass if target cpu's default march is empty. 688 if (MArch != "") 689 return MArch; 690 } 691 692 // 3. Choose a default based on `-mabi=` 693 // 694 // ilp32e -> rv32e 695 // ilp32 | ilp32f | ilp32d -> rv32imafdc 696 // lp64 | lp64f | lp64d -> rv64imafdc 697 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { 698 StringRef MABI = A->getValue(); 699 700 if (MABI.equals_lower("ilp32e")) 701 return "rv32e"; 702 else if (MABI.startswith_lower("ilp32")) 703 return "rv32imafdc"; 704 else if (MABI.startswith_lower("lp64")) 705 return "rv64imafdc"; 706 } 707 708 // 4. Choose a default based on the triple 709 // 710 // We deviate from GCC's defaults here: 711 // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac` 712 // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`) 713 if (Triple.getArch() == llvm::Triple::riscv32) { 714 if (Triple.getOS() == llvm::Triple::UnknownOS) 715 return "rv32imac"; 716 else 717 return "rv32imafdc"; 718 } else { 719 if (Triple.getOS() == llvm::Triple::UnknownOS) 720 return "rv64imac"; 721 else 722 return "rv64imafdc"; 723 } 724 } 725