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