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 void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, 450 const ArgList &Args, 451 std::vector<StringRef> &Features) { 452 StringRef MArch = getRISCVArch(Args, Triple); 453 454 if (!getArchFeatures(D, MArch, Features, Args)) 455 return; 456 457 // Handle features corresponding to "-ffixed-X" options 458 if (Args.hasArg(options::OPT_ffixed_x1)) 459 Features.push_back("+reserve-x1"); 460 if (Args.hasArg(options::OPT_ffixed_x2)) 461 Features.push_back("+reserve-x2"); 462 if (Args.hasArg(options::OPT_ffixed_x3)) 463 Features.push_back("+reserve-x3"); 464 if (Args.hasArg(options::OPT_ffixed_x4)) 465 Features.push_back("+reserve-x4"); 466 if (Args.hasArg(options::OPT_ffixed_x5)) 467 Features.push_back("+reserve-x5"); 468 if (Args.hasArg(options::OPT_ffixed_x6)) 469 Features.push_back("+reserve-x6"); 470 if (Args.hasArg(options::OPT_ffixed_x7)) 471 Features.push_back("+reserve-x7"); 472 if (Args.hasArg(options::OPT_ffixed_x8)) 473 Features.push_back("+reserve-x8"); 474 if (Args.hasArg(options::OPT_ffixed_x9)) 475 Features.push_back("+reserve-x9"); 476 if (Args.hasArg(options::OPT_ffixed_x10)) 477 Features.push_back("+reserve-x10"); 478 if (Args.hasArg(options::OPT_ffixed_x11)) 479 Features.push_back("+reserve-x11"); 480 if (Args.hasArg(options::OPT_ffixed_x12)) 481 Features.push_back("+reserve-x12"); 482 if (Args.hasArg(options::OPT_ffixed_x13)) 483 Features.push_back("+reserve-x13"); 484 if (Args.hasArg(options::OPT_ffixed_x14)) 485 Features.push_back("+reserve-x14"); 486 if (Args.hasArg(options::OPT_ffixed_x15)) 487 Features.push_back("+reserve-x15"); 488 if (Args.hasArg(options::OPT_ffixed_x16)) 489 Features.push_back("+reserve-x16"); 490 if (Args.hasArg(options::OPT_ffixed_x17)) 491 Features.push_back("+reserve-x17"); 492 if (Args.hasArg(options::OPT_ffixed_x18)) 493 Features.push_back("+reserve-x18"); 494 if (Args.hasArg(options::OPT_ffixed_x19)) 495 Features.push_back("+reserve-x19"); 496 if (Args.hasArg(options::OPT_ffixed_x20)) 497 Features.push_back("+reserve-x20"); 498 if (Args.hasArg(options::OPT_ffixed_x21)) 499 Features.push_back("+reserve-x21"); 500 if (Args.hasArg(options::OPT_ffixed_x22)) 501 Features.push_back("+reserve-x22"); 502 if (Args.hasArg(options::OPT_ffixed_x23)) 503 Features.push_back("+reserve-x23"); 504 if (Args.hasArg(options::OPT_ffixed_x24)) 505 Features.push_back("+reserve-x24"); 506 if (Args.hasArg(options::OPT_ffixed_x25)) 507 Features.push_back("+reserve-x25"); 508 if (Args.hasArg(options::OPT_ffixed_x26)) 509 Features.push_back("+reserve-x26"); 510 if (Args.hasArg(options::OPT_ffixed_x27)) 511 Features.push_back("+reserve-x27"); 512 if (Args.hasArg(options::OPT_ffixed_x28)) 513 Features.push_back("+reserve-x28"); 514 if (Args.hasArg(options::OPT_ffixed_x29)) 515 Features.push_back("+reserve-x29"); 516 if (Args.hasArg(options::OPT_ffixed_x30)) 517 Features.push_back("+reserve-x30"); 518 if (Args.hasArg(options::OPT_ffixed_x31)) 519 Features.push_back("+reserve-x31"); 520 521 // -mrelax is default, unless -mno-relax is specified. 522 if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) 523 Features.push_back("+relax"); 524 else 525 Features.push_back("-relax"); 526 527 // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is 528 // specified. 529 if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) 530 Features.push_back("+save-restore"); 531 else 532 Features.push_back("-save-restore"); 533 534 // Now add any that the user explicitly requested on the command line, 535 // which may override the defaults. 536 handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group); 537 } 538 539 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { 540 assert((Triple.getArch() == llvm::Triple::riscv32 || 541 Triple.getArch() == llvm::Triple::riscv64) && 542 "Unexpected triple"); 543 544 // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not 545 // configured using `--with-abi=`, then the logic for the default choice is 546 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We 547 // deviate from GCC's default only on baremetal targets (UnknownOS) where 548 // neither `-march` nor `-mabi` is specified. 549 // 550 // The logic uses the following, in order: 551 // 1. Explicit choices using `--with-abi=` 552 // 2. A default based on `--with-arch=`, if provided 553 // 3. A default based on the target triple's arch 554 // 555 // The logic in config.gcc is a little circular but it is not inconsistent. 556 // 557 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 558 // and `-mabi=` respectively instead. 559 560 // 1. If `-mabi=` is specified, use it. 561 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) 562 return A->getValue(); 563 564 // 2. Choose a default based on `-march=` 565 // 566 // rv32g | rv32*d -> ilp32d 567 // rv32e -> ilp32e 568 // rv32* -> ilp32 569 // rv64g | rv64*d -> lp64d 570 // rv64* -> lp64 571 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 572 StringRef MArch = A->getValue(); 573 574 if (MArch.startswith_lower("rv32")) { 575 // FIXME: parse `March` to find `D` extension properly 576 if (MArch.substr(4).contains_lower("d") || 577 MArch.startswith_lower("rv32g")) 578 return "ilp32d"; 579 else if (MArch.startswith_lower("rv32e")) 580 return "ilp32e"; 581 else 582 return "ilp32"; 583 } else if (MArch.startswith_lower("rv64")) { 584 // FIXME: parse `March` to find `D` extension properly 585 if (MArch.substr(4).contains_lower("d") || 586 MArch.startswith_lower("rv64g")) 587 return "lp64d"; 588 else 589 return "lp64"; 590 } 591 } 592 593 // 3. Choose a default based on the triple 594 // 595 // We deviate from GCC's defaults here: 596 // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only. 597 // - On all other OSs we use the double floating point calling convention. 598 if (Triple.getArch() == llvm::Triple::riscv32) { 599 if (Triple.getOS() == llvm::Triple::UnknownOS) 600 return "ilp32"; 601 else 602 return "ilp32d"; 603 } else { 604 if (Triple.getOS() == llvm::Triple::UnknownOS) 605 return "lp64"; 606 else 607 return "lp64d"; 608 } 609 } 610 611 StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args, 612 const llvm::Triple &Triple) { 613 assert((Triple.getArch() == llvm::Triple::riscv32 || 614 Triple.getArch() == llvm::Triple::riscv64) && 615 "Unexpected triple"); 616 617 // GCC's logic around choosing a default `-march=` is complex. If GCC is not 618 // configured using `--with-arch=`, then the logic for the default choice is 619 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We 620 // deviate from GCC's default only on baremetal targets (UnknownOS) where 621 // neither `-march` nor `-mabi` is specified. 622 // 623 // The logic uses the following, in order: 624 // 1. Explicit choices using `--with-arch=` 625 // 2. A default based on `--with-abi=`, if provided 626 // 3. A default based on the target triple's arch 627 // 628 // The logic in config.gcc is a little circular but it is not inconsistent. 629 // 630 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 631 // and `-mabi=` respectively instead. 632 // 633 // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc` 634 // instead of `rv{XLEN}gc` though they are (currently) equivalent. 635 636 // 1. If `-march=` is specified, use it. 637 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 638 return A->getValue(); 639 640 // 2. Choose a default based on `-mabi=` 641 // 642 // ilp32e -> rv32e 643 // ilp32 | ilp32f | ilp32d -> rv32imafdc 644 // lp64 | lp64f | lp64d -> rv64imafdc 645 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { 646 StringRef MABI = A->getValue(); 647 648 if (MABI.equals_lower("ilp32e")) 649 return "rv32e"; 650 else if (MABI.startswith_lower("ilp32")) 651 return "rv32imafdc"; 652 else if (MABI.startswith_lower("lp64")) 653 return "rv64imafdc"; 654 } 655 656 // 3. Choose a default based on the triple 657 // 658 // We deviate from GCC's defaults here: 659 // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac` 660 // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`) 661 if (Triple.getArch() == llvm::Triple::riscv32) { 662 if (Triple.getOS() == llvm::Triple::UnknownOS) 663 return "rv32imac"; 664 else 665 return "rv32imafdc"; 666 } else { 667 if (Triple.getOS() == llvm::Triple::UnknownOS) 668 return "rv64imac"; 669 else 670 return "rv64imafdc"; 671 } 672 } 673