133965Sjdp//===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===// 2218822Sdim// 333965Sjdp// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 433965Sjdp// See https://llvm.org/LICENSE.txt for license information. 533965Sjdp// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 633965Sjdp// 733965Sjdp//===----------------------------------------------------------------------===// 833965Sjdp 933965Sjdp#include "RISCV.h" 1033965Sjdp#include "clang/Basic/CharInfo.h" 1133965Sjdp#include "clang/Driver/Driver.h" 1233965Sjdp#include "clang/Driver/DriverDiagnostic.h" 1333965Sjdp#include "clang/Driver/Options.h" 1433965Sjdp#include "llvm/Option/ArgList.h" 1533965Sjdp#include "llvm/ADT/Optional.h" 1633965Sjdp#include "llvm/Support/TargetParser.h" 1733965Sjdp#include "llvm/Support/raw_ostream.h" 1833965Sjdp#include "ToolChains/CommonArgs.h" 1933965Sjdp 2033965Sjdpusing namespace clang::driver; 21218822Sdimusing namespace clang::driver::tools; 22218822Sdimusing namespace clang; 2333965Sjdpusing namespace llvm::opt; 24218822Sdim 2533965Sjdpstatic StringRef getExtensionTypeDesc(StringRef Ext) { 2633965Sjdp if (Ext.startswith("sx")) 2733965Sjdp return "non-standard supervisor-level extension"; 2833965Sjdp if (Ext.startswith("s")) 2933965Sjdp return "standard supervisor-level extension"; 3033965Sjdp if (Ext.startswith("x")) 3133965Sjdp return "non-standard user-level extension"; 3233965Sjdp return StringRef(); 3333965Sjdp} 3433965Sjdp 3533965Sjdpstatic StringRef getExtensionType(StringRef Ext) { 3633965Sjdp if (Ext.startswith("sx")) 3733965Sjdp return "sx"; 3833965Sjdp if (Ext.startswith("s")) 39218822Sdim return "s"; 4033965Sjdp if (Ext.startswith("x")) 41218822Sdim return "x"; 42130561Sobrien return StringRef(); 4333965Sjdp} 4433965Sjdp 45218822Sdimstatic bool isSupportedExtension(StringRef Ext) { 4633965Sjdp // LLVM does not support "sx", "s" nor "x" extensions. 4733965Sjdp return false; 48218822Sdim} 49218822Sdim 50218822Sdim// Extensions may have a version number, and may be separated by 51218822Sdim// an underscore '_' e.g.: rv32i2_m2. 5233965Sjdp// Version number is divided into major and minor version numbers, 53218822Sdim// separated by a 'p'. If the minor version is 0 then 'p0' can be 5433965Sjdp// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 55218822Sdimstatic bool getExtensionVersion(const Driver &D, StringRef MArch, 56130561Sobrien StringRef Ext, StringRef In, 5733965Sjdp std::string &Major, std::string &Minor) { 58218822Sdim Major = In.take_while(isDigit); 5933965Sjdp In = In.substr(Major.size()); 6033965Sjdp if (Major.empty()) 61218822Sdim return true; 6233965Sjdp 6333965Sjdp if (In.consume_front("p")) { 6433965Sjdp Minor = In.take_while(isDigit); 6533965Sjdp In = In.substr(Major.size()); 66218822Sdim 6733965Sjdp // Expected 'p' to be followed by minor version number. 6833965Sjdp if (Minor.empty()) { 6933965Sjdp std::string Error = 7033965Sjdp "minor version number missing after 'p' for extension"; 7133965Sjdp D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 7233965Sjdp << MArch << Error << Ext; 7333965Sjdp return false; 74218822Sdim } 7533965Sjdp } 7633965Sjdp 77218822Sdim // TODO: Handle extensions with version number. 7833965Sjdp std::string Error = "unsupported version number " + Major; 7933965Sjdp if (!Minor.empty()) 8033965Sjdp Error += "." + Minor; 8133965Sjdp Error += " for extension"; 8233965Sjdp D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext; 8333965Sjdp 8433965Sjdp return false; 85130561Sobrien} 8633965Sjdp 8733965Sjdp// Handle other types of extensions other than the standard 8833965Sjdp// general purpose and standard user-level extensions. 8933965Sjdp// Parse the ISA string containing non-standard user-level 90218822Sdim// extensions, standard supervisor-level extensions and 9133965Sjdp// non-standard supervisor-level extensions. 9233965Sjdp// These extensions start with 'x', 's', 'sx' prefixes, follow a 93130561Sobrien// canonical order, might have a version number (major, minor) 9433965Sjdp// and are separated by a single underscore '_'. 95218822Sdim// Set the hardware features for the extensions that are supported. 9633965Sjdpstatic void getExtensionFeatures(const Driver &D, 9733965Sjdp const ArgList &Args, 9833965Sjdp std::vector<StringRef> &Features, 9933965Sjdp StringRef &MArch, StringRef &Exts) { 100218822Sdim if (Exts.empty()) 10133965Sjdp return; 10233965Sjdp 103130561Sobrien // Multi-letter extensions are seperated by a single underscore 10433965Sjdp // as described in RISC-V User-Level ISA V2.2. 10533965Sjdp SmallVector<StringRef, 8> Split; 10633965Sjdp Exts.split(Split, StringRef("_")); 10733965Sjdp 10833965Sjdp SmallVector<StringRef, 3> Prefix{"x", "s", "sx"}; 10933965Sjdp auto I = Prefix.begin(); 110218822Sdim auto E = Prefix.end(); 111218822Sdim 112218822Sdim SmallVector<StringRef, 8> AllExts; 113218822Sdim 114218822Sdim for (StringRef Ext : Split) { 115218822Sdim if (Ext.empty()) { 116218822Sdim D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 117218822Sdim << "extension name missing after separator '_'"; 118218822Sdim return; 119218822Sdim } 120218822Sdim 121218822Sdim StringRef Type = getExtensionType(Ext); 122218822Sdim StringRef Name(Ext.substr(Type.size())); 123218822Sdim StringRef Desc = getExtensionTypeDesc(Ext); 124218822Sdim 125218822Sdim if (Type.empty()) { 126218822Sdim D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 127218822Sdim << MArch << "invalid extension prefix" << Ext; 128218822Sdim return; 129218822Sdim } 130218822Sdim 131218822Sdim // Check ISA extensions are specified in the canonical order. 132218822Sdim while (I != E && *I != Type) 133218822Sdim ++I; 134218822Sdim 135218822Sdim if (I == E) { 136218822Sdim std::string Error = Desc; 137218822Sdim Error += " not given in canonical order"; 138218822Sdim D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 139218822Sdim << MArch << Error << Ext; 140218822Sdim return; 141218822Sdim } 142218822Sdim 14377298Sobrien // The order is OK, do not advance I to the next prefix 14433965Sjdp // to allow repeated extension type, e.g.: rv32ixabc_xdef. 14533965Sjdp 146130561Sobrien if (Name.empty()) { 14733965Sjdp std::string Error = Desc; 14833965Sjdp Error += " name missing after"; 14933965Sjdp D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 15033965Sjdp << MArch << Error << Ext; 15133965Sjdp return; 152218822Sdim } 15333965Sjdp 15433965Sjdp std::string Major, Minor; 15533965Sjdp auto Pos = Name.find_if(isDigit); 15633965Sjdp if (Pos != StringRef::npos) { 15733965Sjdp auto Next = Name.substr(Pos); 15833965Sjdp Name = Name.substr(0, Pos); 15933965Sjdp if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor)) 16033965Sjdp return; 16133965Sjdp } 162218822Sdim 16333965Sjdp // Check if duplicated extension. 16433965Sjdp if (llvm::is_contained(AllExts, Ext)) { 165130561Sobrien std::string Error = "duplicated "; 16633965Sjdp Error += Desc; 16733965Sjdp D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 16833965Sjdp << MArch << Error << Ext; 16933965Sjdp return; 170218822Sdim } 17133965Sjdp 17233965Sjdp // Extension format is correct, keep parsing the extensions. 173130561Sobrien // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 17433965Sjdp AllExts.push_back(Ext); 17533965Sjdp } 17633965Sjdp 17733965Sjdp // Set target features. 17833965Sjdp // TODO: Hardware features to be handled in Support/TargetParser.cpp. 179218822Sdim // TODO: Use version number when setting target features. 18033965Sjdp for (auto Ext : AllExts) { 18133965Sjdp if (!isSupportedExtension(Ext)) { 182130561Sobrien StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 18333965Sjdp std::string Error = "unsupported "; 18433965Sjdp Error += Desc; 18533965Sjdp D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 18633965Sjdp << MArch << Error << Ext; 18733965Sjdp return; 18833965Sjdp } 18933965Sjdp Features.push_back(Args.MakeArgString("+" + Ext)); 190218822Sdim } 19133965Sjdp} 19233965Sjdp 193130561Sobrien// Returns false if an error is diagnosed. 19433965Sjdpstatic bool getArchFeatures(const Driver &D, StringRef MArch, 19533965Sjdp std::vector<StringRef> &Features, 19633965Sjdp const ArgList &Args) { 19733965Sjdp // RISC-V ISA strings must be lowercase. 19833965Sjdp if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { 19933965Sjdp D.Diag(diag::err_drv_invalid_riscv_arch_name) 200218822Sdim << MArch << "string must be lowercase"; 20133965Sjdp return false; 20233965Sjdp } 203130561Sobrien 20433965Sjdp // ISA string must begin with rv32 or rv64. 20533965Sjdp if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || 20633965Sjdp (MArch.size() < 5)) { 20733965Sjdp D.Diag(diag::err_drv_invalid_riscv_arch_name) 20833965Sjdp << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}"; 20933965Sjdp return false; 210218822Sdim } 211218822Sdim 21233965Sjdp bool HasRV64 = MArch.startswith("rv64"); 21333965Sjdp 214130561Sobrien // The canonical order specified in ISA manual. 21533965Sjdp // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 21633965Sjdp StringRef StdExts = "mafdqlcbjtpvn"; 21733965Sjdp bool HasF = false, HasD = false; 21833965Sjdp char Baseline = MArch[4]; 21933965Sjdp 22033965Sjdp // First letter should be 'e', 'i' or 'g'. 22133965Sjdp switch (Baseline) { 22233965Sjdp default: 223218822Sdim D.Diag(diag::err_drv_invalid_riscv_arch_name) 224130561Sobrien << MArch << "first letter should be 'e', 'i' or 'g'"; 22577298Sobrien return false; 22633965Sjdp case 'e': { 22733965Sjdp StringRef Error; 228130561Sobrien // Currently LLVM does not support 'e'. 22933965Sjdp // Extension 'e' is not allowed in rv64. 23033965Sjdp if (HasRV64) 23133965Sjdp Error = "standard user-level extension 'e' requires 'rv32'"; 23233965Sjdp else 23333965Sjdp Error = "unsupported standard user-level extension 'e'"; 23433965Sjdp D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error; 23533965Sjdp return false; 23633965Sjdp } 23733965Sjdp case 'i': 23833965Sjdp break; 23933965Sjdp case 'g': 24033965Sjdp // g = imafd 24133965Sjdp StdExts = StdExts.drop_front(4); 24233965Sjdp Features.push_back("+m"); 24333965Sjdp Features.push_back("+a"); 24433965Sjdp Features.push_back("+f"); 24533965Sjdp 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 357void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, 358 const ArgList &Args, 359 std::vector<StringRef> &Features) { 360 StringRef MArch = getRISCVArch(Args, Triple); 361 362 if (!getArchFeatures(D, MArch, Features, Args)) 363 return; 364 365 // Handle features corresponding to "-ffixed-X" options 366 if (Args.hasArg(options::OPT_ffixed_x1)) 367 Features.push_back("+reserve-x1"); 368 if (Args.hasArg(options::OPT_ffixed_x2)) 369 Features.push_back("+reserve-x2"); 370 if (Args.hasArg(options::OPT_ffixed_x3)) 371 Features.push_back("+reserve-x3"); 372 if (Args.hasArg(options::OPT_ffixed_x4)) 373 Features.push_back("+reserve-x4"); 374 if (Args.hasArg(options::OPT_ffixed_x5)) 375 Features.push_back("+reserve-x5"); 376 if (Args.hasArg(options::OPT_ffixed_x6)) 377 Features.push_back("+reserve-x6"); 378 if (Args.hasArg(options::OPT_ffixed_x7)) 379 Features.push_back("+reserve-x7"); 380 if (Args.hasArg(options::OPT_ffixed_x8)) 381 Features.push_back("+reserve-x8"); 382 if (Args.hasArg(options::OPT_ffixed_x9)) 383 Features.push_back("+reserve-x9"); 384 if (Args.hasArg(options::OPT_ffixed_x10)) 385 Features.push_back("+reserve-x10"); 386 if (Args.hasArg(options::OPT_ffixed_x11)) 387 Features.push_back("+reserve-x11"); 388 if (Args.hasArg(options::OPT_ffixed_x12)) 389 Features.push_back("+reserve-x12"); 390 if (Args.hasArg(options::OPT_ffixed_x13)) 391 Features.push_back("+reserve-x13"); 392 if (Args.hasArg(options::OPT_ffixed_x14)) 393 Features.push_back("+reserve-x14"); 394 if (Args.hasArg(options::OPT_ffixed_x15)) 395 Features.push_back("+reserve-x15"); 396 if (Args.hasArg(options::OPT_ffixed_x16)) 397 Features.push_back("+reserve-x16"); 398 if (Args.hasArg(options::OPT_ffixed_x17)) 399 Features.push_back("+reserve-x17"); 400 if (Args.hasArg(options::OPT_ffixed_x18)) 401 Features.push_back("+reserve-x18"); 402 if (Args.hasArg(options::OPT_ffixed_x19)) 403 Features.push_back("+reserve-x19"); 404 if (Args.hasArg(options::OPT_ffixed_x20)) 405 Features.push_back("+reserve-x20"); 406 if (Args.hasArg(options::OPT_ffixed_x21)) 407 Features.push_back("+reserve-x21"); 408 if (Args.hasArg(options::OPT_ffixed_x22)) 409 Features.push_back("+reserve-x22"); 410 if (Args.hasArg(options::OPT_ffixed_x23)) 411 Features.push_back("+reserve-x23"); 412 if (Args.hasArg(options::OPT_ffixed_x24)) 413 Features.push_back("+reserve-x24"); 414 if (Args.hasArg(options::OPT_ffixed_x25)) 415 Features.push_back("+reserve-x25"); 416 if (Args.hasArg(options::OPT_ffixed_x26)) 417 Features.push_back("+reserve-x26"); 418 if (Args.hasArg(options::OPT_ffixed_x27)) 419 Features.push_back("+reserve-x27"); 420 if (Args.hasArg(options::OPT_ffixed_x28)) 421 Features.push_back("+reserve-x28"); 422 if (Args.hasArg(options::OPT_ffixed_x29)) 423 Features.push_back("+reserve-x29"); 424 if (Args.hasArg(options::OPT_ffixed_x30)) 425 Features.push_back("+reserve-x30"); 426 if (Args.hasArg(options::OPT_ffixed_x31)) 427 Features.push_back("+reserve-x31"); 428 429 // FreeBSD local, because ld.lld doesn't support relaxations 430 // -mno-relax is default, unless -mrelax is specified. 431 if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) 432 Features.push_back("+relax"); 433 else 434 Features.push_back("-relax"); 435 436 // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is 437 // specified... 438 if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) { 439 // ... but we don't support -msave-restore, so issue a warning. 440 D.Diag(diag::warn_drv_clang_unsupported) 441 << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args); 442 } 443 444 // Now add any that the user explicitly requested on the command line, 445 // which may override the defaults. 446 handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group); 447} 448 449StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { 450 assert((Triple.getArch() == llvm::Triple::riscv32 || 451 Triple.getArch() == llvm::Triple::riscv64) && 452 "Unexpected triple"); 453 454 // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not 455 // configured using `--with-abi=`, then the logic for the default choice is 456 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We 457 // deviate from GCC's default only on baremetal targets (UnknownOS) where 458 // neither `-march` nor `-mabi` is specified. 459 // 460 // The logic uses the following, in order: 461 // 1. Explicit choices using `--with-abi=` 462 // 2. A default based on `--with-arch=`, if provided 463 // 3. A default based on the target triple's arch 464 // 465 // The logic in config.gcc is a little circular but it is not inconsistent. 466 // 467 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 468 // and `-mabi=` respectively instead. 469 470 // 1. If `-mabi=` is specified, use it. 471 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) 472 return A->getValue(); 473 474 // 2. Choose a default based on `-march=` 475 // 476 // rv32g | rv32*d -> ilp32d 477 // rv32e -> ilp32e 478 // rv32* -> ilp32 479 // rv64g | rv64*d -> lp64d 480 // rv64* -> lp64 481 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 482 StringRef MArch = A->getValue(); 483 484 if (MArch.startswith_lower("rv32")) { 485 // FIXME: parse `March` to find `D` extension properly 486 if (MArch.substr(4).contains_lower("d") || 487 MArch.startswith_lower("rv32g")) 488 return "ilp32d"; 489 else if (MArch.startswith_lower("rv32e")) 490 return "ilp32e"; 491 else 492 return "ilp32"; 493 } else if (MArch.startswith_lower("rv64")) { 494 // FIXME: parse `March` to find `D` extension properly 495 if (MArch.substr(4).contains_lower("d") || 496 MArch.startswith_lower("rv64g")) 497 return "lp64d"; 498 else 499 return "lp64"; 500 } 501 } 502 503 // 3. Choose a default based on the triple 504 // 505 // We deviate from GCC's defaults here: 506 // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only. 507 // - On all other OSs we use the double floating point calling convention. 508 if (Triple.getArch() == llvm::Triple::riscv32) { 509 if (Triple.getOS() == llvm::Triple::UnknownOS) 510 return "ilp32"; 511 else 512 return "ilp32d"; 513 } else { 514 if (Triple.getOS() == llvm::Triple::UnknownOS) 515 return "lp64"; 516 else 517 return "lp64d"; 518 } 519} 520 521StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args, 522 const llvm::Triple &Triple) { 523 assert((Triple.getArch() == llvm::Triple::riscv32 || 524 Triple.getArch() == llvm::Triple::riscv64) && 525 "Unexpected triple"); 526 527 // GCC's logic around choosing a default `-march=` is complex. If GCC is not 528 // configured using `--with-arch=`, then the logic for the default choice is 529 // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We 530 // deviate from GCC's default only on baremetal targets (UnknownOS) where 531 // neither `-march` nor `-mabi` is specified. 532 // 533 // The logic uses the following, in order: 534 // 1. Explicit choices using `--with-arch=` 535 // 2. A default based on `--with-abi=`, if provided 536 // 3. A default based on the target triple's arch 537 // 538 // The logic in config.gcc is a little circular but it is not inconsistent. 539 // 540 // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=` 541 // and `-mabi=` respectively instead. 542 // 543 // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc` 544 // instead of `rv{XLEN}gc` though they are (currently) equivalent. 545 546 // 1. If `-march=` is specified, use it. 547 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) 548 return A->getValue(); 549 550 // 2. Choose a default based on `-mabi=` 551 // 552 // ilp32e -> rv32e 553 // ilp32 | ilp32f | ilp32d -> rv32imafdc 554 // lp64 | lp64f | lp64d -> rv64imafdc 555 if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { 556 StringRef MABI = A->getValue(); 557 558 if (MABI.equals_lower("ilp32e")) 559 return "rv32e"; 560 else if (MABI.startswith_lower("ilp32")) 561 return "rv32imafdc"; 562 else if (MABI.startswith_lower("lp64")) 563 return "rv64imafdc"; 564 } 565 566 // 3. Choose a default based on the triple 567 // 568 // We deviate from GCC's defaults here: 569 // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac` 570 // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`) 571 if (Triple.getArch() == llvm::Triple::riscv32) { 572 if (Triple.getOS() == llvm::Triple::UnknownOS) 573 return "rv32imac"; 574 else 575 return "rv32imafdc"; 576 } else { 577 if (Triple.getOS() == llvm::Triple::UnknownOS) 578 return "rv64imac"; 579 else 580 return "rv64imafdc"; 581 } 582} 583